summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Goddard <michael.goddard@nokia.com>2011-06-29 13:38:46 +1000
committerMichael Goddard <michael.goddard@nokia.com>2011-06-29 13:38:46 +1000
commit2a34e88c1e1ced28e75c487cd13402e1c9cf9fa3 (patch)
treee6c1b770c5c47212792a1f9344fa034ea3e54c44
Initial copy of QtMultimediaKit.
Comes from original repo, with SHA1: 2c82d5611655e5967f5c5095af50c0991c4378b2
-rwxr-xr-xbin/pathhelper59
-rw-r--r--config.tests/FmTxClient/FmTxClient.pro10
-rw-r--r--config.tests/FmTxClient/main.cpp49
-rw-r--r--config.tests/audiorouting_s60/audiorouting_s60.pro9
-rw-r--r--config.tests/audiorouting_s60/main.cpp46
-rw-r--r--config.tests/directshow/directshow.pro9
-rw-r--r--config.tests/directshow/main.cpp49
-rw-r--r--config.tests/evr/evr.pro6
-rw-r--r--config.tests/evr/main.cpp47
-rw-r--r--config.tests/gstreamer-appsrc/gstreamer-appsrc.pro19
-rw-r--r--config.tests/gstreamer-appsrc/main.cpp49
-rw-r--r--config.tests/gstreamer-photography/gstreamer-photography.pro19
-rw-r--r--config.tests/gstreamer-photography/main.cpp50
-rw-r--r--config.tests/make/make.pro11
-rw-r--r--config.tests/mmf_http_cookies/main.cpp49
-rw-r--r--config.tests/mmf_http_cookies/mmf_http_cookies.pro7
-rw-r--r--config.tests/openmaxal_symbian/main.cpp45
-rw-r--r--config.tests/openmaxal_symbian/openmaxal_symbian.pro7
-rw-r--r--config.tests/pulseaudio/pulseaudio.cpp55
-rw-r--r--config.tests/pulseaudio/pulseaudio.pro8
-rw-r--r--config.tests/radioutility_s60/main.cpp46
-rw-r--r--config.tests/radioutility_s60/radioutility_s60.pro9
-rw-r--r--config.tests/surfaces_s60/main.cpp48
-rw-r--r--config.tests/surfaces_s60/surfaces_s60.pro8
-rw-r--r--config.tests/symbian_camera_camautofocus/main.cpp45
-rw-r--r--config.tests/symbian_camera_camautofocus/symbian_camera_camautofocus.pro7
-rw-r--r--config.tests/symbian_camera_devvideorecord/main.cpp45
-rw-r--r--config.tests/symbian_camera_devvideorecord/symbian_camera_devvideorecord.pro7
-rw-r--r--config.tests/symbian_camera_ecamadvsettings/main.cpp45
-rw-r--r--config.tests/symbian_camera_ecamadvsettings/symbian_camera_ecamadvsettings.pro7
-rw-r--r--config.tests/symbian_camera_snapshot/main.cpp45
-rw-r--r--config.tests/symbian_camera_snapshot/symbian_camera_snapshot.pro7
-rwxr-xr-xconfig.tests/tools/which.test40
-rw-r--r--config.tests/tunerlib_s60/main.cpp46
-rw-r--r--config.tests/tunerlib_s60/tunerlib_s60.pro9
-rw-r--r--config.tests/wmp/main.cpp47
-rw-r--r--config.tests/wmp/wmp.pro9
-rw-r--r--config.tests/wmsdk/main.cpp47
-rw-r--r--config.tests/wmsdk/wmsdk.pro6
-rwxr-xr-xconfigure443
-rw-r--r--configure.bat806
-rw-r--r--demos/demos.pri10
-rw-r--r--demos/demos.pro7
-rw-r--r--demos/player/main.cpp70
-rw-r--r--demos/player/player.cpp434
-rw-r--r--demos/player/player.h123
-rw-r--r--demos/player/player.pro30
-rw-r--r--demos/player/playercontrols.cpp211
-rw-r--r--demos/player/playercontrols.h101
-rw-r--r--demos/player/playlistmodel.cpp159
-rw-r--r--demos/player/playlistmodel.h90
-rw-r--r--demos/player/videowidget.cpp95
-rw-r--r--demos/player/videowidget.h59
-rw-r--r--doc/config/compat.qdocconf31
-rw-r--r--doc/config/images/arrow_down.pngbin0 -> 177 bytes
-rwxr-xr-xdoc/config/images/bg_l.pngbin0 -> 100 bytes
-rwxr-xr-xdoc/config/images/bg_l_blank.pngbin0 -> 84 bytes
-rw-r--r--doc/config/images/bg_ll_blank.pngbin0 -> 320 bytes
-rwxr-xr-xdoc/config/images/bg_r.pngbin0 -> 96 bytes
-rw-r--r--doc/config/images/bg_ul_blank.pngbin0 -> 304 bytes
-rwxr-xr-xdoc/config/images/box_bg.pngbin0 -> 89 bytes
-rwxr-xr-xdoc/config/images/breadcrumb.pngbin0 -> 134 bytes
-rw-r--r--doc/config/images/bullet_dn.pngbin0 -> 230 bytes
-rwxr-xr-xdoc/config/images/bullet_gt.pngbin0 -> 124 bytes
-rwxr-xr-xdoc/config/images/bullet_sq.pngbin0 -> 74 bytes
-rw-r--r--doc/config/images/bullet_up.pngbin0 -> 210 bytes
-rwxr-xr-xdoc/config/images/feedbackground.pngbin0 -> 263 bytes
-rw-r--r--doc/config/images/header_bg.pngbin0 -> 114 bytes
-rwxr-xr-xdoc/config/images/horBar.pngbin0 -> 2807 bytes
-rw-r--r--doc/config/images/page.pngbin0 -> 3102 bytes
-rwxr-xr-xdoc/config/images/page_bg.pngbin0 -> 84 bytes
-rw-r--r--doc/config/images/qt-logo.pngbin0 -> 5149 bytes
-rw-r--r--doc/config/images/spinner.gifbin0 -> 2037 bytes
-rwxr-xr-xdoc/config/images/sprites-combined.pngbin0 -> 65056 bytes
-rw-r--r--doc/config/macros.qdocconf37
-rw-r--r--doc/config/qt-cpp-ignore.qdocconf99
-rw-r--r--doc/config/qt-defines.qdocconf17
-rw-r--r--doc/config/qt-html-default-styles.qdocconf32
-rw-r--r--doc/config/qt-html-online-styles.qdocconf72
-rw-r--r--doc/config/qt-html-templates-online.qdocconf142
-rw-r--r--doc/config/qt-html-templates.qdocconf54
-rw-r--r--doc/config/qtmobility-cpp-ignore.qdocconf18
-rw-r--r--doc/config/qtmobility-ditaxml.qdocconf13
-rw-r--r--doc/config/qtmobility-online.qdocconf2
-rw-r--r--doc/config/qtmobility-project.qdocconf142
-rw-r--r--doc/config/qtmobility.qdocconf2
-rw-r--r--doc/config/scripts/functions.js258
-rw-r--r--doc/config/scripts/jquery.js152
-rw-r--r--doc/config/scripts/narrow.js133
-rw-r--r--doc/config/scripts/superfish.js121
-rw-r--r--doc/config/style/narrow.css270
-rw-r--r--doc/config/style/offline.css675
-rw-r--r--doc/config/style/style.css1627
-rw-r--r--doc/config/style/style_ie6.css54
-rw-r--r--doc/config/style/style_ie7.css19
-rw-r--r--doc/config/style/style_ie8.css0
-rw-r--r--doc/config/style/superfish.css51
-rw-r--r--doc/doc.pri31
-rw-r--r--doc/doc.pro8
-rw-r--r--doc/src/camera.qdoc188
-rw-r--r--doc/src/classic.css284
-rw-r--r--doc/src/examples/audiodevices.qdoc42
-rw-r--r--doc/src/examples/audiorecorder.qdoc68
-rw-r--r--doc/src/examples/camera.qdoc79
-rw-r--r--doc/src/examples/declarative-camera.qdoc69
-rw-r--r--doc/src/examples/hapticsplayer.qdoc73
-rw-r--r--doc/src/examples/player.qdoc95
-rw-r--r--doc/src/examples/slideshow.qdoc75
-rw-r--r--doc/src/images/annotatedurl.pngbin0 -> 40129 bytes
-rw-r--r--doc/src/images/audiodevices.pngbin0 -> 37896 bytes
-rw-r--r--doc/src/images/camera-example.pngbin0 -> 13647 bytes
-rw-r--r--doc/src/images/codeless.pngbin0 -> 4636 bytes
-rw-r--r--doc/src/images/qml-camera.pngbin0 -> 28409 bytes
-rw-r--r--doc/src/images/slideshow-img1.pngbin0 -> 596624 bytes
-rw-r--r--doc/src/legal/3rdparty.qdoc300
-rw-r--r--doc/src/legal/editions.qdoc64
-rw-r--r--doc/src/legal/gpl.qdoc67
-rw-r--r--doc/src/legal/opensourceedition.qdoc91
-rw-r--r--doc/src/legal/trademarks.qdoc77
-rw-r--r--doc/src/multimedia.qdoc470
-rw-r--r--doc/src/plugins/qml-multimedia.qdoc291
-rw-r--r--doc/src/snippets/multimedia-snippets/audio.cpp210
-rw-r--r--doc/src/snippets/multimedia-snippets/audiorecorder.cpp215
-rw-r--r--doc/src/snippets/multimedia-snippets/camera.cpp82
-rw-r--r--doc/src/snippets/multimedia-snippets/media.cpp236
-rw-r--r--doc/src/snippets/multimedia-snippets/multimedia-snippets.pro21
-rw-r--r--doc/src/snippets/multimedia-snippets/player.cpp317
-rw-r--r--doc/src/snippets/multimedia-snippets/soundeffect.qml63
-rw-r--r--doc/src/snippets/multimedia-snippets/video.cpp129
-rw-r--r--doc/src/snippets/snippets.pro3
-rw-r--r--examples/audiodevices/audiodevices.cpp312
-rw-r--r--examples/audiodevices/audiodevices.h83
-rw-r--r--examples/audiodevices/audiodevices.pro21
-rw-r--r--examples/audiodevices/audiodevicesbase.ui399
-rw-r--r--examples/audioinput/audioinput.cpp366
-rw-r--r--examples/audioinput/audioinput.h139
-rw-r--r--examples/audioinput/audioinput.pro16
-rw-r--r--examples/audioinput/main.cpp54
-rw-r--r--examples/audiooutput/audiooutput.cpp314
-rw-r--r--examples/audiooutput/audiooutput.h122
-rw-r--r--examples/audiooutput/audiooutput.pro15
-rw-r--r--examples/audiooutput/main.cpp55
-rw-r--r--examples/audiorecorder/audiorecorder.cpp225
-rw-r--r--examples/audiorecorder/audiorecorder.h88
-rw-r--r--examples/audiorecorder/audiorecorder.pro29
-rw-r--r--examples/audiorecorder/audiorecorder.ui250
-rw-r--r--examples/audiorecorder/audiorecorder_small.ui266
-rw-r--r--examples/audiorecorder/main.cpp57
-rw-r--r--examples/camera/camera.cpp440
-rw-r--r--examples/camera/camera.h126
-rw-r--r--examples/camera/camera.pro33
-rw-r--r--examples/camera/camera.ui492
-rw-r--r--examples/camera/camerakeyevent_symbian/camerakeyevent_symbian.cpp101
-rw-r--r--examples/camera/camerakeyevent_symbian/camerakeyevent_symbian.h87
-rw-r--r--examples/camera/camerakeyevent_symbian/camerakeyevent_symbian.pri7
-rw-r--r--examples/camera/imagesettings.cpp126
-rw-r--r--examples/camera/imagesettings.h84
-rw-r--r--examples/camera/imagesettings.ui123
-rw-r--r--examples/camera/main.cpp72
-rw-r--r--examples/camera/videosettings.cpp191
-rw-r--r--examples/camera/videosettings.h84
-rw-r--r--examples/camera/videosettings.ui211
-rw-r--r--examples/declarative-camera/CameraButton.qml71
-rw-r--r--examples/declarative-camera/CameraPropertyButton.qml107
-rw-r--r--examples/declarative-camera/CameraPropertyPopup.qml122
-rw-r--r--examples/declarative-camera/CaptureControls.qml237
-rw-r--r--examples/declarative-camera/ExposureCompensationButton.qml85
-rw-r--r--examples/declarative-camera/FlickableList.qml128
-rw-r--r--examples/declarative-camera/FocusButton.qml62
-rw-r--r--examples/declarative-camera/PhotoPreview.qml62
-rw-r--r--examples/declarative-camera/ZoomControl.qml118
-rw-r--r--examples/declarative-camera/camerakeyevent_symbian/camerakeyevent_symbian.cpp101
-rw-r--r--examples/declarative-camera/camerakeyevent_symbian/camerakeyevent_symbian.h87
-rw-r--r--examples/declarative-camera/camerakeyevent_symbian/camerakeyevent_symbian.pri7
-rw-r--r--examples/declarative-camera/declarative-camera.pro31
-rw-r--r--examples/declarative-camera/declarative-camera.qml116
-rw-r--r--examples/declarative-camera/declarative-camera.qmlproject18
-rw-r--r--examples/declarative-camera/declarative-camera.qrc28
-rw-r--r--examples/declarative-camera/images/camera_auto_mode.pngbin0 -> 778 bytes
-rw-r--r--examples/declarative-camera/images/camera_camera_setting.pngbin0 -> 717 bytes
-rw-r--r--examples/declarative-camera/images/camera_flash_auto.pngbin0 -> 1119 bytes
-rw-r--r--examples/declarative-camera/images/camera_flash_fill.pngbin0 -> 610 bytes
-rw-r--r--examples/declarative-camera/images/camera_flash_off.pngbin0 -> 717 bytes
-rw-r--r--examples/declarative-camera/images/camera_flash_redeye.pngbin0 -> 945 bytes
-rw-r--r--examples/declarative-camera/images/camera_white_balance_cloudy.pngbin0 -> 625 bytes
-rw-r--r--examples/declarative-camera/images/camera_white_balance_flourescent.pngbin0 -> 554 bytes
-rw-r--r--examples/declarative-camera/images/camera_white_balance_incandescent.pngbin0 -> 600 bytes
-rw-r--r--examples/declarative-camera/images/camera_white_balance_sunny.pngbin0 -> 587 bytes
-rw-r--r--examples/declarative-camera/images/toolbutton.pngbin0 -> 2550 bytes
-rw-r--r--examples/declarative-camera/images/toolbutton.sci5
-rw-r--r--examples/declarative-camera/qmlcamera.cpp95
-rw-r--r--examples/examples.pro21
-rw-r--r--examples/main.cpp58
-rw-r--r--examples/radio/main.cpp57
-rw-r--r--examples/radio/radio.cpp179
-rw-r--r--examples/radio/radio.h84
-rw-r--r--examples/radio/radio.pro21
-rw-r--r--examples/slideshow/main.cpp57
-rw-r--r--examples/slideshow/slideshow.cpp215
-rw-r--r--examples/slideshow/slideshow.h87
-rw-r--r--examples/slideshow/slideshow.pro19
-rw-r--r--examples/videographicsitem/main.cpp54
-rw-r--r--examples/videographicsitem/videographicsitem.pro19
-rw-r--r--examples/videographicsitem/videoitem.cpp144
-rw-r--r--examples/videographicsitem/videoitem.h78
-rw-r--r--examples/videographicsitem/videoplayer.cpp174
-rw-r--r--examples/videographicsitem/videoplayer.h85
-rw-r--r--examples/videowidget/main.cpp53
-rw-r--r--examples/videowidget/videoplayer.cpp143
-rw-r--r--examples/videowidget/videoplayer.h77
-rw-r--r--examples/videowidget/videowidget.cpp114
-rw-r--r--examples/videowidget/videowidget.h75
-rw-r--r--examples/videowidget/videowidget.pro22
-rw-r--r--examples/videowidget/videowidgetsurface.cpp176
-rw-r--r--examples/videowidget/videowidgetsurface.h80
-rw-r--r--features/basic_examples_setup.pri59
-rw-r--r--features/deploy.pri61
-rw-r--r--features/mobility.prf.template130
-rw-r--r--modules/qt_multimediakit.pri17
-rw-r--r--qtmultimediakit.pro29
-rw-r--r--src/harmattaninstalls/README19
-rw-r--r--src/harmattaninstalls/api92
-rw-r--r--src/harmattaninstalls/changelog178
-rw-r--r--src/harmattaninstalls/compat1
-rw-r--r--src/harmattaninstalls/control716
-rw-r--r--src/harmattaninstalls/docs2
-rw-r--r--src/harmattaninstalls/libqtm-contacts-tests.aegis13
-rw-r--r--src/harmattaninstalls/libqtm-doc.install1
-rw-r--r--src/harmattaninstalls/libqtm-examples.aegis54
-rw-r--r--src/harmattaninstalls/libqtm-examples.install100
-rw-r--r--src/harmattaninstalls/libqtm-multimedia-dev.install145
-rw-r--r--src/harmattaninstalls/libqtm-multimedia-tests.install32
-rw-r--r--src/harmattaninstalls/libqtm-multimedia.install8
-rw-r--r--src/harmattaninstalls/libqtm-systeminfo-tests.aegis10
-rw-r--r--src/harmattaninstalls/patches/series0
-rwxr-xr-xsrc/harmattaninstalls/rules110
-rwxr-xr-xsrc/harmattaninstalls/tests/install_tests201
-rw-r--r--src/harmattaninstalls/tests/testset.txt11
-rw-r--r--src/harmattaninstalls/tests/testsuite_footer.txt2
-rw-r--r--src/harmattaninstalls/tests/testsuite_header.txt4
-rw-r--r--src/imports/imports.pro5
-rw-r--r--src/imports/multimedia/multimedia.cpp85
-rw-r--r--src/imports/multimedia/multimedia.pro41
-rw-r--r--src/imports/multimedia/qdeclarativeaudio.cpp698
-rw-r--r--src/imports/multimedia/qdeclarativeaudio_p.h178
-rw-r--r--src/imports/multimedia/qdeclarativecamera.cpp1342
-rw-r--r--src/imports/multimedia/qdeclarativecamera_p.h302
-rw-r--r--src/imports/multimedia/qdeclarativecamerapreviewprovider.cpp97
-rw-r--r--src/imports/multimedia/qdeclarativecamerapreviewprovider_p.h76
-rw-r--r--src/imports/multimedia/qdeclarativemediabase.cpp567
-rw-r--r--src/imports/multimedia/qdeclarativemediabase_p.h187
-rw-r--r--src/imports/multimedia/qdeclarativemediametadata_p.h185
-rw-r--r--src/imports/multimedia/qdeclarativevideo.cpp951
-rw-r--r--src/imports/multimedia/qdeclarativevideo_p.h202
-rw-r--r--src/imports/multimedia/qmldir1
-rw-r--r--src/imports/qimportbase.pri38
-rw-r--r--src/meegoinstalls/Makefile40
-rw-r--r--src/meegoinstalls/README95
-rw-r--r--src/meegoinstalls/qt-mobility.spec1360
-rw-r--r--src/meegoinstalls/qt-mobility.yaml353
-rw-r--r--src/multimediakit/audio/audio.pri79
-rw-r--r--src/multimediakit/audio/qaudio.cpp103
-rw-r--r--src/multimediakit/audio/qaudio.h71
-rw-r--r--src/multimediakit/audio/qaudio_mac.cpp145
-rw-r--r--src/multimediakit/audio/qaudio_mac_p.h142
-rw-r--r--src/multimediakit/audio/qaudio_symbian_p.cpp663
-rw-r--r--src/multimediakit/audio/qaudio_symbian_p.h204
-rw-r--r--src/multimediakit/audio/qaudiodevicefactory.cpp292
-rw-r--r--src/multimediakit/audio/qaudiodevicefactory_p.h97
-rw-r--r--src/multimediakit/audio/qaudiodeviceinfo.cpp487
-rw-r--r--src/multimediakit/audio/qaudiodeviceinfo.h113
-rw-r--r--src/multimediakit/audio/qaudiodeviceinfo_alsa_p.cpp535
-rw-r--r--src/multimediakit/audio/qaudiodeviceinfo_alsa_p.h121
-rw-r--r--src/multimediakit/audio/qaudiodeviceinfo_mac_p.cpp351
-rw-r--r--src/multimediakit/audio/qaudiodeviceinfo_mac_p.h96
-rw-r--r--src/multimediakit/audio/qaudiodeviceinfo_symbian_p.cpp235
-rw-r--r--src/multimediakit/audio/qaudiodeviceinfo_symbian_p.h116
-rw-r--r--src/multimediakit/audio/qaudiodeviceinfo_win32_p.cpp471
-rw-r--r--src/multimediakit/audio/qaudiodeviceinfo_win32_p.h112
-rw-r--r--src/multimediakit/audio/qaudioformat.cpp407
-rw-r--r--src/multimediakit/audio/qaudioformat.h106
-rw-r--r--src/multimediakit/audio/qaudioinput.cpp426
-rw-r--r--src/multimediakit/audio/qaudioinput.h111
-rw-r--r--src/multimediakit/audio/qaudioinput_alsa_p.cpp867
-rw-r--r--src/multimediakit/audio/qaudioinput_alsa_p.h183
-rw-r--r--src/multimediakit/audio/qaudioinput_mac_p.cpp989
-rw-r--r--src/multimediakit/audio/qaudioinput_mac_p.h171
-rw-r--r--src/multimediakit/audio/qaudioinput_symbian_p.cpp594
-rw-r--r--src/multimediakit/audio/qaudioinput_symbian_p.h178
-rw-r--r--src/multimediakit/audio/qaudioinput_win32_p.cpp649
-rw-r--r--src/multimediakit/audio/qaudioinput_win32_p.h171
-rw-r--r--src/multimediakit/audio/qaudiooutput.cpp393
-rw-r--r--src/multimediakit/audio/qaudiooutput.h111
-rw-r--r--src/multimediakit/audio/qaudiooutput_alsa_p.cpp834
-rw-r--r--src/multimediakit/audio/qaudiooutput_alsa_p.h167
-rw-r--r--src/multimediakit/audio/qaudiooutput_mac_p.cpp729
-rw-r--r--src/multimediakit/audio/qaudiooutput_mac_p.h171
-rw-r--r--src/multimediakit/audio/qaudiooutput_symbian_p.cpp713
-rw-r--r--src/multimediakit/audio/qaudiooutput_symbian_p.h201
-rw-r--r--src/multimediakit/audio/qaudiooutput_win32_p.cpp715
-rw-r--r--src/multimediakit/audio/qaudiooutput_win32_p.h167
-rw-r--r--src/multimediakit/audio/qaudiopluginloader.cpp180
-rw-r--r--src/multimediakit/audio/qaudiopluginloader_p.h92
-rw-r--r--src/multimediakit/audio/qaudiosystem.cpp423
-rw-r--r--src/multimediakit/audio/qaudiosystem.h136
-rw-r--r--src/multimediakit/audio/qaudiosystemplugin.cpp143
-rw-r--r--src/multimediakit/audio/qaudiosystemplugin.h93
-rw-r--r--src/multimediakit/effects/effects.pri32
-rw-r--r--src/multimediakit/effects/qsamplecache_p.cpp398
-rw-r--r--src/multimediakit/effects/qsamplecache_p.h158
-rw-r--r--src/multimediakit/effects/qsoundeffect.cpp301
-rw-r--r--src/multimediakit/effects/qsoundeffect_p.h140
-rw-r--r--src/multimediakit/effects/qsoundeffect_pulse_p.cpp955
-rw-r--r--src/multimediakit/effects/qsoundeffect_pulse_p.h160
-rw-r--r--src/multimediakit/effects/qsoundeffect_qmedia_p.cpp233
-rw-r--r--src/multimediakit/effects/qsoundeffect_qmedia_p.h119
-rw-r--r--src/multimediakit/effects/qsoundeffect_qsound_p.cpp222
-rw-r--r--src/multimediakit/effects/qsoundeffect_qsound_p.h118
-rw-r--r--src/multimediakit/effects/qwavedecoder_p.cpp232
-rw-r--r--src/multimediakit/effects/qwavedecoder_p.h134
-rw-r--r--src/multimediakit/multimediakit.pro217
-rw-r--r--src/multimediakit/qaudiocapturesource.cpp275
-rw-r--r--src/multimediakit/qaudiocapturesource.h95
-rw-r--r--src/multimediakit/qaudioencodercontrol.cpp167
-rw-r--r--src/multimediakit/qaudioencodercontrol.h87
-rw-r--r--src/multimediakit/qaudioendpointselector.cpp142
-rw-r--r--src/multimediakit/qaudioendpointselector.h78
-rw-r--r--src/multimediakit/qaudionamespace.qdoc70
-rw-r--r--src/multimediakit/qcamera.cpp1027
-rw-r--r--src/multimediakit/qcamera.h231
-rw-r--r--src/multimediakit/qcameracapturebufferformatcontrol.cpp118
-rw-r--r--src/multimediakit/qcameracapturebufferformatcontrol.h73
-rw-r--r--src/multimediakit/qcameracapturedestinationcontrol.cpp122
-rw-r--r--src/multimediakit/qcameracapturedestinationcontrol.h73
-rw-r--r--src/multimediakit/qcameracontrol.cpp215
-rw-r--r--src/multimediakit/qcameracontrol.h93
-rw-r--r--src/multimediakit/qcameraexposure.cpp646
-rw-r--r--src/multimediakit/qcameraexposure.h178
-rw-r--r--src/multimediakit/qcameraexposurecontrol.cpp252
-rw-r--r--src/multimediakit/qcameraexposurecontrol.h116
-rw-r--r--src/multimediakit/qcameraflashcontrol.cpp143
-rw-r--r--src/multimediakit/qcameraflashcontrol.h79
-rw-r--r--src/multimediakit/qcamerafocus.cpp478
-rw-r--r--src/multimediakit/qcamerafocus.h176
-rw-r--r--src/multimediakit/qcamerafocuscontrol.cpp253
-rw-r--r--src/multimediakit/qcamerafocuscontrol.h95
-rw-r--r--src/multimediakit/qcameraimagecapture.cpp668
-rw-r--r--src/multimediakit/qcameraimagecapture.h162
-rw-r--r--src/multimediakit/qcameraimagecapturecontrol.cpp208
-rw-r--r--src/multimediakit/qcameraimagecapturecontrol.h91
-rw-r--r--src/multimediakit/qcameraimageprocessing.cpp353
-rw-r--r--src/multimediakit/qcameraimageprocessing.h118
-rw-r--r--src/multimediakit/qcameraimageprocessingcontrol.cpp169
-rw-r--r--src/multimediakit/qcameraimageprocessingcontrol.h93
-rw-r--r--src/multimediakit/qcameralockscontrol.cpp134
-rw-r--r--src/multimediakit/qcameralockscontrol.h78
-rw-r--r--src/multimediakit/qcameraviewfinder.cpp115
-rw-r--r--src/multimediakit/qcameraviewfinder.h82
-rw-r--r--src/multimediakit/qeglimagetexturesurface.cpp554
-rw-r--r--src/multimediakit/qeglimagetexturesurface_p.h142
-rw-r--r--src/multimediakit/qgraphicsvideoitem.cpp432
-rw-r--r--src/multimediakit/qgraphicsvideoitem.h107
-rw-r--r--src/multimediakit/qgraphicsvideoitem_maemo5.cpp647
-rw-r--r--src/multimediakit/qgraphicsvideoitem_maemo6.cpp498
-rw-r--r--src/multimediakit/qgraphicsvideoitem_overlay.cpp436
-rw-r--r--src/multimediakit/qgraphicsvideoitem_symbian.cpp604
-rw-r--r--src/multimediakit/qimageencodercontrol.cpp142
-rw-r--r--src/multimediakit/qimageencodercontrol.h83
-rw-r--r--src/multimediakit/qlocalmediaplaylistprovider.cpp194
-rw-r--r--src/multimediakit/qlocalmediaplaylistprovider.h79
-rw-r--r--src/multimediakit/qmediabindableinterface.cpp85
-rw-r--r--src/multimediakit/qmediabindableinterface.h69
-rw-r--r--src/multimediakit/qmediacontainercontrol.cpp126
-rw-r--r--src/multimediakit/qmediacontainercontrol.h72
-rw-r--r--src/multimediakit/qmediacontent.cpp254
-rw-r--r--src/multimediakit/qmediacontent.h90
-rw-r--r--src/multimediakit/qmediacontrol.cpp140
-rw-r--r--src/multimediakit/qmediacontrol.h79
-rw-r--r--src/multimediakit/qmediacontrol_p.h72
-rw-r--r--src/multimediakit/qmediaencodersettings.cpp822
-rw-r--r--src/multimediakit/qmediaencodersettings.h160
-rw-r--r--src/multimediakit/qmediaenumdebug.h76
-rw-r--r--src/multimediakit/qmediaimageviewer.cpp599
-rw-r--r--src/multimediakit/qmediaimageviewer.h135
-rw-r--r--src/multimediakit/qmediaimageviewerservice.cpp465
-rw-r--r--src/multimediakit/qmediaimageviewerservice_p.h141
-rw-r--r--src/multimediakit/qmedianetworkaccesscontrol.cpp103
-rw-r--r--src/multimediakit/qmedianetworkaccesscontrol.h75
-rw-r--r--src/multimediakit/qmediaobject.cpp427
-rw-r--r--src/multimediakit/qmediaobject.h110
-rw-r--r--src/multimediakit/qmediaobject_p.h91
-rw-r--r--src/multimediakit/qmediaplayer.cpp1134
-rw-r--r--src/multimediakit/qmediaplayer.h224
-rw-r--r--src/multimediakit/qmediaplayercontrol.cpp414
-rw-r--r--src/multimediakit/qmediaplayercontrol.h123
-rw-r--r--src/multimediakit/qmediaplaylist.cpp756
-rw-r--r--src/multimediakit/qmediaplaylist.h147
-rw-r--r--src/multimediakit/qmediaplaylist_p.h169
-rw-r--r--src/multimediakit/qmediaplaylistcontrol.cpp219
-rw-r--r--src/multimediakit/qmediaplaylistcontrol.h90
-rw-r--r--src/multimediakit/qmediaplaylistioplugin.cpp204
-rw-r--r--src/multimediakit/qmediaplaylistioplugin.h118
-rw-r--r--src/multimediakit/qmediaplaylistnavigator.cpp568
-rw-r--r--src/multimediakit/qmediaplaylistnavigator.h107
-rw-r--r--src/multimediakit/qmediaplaylistprovider.cpp329
-rw-r--r--src/multimediakit/qmediaplaylistprovider.h107
-rw-r--r--src/multimediakit/qmediaplaylistprovider_p.h72
-rw-r--r--src/multimediakit/qmediaplaylistsourcecontrol.cpp128
-rw-r--r--src/multimediakit/qmediaplaylistsourcecontrol.h74
-rw-r--r--src/multimediakit/qmediapluginloader.cpp271
-rw-r--r--src/multimediakit/qmediapluginloader_p.h91
-rw-r--r--src/multimediakit/qmediarecorder.cpp899
-rw-r--r--src/multimediakit/qmediarecorder.h190
-rw-r--r--src/multimediakit/qmediarecordercontrol.cpp209
-rw-r--r--src/multimediakit/qmediarecordercontrol.h93
-rw-r--r--src/multimediakit/qmediaresource.cpp440
-rw-r--r--src/multimediakit/qmediaresource.h128
-rw-r--r--src/multimediakit/qmediaservice.cpp151
-rw-r--r--src/multimediakit/qmediaservice.h89
-rw-r--r--src/multimediakit/qmediaservice_p.h72
-rw-r--r--src/multimediakit/qmediaserviceprovider.cpp780
-rw-r--r--src/multimediakit/qmediaserviceprovider.h170
-rw-r--r--src/multimediakit/qmediaserviceproviderplugin.h121
-rw-r--r--src/multimediakit/qmediastreamscontrol.cpp162
-rw-r--r--src/multimediakit/qmediastreamscontrol.h88
-rw-r--r--src/multimediakit/qmediatimerange.cpp759
-rw-r--r--src/multimediakit/qmediatimerange.h132
-rw-r--r--src/multimediakit/qmetadatareadercontrol.cpp163
-rw-r--r--src/multimediakit/qmetadatareadercontrol.h84
-rw-r--r--src/multimediakit/qmetadatawritercontrol.cpp195
-rw-r--r--src/multimediakit/qmetadatawritercontrol.h89
-rw-r--r--src/multimediakit/qmobilityglobal.h245
-rw-r--r--src/multimediakit/qpaintervideosurface.cpp1728
-rw-r--r--src/multimediakit/qpaintervideosurface_mac.mm284
-rw-r--r--src/multimediakit/qpaintervideosurface_mac_p.h100
-rw-r--r--src/multimediakit/qpaintervideosurface_p.h183
-rw-r--r--src/multimediakit/qradiotuner.cpp614
-rw-r--r--src/multimediakit/qradiotuner.h151
-rw-r--r--src/multimediakit/qradiotunercontrol.cpp364
-rw-r--r--src/multimediakit/qradiotunercontrol.h115
-rw-r--r--src/multimediakit/qtmedianamespace.h190
-rw-r--r--src/multimediakit/qtmedianamespace.qdoc208
-rw-r--r--src/multimediakit/qvideodevicecontrol.cpp159
-rw-r--r--src/multimediakit/qvideodevicecontrol.h83
-rw-r--r--src/multimediakit/qvideoencodercontrol.cpp190
-rw-r--r--src/multimediakit/qvideoencodercontrol.h90
-rw-r--r--src/multimediakit/qvideorenderercontrol.cpp114
-rw-r--r--src/multimediakit/qvideorenderercontrol.h73
-rw-r--r--src/multimediakit/qvideosurfaceoutput.cpp100
-rw-r--r--src/multimediakit/qvideosurfaceoutput_p.h78
-rw-r--r--src/multimediakit/qvideowidget.cpp1049
-rw-r--r--src/multimediakit/qvideowidget.h131
-rw-r--r--src/multimediakit/qvideowidget_p.h282
-rw-r--r--src/multimediakit/qvideowidgetcontrol.cpp245
-rw-r--r--src/multimediakit/qvideowidgetcontrol.h97
-rw-r--r--src/multimediakit/qvideowindowcontrol.cpp284
-rw-r--r--src/multimediakit/qvideowindowcontrol.h104
-rw-r--r--src/multimediakit/qxvideosurface_maemo5.cpp497
-rw-r--r--src/multimediakit/qxvideosurface_maemo5_p.h111
-rw-r--r--src/multimediakit/video/qabstractvideobuffer.cpp208
-rw-r--r--src/multimediakit/video/qabstractvideobuffer.h109
-rw-r--r--src/multimediakit/video/qabstractvideobuffer_p.h80
-rw-r--r--src/multimediakit/video/qabstractvideosurface.cpp344
-rw-r--r--src/multimediakit/video/qabstractvideosurface.h112
-rw-r--r--src/multimediakit/video/qimagevideobuffer.cpp106
-rw-r--r--src/multimediakit/video/qimagevideobuffer_p.h79
-rw-r--r--src/multimediakit/video/qmemoryvideobuffer.cpp133
-rw-r--r--src/multimediakit/video/qmemoryvideobuffer_p.h81
-rw-r--r--src/multimediakit/video/qvideoframe.cpp793
-rw-r--r--src/multimediakit/video/qvideoframe.h172
-rw-r--r--src/multimediakit/video/qvideosurfaceformat.cpp709
-rw-r--r--src/multimediakit/video/qvideosurfaceformat.h145
-rw-r--r--src/multimediakit/video/video.pri22
-rw-r--r--src/plugins/audiocapture/audiocapture.pro25
-rw-r--r--src/plugins/audiocapture/audiocaptureservice.cpp90
-rw-r--r--src/plugins/audiocapture/audiocaptureservice.h74
-rw-r--r--src/plugins/audiocapture/audiocaptureserviceplugin.cpp69
-rw-r--r--src/plugins/audiocapture/audiocaptureserviceplugin.h60
-rw-r--r--src/plugins/audiocapture/audiocapturesession.cpp358
-rw-r--r--src/plugins/audiocapture/audiocapturesession.h152
-rw-r--r--src/plugins/audiocapture/audiocontainercontrol.cpp74
-rw-r--r--src/plugins/audiocapture/audiocontainercontrol.h70
-rw-r--r--src/plugins/audiocapture/audioencodercontrol.cpp168
-rw-r--r--src/plugins/audiocapture/audioencodercontrol.h79
-rw-r--r--src/plugins/audiocapture/audioendpointselector.cpp110
-rw-r--r--src/plugins/audiocapture/audioendpointselector.h77
-rw-r--r--src/plugins/audiocapture/audiomediarecordercontrol.cpp102
-rw-r--r--src/plugins/audiocapture/audiomediarecordercontrol.h82
-rw-r--r--src/plugins/directshow/camera/camera.pri31
-rw-r--r--src/plugins/directshow/camera/directshowglobal.h236
-rw-r--r--src/plugins/directshow/camera/dscameracontrol.cpp103
-rw-r--r--src/plugins/directshow/camera/dscameracontrol.h94
-rw-r--r--src/plugins/directshow/camera/dscameraservice.cpp114
-rw-r--r--src/plugins/directshow/camera/dscameraservice.h88
-rw-r--r--src/plugins/directshow/camera/dscamerasession.cpp1160
-rw-r--r--src/plugins/directshow/camera/dscamerasession.h208
-rw-r--r--src/plugins/directshow/camera/dsimagecapturecontrol.cpp83
-rw-r--r--src/plugins/directshow/camera/dsimagecapturecontrol.h80
-rw-r--r--src/plugins/directshow/camera/dsvideodevicecontrol.cpp168
-rw-r--r--src/plugins/directshow/camera/dsvideodevicecontrol.h83
-rw-r--r--src/plugins/directshow/camera/dsvideorenderer.cpp72
-rw-r--r--src/plugins/directshow/camera/dsvideorenderer.h77
-rw-r--r--src/plugins/directshow/camera/dsvideowidgetcontrol.cpp250
-rw-r--r--src/plugins/directshow/camera/dsvideowidgetcontrol.h154
-rw-r--r--src/plugins/directshow/directshow.pro23
-rw-r--r--src/plugins/directshow/dsserviceplugin.cpp211
-rw-r--r--src/plugins/directshow/dsserviceplugin.h76
-rw-r--r--src/plugins/directshow/player/directshowaudioendpointcontrol.cpp161
-rw-r--r--src/plugins/directshow/player/directshowaudioendpointcontrol.h82
-rw-r--r--src/plugins/directshow/player/directshoweventloop.cpp150
-rw-r--r--src/plugins/directshow/player/directshoweventloop.h78
-rw-r--r--src/plugins/directshow/player/directshowglobal.h139
-rw-r--r--src/plugins/directshow/player/directshowioreader.cpp496
-rw-r--r--src/plugins/directshow/player/directshowioreader.h120
-rw-r--r--src/plugins/directshow/player/directshowiosource.cpp639
-rw-r--r--src/plugins/directshow/player/directshowiosource.h149
-rw-r--r--src/plugins/directshow/player/directshowmediatype.cpp184
-rw-r--r--src/plugins/directshow/player/directshowmediatype.h74
-rw-r--r--src/plugins/directshow/player/directshowmediatypelist.cpp226
-rw-r--r--src/plugins/directshow/player/directshowmediatypelist.h69
-rw-r--r--src/plugins/directshow/player/directshowmetadatacontrol.cpp352
-rw-r--r--src/plugins/directshow/player/directshowmetadatacontrol.h93
-rw-r--r--src/plugins/directshow/player/directshowpinenum.cpp134
-rw-r--r--src/plugins/directshow/player/directshowpinenum.h72
-rw-r--r--src/plugins/directshow/player/directshowplayercontrol.cpp405
-rw-r--r--src/plugins/directshow/player/directshowplayercontrol.h146
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.cpp1408
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.h219
-rw-r--r--src/plugins/directshow/player/directshowsamplescheduler.cpp437
-rw-r--r--src/plugins/directshow/player/directshowsamplescheduler.h117
-rw-r--r--src/plugins/directshow/player/directshowvideorenderercontrol.cpp86
-rw-r--r--src/plugins/directshow/player/directshowvideorenderercontrol.h75
-rw-r--r--src/plugins/directshow/player/mediasamplevideobuffer.cpp86
-rw-r--r--src/plugins/directshow/player/mediasamplevideobuffer.h69
-rw-r--r--src/plugins/directshow/player/player.pri47
-rw-r--r--src/plugins/directshow/player/videosurfacefilter.cpp631
-rw-r--r--src/plugins/directshow/player/videosurfacefilter.h176
-rw-r--r--src/plugins/directshow/player/vmr9videowindowcontrol.cpp329
-rw-r--r--src/plugins/directshow/player/vmr9videowindowcontrol.h108
-rw-r--r--src/plugins/gstreamer/camerabin/camerabin.pri50
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp293
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinaudioencoder.h105
-rw-r--r--src/plugins/gstreamer/camerabin/camerabincapturebufferformat.cpp78
-rw-r--r--src/plugins/gstreamer/camerabin/camerabincapturebufferformat.h72
-rw-r--r--src/plugins/gstreamer/camerabin/camerabincapturedestination.cpp74
-rw-r--r--src/plugins/gstreamer/camerabin/camerabincapturedestination.h69
-rw-r--r--src/plugins/gstreamer/camerabin/camerabincontainer.cpp122
-rw-r--r--src/plugins/gstreamer/camerabin/camerabincontainer.h103
-rw-r--r--src/plugins/gstreamer/camerabin/camerabincontrol.cpp356
-rw-r--r--src/plugins/gstreamer/camerabin/camerabincontrol.h101
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinexposure.cpp232
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinexposure.h83
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinflash.cpp104
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinflash.h73
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinfocus.cpp245
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinfocus.h104
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp347
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinimagecapture.h82
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinimageencoder.cpp87
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinimageencoder.h86
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinimageprocessing.cpp171
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinimageprocessing.h84
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinlocks.cpp88
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinlocks.h79
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinmetadata.cpp198
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinmetadata.h75
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinrecorder.cpp225
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinrecorder.h85
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinresourcepolicy.cpp188
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinresourcepolicy.h84
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinservice.cpp261
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinservice.h96
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinsession.cpp1267
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinsession.h234
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp346
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinvideoencoder.h106
-rw-r--r--src/plugins/gstreamer/camerabuttonlistener_maemo.cpp121
-rw-r--r--src/plugins/gstreamer/camerabuttonlistener_maemo.h64
-rw-r--r--src/plugins/gstreamer/camerabuttonlistener_meego.cpp92
-rw-r--r--src/plugins/gstreamer/camerabuttonlistener_meego.h65
-rw-r--r--src/plugins/gstreamer/gstreamer.pro101
-rw-r--r--src/plugins/gstreamer/gstvideoconnector.c421
-rw-r--r--src/plugins/gstreamer/gstvideoconnector.h87
-rw-r--r--src/plugins/gstreamer/mediacapture/mediacapture.pri27
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp292
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreameraudioencode.h97
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.cpp185
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.h98
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp198
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.h75
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp185
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h96
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp1051
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h211
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamerimagecapturecontrol.cpp98
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamerimagecapturecontrol.h73
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamerimageencode.cpp90
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamerimageencode.h80
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.cpp135
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.h84
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp289
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.h91
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.cpp297
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.h83
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp331
-rw-r--r--src/plugins/gstreamer/mediacapture/qgstreamervideoencode.h98
-rw-r--r--src/plugins/gstreamer/mediaplayer/mediaplayer.pri30
-rw-r--r--src/plugins/gstreamer/mediaplayer/playerresourcepolicy.cpp180
-rw-r--r--src/plugins/gstreamer/mediaplayer/playerresourcepolicy.h90
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstappsrc.cpp224
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstappsrc.h106
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp192
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h74
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp748
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h157
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp134
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h90
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp1537
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h217
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp89
-rw-r--r--src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.h71
-rw-r--r--src/plugins/gstreamer/qabstractgstbufferpool.h75
-rw-r--r--src/plugins/gstreamer/qgstreameraudioinputendpointselector.cpp174
-rw-r--r--src/plugins/gstreamer/qgstreameraudioinputendpointselector.h76
-rw-r--r--src/plugins/gstreamer/qgstreamerbushelper.cpp203
-rw-r--r--src/plugins/gstreamer/qgstreamerbushelper.h77
-rw-r--r--src/plugins/gstreamer/qgstreamergltexturerenderer.cpp578
-rw-r--r--src/plugins/gstreamer/qgstreamergltexturerenderer.h127
-rw-r--r--src/plugins/gstreamer/qgstreamermessage.cpp93
-rw-r--r--src/plugins/gstreamer/qgstreamermessage.h68
-rw-r--r--src/plugins/gstreamer/qgstreamerserviceplugin.cpp401
-rw-r--r--src/plugins/gstreamer/qgstreamerserviceplugin.h86
-rw-r--r--src/plugins/gstreamer/qgstreamervideoinputdevicecontrol.cpp162
-rw-r--r--src/plugins/gstreamer/qgstreamervideoinputdevicecontrol.h77
-rw-r--r--src/plugins/gstreamer/qgstreamervideooverlay.cpp232
-rw-r--r--src/plugins/gstreamer/qgstreamervideooverlay.h119
-rw-r--r--src/plugins/gstreamer/qgstreamervideorenderer.cpp120
-rw-r--r--src/plugins/gstreamer/qgstreamervideorenderer.h80
-rw-r--r--src/plugins/gstreamer/qgstreamervideorendererinterface.cpp46
-rw-r--r--src/plugins/gstreamer/qgstreamervideorendererinterface.h79
-rw-r--r--src/plugins/gstreamer/qgstreamervideowidget.cpp331
-rw-r--r--src/plugins/gstreamer/qgstreamervideowidget.h108
-rw-r--r--src/plugins/gstreamer/qgstreamervideowindow.cpp342
-rw-r--r--src/plugins/gstreamer/qgstreamervideowindow.h131
-rw-r--r--src/plugins/gstreamer/qgstutils.cpp165
-rw-r--r--src/plugins/gstreamer/qgstutils.h59
-rw-r--r--src/plugins/gstreamer/qgstvideobuffer.cpp97
-rw-r--r--src/plugins/gstreamer/qgstvideobuffer.h72
-rw-r--r--src/plugins/gstreamer/qgstxvimagebuffer.cpp311
-rw-r--r--src/plugins/gstreamer/qgstxvimagebuffer.h130
-rw-r--r--src/plugins/gstreamer/qvideosurfacegstsink.cpp772
-rw-r--r--src/plugins/gstreamer/qvideosurfacegstsink.h162
-rw-r--r--src/plugins/gstreamer/qx11videosurface.cpp535
-rw-r--r--src/plugins/gstreamer/qx11videosurface.h117
-rw-r--r--src/plugins/m3u/m3u.pro23
-rw-r--r--src/plugins/m3u/main.cpp47
-rw-r--r--src/plugins/m3u/qm3uhandler.cpp237
-rw-r--r--src/plugins/m3u/qm3uhandler.h70
-rw-r--r--src/plugins/plugins.pro46
-rw-r--r--src/plugins/pulseaudio/pulseaudio.pro26
-rw-r--r--src/plugins/pulseaudio/qaudiodeviceinfo_pulse.cpp105
-rw-r--r--src/plugins/pulseaudio/qaudiodeviceinfo_pulse.h92
-rw-r--r--src/plugins/pulseaudio/qaudioinput_pulse.cpp600
-rw-r--r--src/plugins/pulseaudio/qaudioinput_pulse.h153
-rw-r--r--src/plugins/pulseaudio/qaudiooutput_pulse.cpp573
-rw-r--r--src/plugins/pulseaudio/qaudiooutput_pulse.h153
-rw-r--r--src/plugins/pulseaudio/qpulseaudioengine.cpp354
-rw-r--r--src/plugins/pulseaudio/qpulseaudioengine.h100
-rw-r--r--src/plugins/pulseaudio/qpulseaudioplugin.cpp89
-rw-r--r--src/plugins/pulseaudio/qpulseaudioplugin.h71
-rw-r--r--src/plugins/pulseaudio/qpulsehelpers.cpp220
-rw-r--r--src/plugins/pulseaudio/qpulsehelpers.h73
-rw-r--r--src/plugins/qt7/mediaplayer/mediaplayer.pri16
-rw-r--r--src/plugins/qt7/mediaplayer/qt7playercontrol.h109
-rw-r--r--src/plugins/qt7/mediaplayer/qt7playercontrol.mm191
-rw-r--r--src/plugins/qt7/mediaplayer/qt7playermetadata.h77
-rw-r--r--src/plugins/qt7/mediaplayer/qt7playermetadata.mm260
-rw-r--r--src/plugins/qt7/mediaplayer/qt7playerservice.h82
-rw-r--r--src/plugins/qt7/mediaplayer/qt7playerservice.mm129
-rw-r--r--src/plugins/qt7/mediaplayer/qt7playersession.h194
-rw-r--r--src/plugins/qt7/mediaplayer/qt7playersession.mm751
-rw-r--r--src/plugins/qt7/qcvdisplaylink.h88
-rw-r--r--src/plugins/qt7/qcvdisplaylink.mm156
-rw-r--r--src/plugins/qt7/qt7.pro58
-rw-r--r--src/plugins/qt7/qt7backend.h68
-rw-r--r--src/plugins/qt7/qt7backend.mm60
-rw-r--r--src/plugins/qt7/qt7ciimagevideobuffer.h86
-rw-r--r--src/plugins/qt7/qt7ciimagevideobuffer.mm107
-rw-r--r--src/plugins/qt7/qt7movierenderer.h107
-rw-r--r--src/plugins/qt7/qt7movierenderer.mm479
-rw-r--r--src/plugins/qt7/qt7movievideowidget.h126
-rw-r--r--src/plugins/qt7/qt7movievideowidget.mm437
-rw-r--r--src/plugins/qt7/qt7movieviewoutput.h116
-rw-r--r--src/plugins/qt7/qt7movieviewoutput.mm339
-rw-r--r--src/plugins/qt7/qt7movieviewrenderer.h93
-rw-r--r--src/plugins/qt7/qt7movieviewrenderer.mm371
-rw-r--r--src/plugins/qt7/qt7serviceplugin.h75
-rw-r--r--src/plugins/qt7/qt7serviceplugin.mm129
-rw-r--r--src/plugins/qt7/qt7videooutput.h116
-rw-r--r--src/plugins/qt7/qt7videooutput.mm91
-rw-r--r--src/plugins/simulator/camera/simulatorcamera.pri25
-rw-r--r--src/plugins/simulator/camera/simulatorcameracontrol.cpp179
-rw-r--r--src/plugins/simulator/camera/simulatorcameracontrol.h87
-rw-r--r--src/plugins/simulator/camera/simulatorcameraexposurecontrol.cpp502
-rw-r--r--src/plugins/simulator/camera/simulatorcameraexposurecontrol.h125
-rw-r--r--src/plugins/simulator/camera/simulatorcameraimagecapturecontrol.cpp120
-rw-r--r--src/plugins/simulator/camera/simulatorcameraimagecapturecontrol.h87
-rw-r--r--src/plugins/simulator/camera/simulatorcameraservice.cpp161
-rw-r--r--src/plugins/simulator/camera/simulatorcameraservice.h92
-rw-r--r--src/plugins/simulator/camera/simulatorcamerasession.cpp147
-rw-r--r--src/plugins/simulator/camera/simulatorcamerasession.h96
-rw-r--r--src/plugins/simulator/camera/simulatorcamerasettings.cpp174
-rw-r--r--src/plugins/simulator/camera/simulatorcamerasettings.h110
-rw-r--r--src/plugins/simulator/camera/simulatorvideoinputdevicecontrol.cpp152
-rw-r--r--src/plugins/simulator/camera/simulatorvideoinputdevicecontrol.h83
-rw-r--r--src/plugins/simulator/camera/simulatorvideorenderercontrol.cpp130
-rw-r--r--src/plugins/simulator/camera/simulatorvideorenderercontrol.h82
-rw-r--r--src/plugins/simulator/qsimulatormultimediaconnection.cpp122
-rw-r--r--src/plugins/simulator/qsimulatormultimediaconnection_p.h89
-rw-r--r--src/plugins/simulator/qsimulatormultimediadata.cpp78
-rw-r--r--src/plugins/simulator/qsimulatormultimediadata_p.h81
-rw-r--r--src/plugins/simulator/qsimulatorserviceplugin.cpp127
-rw-r--r--src/plugins/simulator/qsimulatorserviceplugin.h75
-rw-r--r--src/plugins/simulator/simulator.pro28
-rw-r--r--src/plugins/symbian/ecam/camera_s60.pri157
-rw-r--r--src/plugins/symbian/ecam/ecam.pro40
-rw-r--r--src/plugins/symbian/ecam/s60audioencodercontrol.cpp159
-rw-r--r--src/plugins/symbian/ecam/s60audioencodercontrol.h90
-rw-r--r--src/plugins/symbian/ecam/s60cameraconstants.h257
-rw-r--r--src/plugins/symbian/ecam/s60cameracontrol.cpp983
-rw-r--r--src/plugins/symbian/ecam/s60cameracontrol.h178
-rw-r--r--src/plugins/symbian/ecam/s60cameraengine.cpp824
-rw-r--r--src/plugins/symbian/ecam/s60cameraengine.h407
-rw-r--r--src/plugins/symbian/ecam/s60cameraengineobserver.h178
-rw-r--r--src/plugins/symbian/ecam/s60cameraexposurecontrol.cpp584
-rw-r--r--src/plugins/symbian/ecam/s60cameraexposurecontrol.h138
-rw-r--r--src/plugins/symbian/ecam/s60cameraflashcontrol.cpp109
-rw-r--r--src/plugins/symbian/ecam/s60cameraflashcontrol.h93
-rw-r--r--src/plugins/symbian/ecam/s60camerafocuscontrol.cpp193
-rw-r--r--src/plugins/symbian/ecam/s60camerafocuscontrol.h112
-rw-r--r--src/plugins/symbian/ecam/s60cameraimagecapturecontrol.cpp124
-rw-r--r--src/plugins/symbian/ecam/s60cameraimagecapturecontrol.h99
-rw-r--r--src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.cpp254
-rw-r--r--src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.h118
-rw-r--r--src/plugins/symbian/ecam/s60cameralockscontrol.cpp263
-rw-r--r--src/plugins/symbian/ecam/s60cameralockscontrol.h115
-rw-r--r--src/plugins/symbian/ecam/s60cameraservice.cpp259
-rw-r--r--src/plugins/symbian/ecam/s60cameraservice.h111
-rw-r--r--src/plugins/symbian/ecam/s60cameraserviceplugin.cpp115
-rw-r--r--src/plugins/symbian/ecam/s60cameraserviceplugin.h81
-rw-r--r--src/plugins/symbian/ecam/s60camerasettings.cpp986
-rw-r--r--src/plugins/symbian/ecam/s60camerasettings.h177
-rw-r--r--src/plugins/symbian/ecam/s60cameraviewfinderengine.cpp789
-rw-r--r--src/plugins/symbian/ecam/s60cameraviewfinderengine.h182
-rw-r--r--src/plugins/symbian/ecam/s60imagecapturesession.cpp1884
-rw-r--r--src/plugins/symbian/ecam/s60imagecapturesession.h359
-rw-r--r--src/plugins/symbian/ecam/s60imageencodercontrol.cpp128
-rw-r--r--src/plugins/symbian/ecam/s60imageencodercontrol.h84
-rw-r--r--src/plugins/symbian/ecam/s60mediacontainercontrol.cpp97
-rw-r--r--src/plugins/symbian/ecam/s60mediacontainercontrol.h82
-rw-r--r--src/plugins/symbian/ecam/s60mediarecordercontrol.cpp187
-rw-r--r--src/plugins/symbian/ecam/s60mediarecordercontrol.h118
-rw-r--r--src/plugins/symbian/ecam/s60videocapturesession.cpp2995
-rw-r--r--src/plugins/symbian/ecam/s60videocapturesession.h414
-rw-r--r--src/plugins/symbian/ecam/s60videodevicecontrol.cpp108
-rw-r--r--src/plugins/symbian/ecam/s60videodevicecontrol.h95
-rw-r--r--src/plugins/symbian/ecam/s60videoencodercontrol.cpp204
-rw-r--r--src/plugins/symbian/ecam/s60videoencodercontrol.h94
-rw-r--r--src/plugins/symbian/ecam/s60videorenderercontrol.cpp78
-rw-r--r--src/plugins/symbian/ecam/s60videorenderercontrol.h76
-rw-r--r--src/plugins/symbian/mmf/audiosource/audiosource_s60.pri31
-rw-r--r--src/plugins/symbian/mmf/audiosource/s60audiocaptureservice.cpp98
-rw-r--r--src/plugins/symbian/mmf/audiosource/s60audiocaptureservice.h75
-rw-r--r--src/plugins/symbian/mmf/audiosource/s60audiocapturesession.cpp937
-rw-r--r--src/plugins/symbian/mmf/audiosource/s60audiocapturesession.h193
-rw-r--r--src/plugins/symbian/mmf/audiosource/s60audiocontainercontrol.cpp96
-rw-r--r--src/plugins/symbian/mmf/audiosource/s60audiocontainercontrol.h70
-rw-r--r--src/plugins/symbian/mmf/audiosource/s60audioencodercontrol.cpp235
-rw-r--r--src/plugins/symbian/mmf/audiosource/s60audioencodercontrol.h82
-rw-r--r--src/plugins/symbian/mmf/audiosource/s60audioendpointselector.cpp100
-rw-r--r--src/plugins/symbian/mmf/audiosource/s60audioendpointselector.h76
-rw-r--r--src/plugins/symbian/mmf/audiosource/s60audiomediarecordercontrol.cpp180
-rw-r--r--src/plugins/symbian/mmf/audiosource/s60audiomediarecordercontrol.h92
-rw-r--r--src/plugins/symbian/mmf/inc/DebugMacros.h66
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/mediaplayer_s60.pri92
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/ms60mediaplayerresolver.h54
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60audioplayersession.cpp577
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60audioplayersession.h136
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediametadataprovider.cpp146
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediametadataprovider.h72
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60medianetworkaccesscontrol.cpp144
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60medianetworkaccesscontrol.h89
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediaplayeraudioendpointselector.cpp182
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediaplayeraudioendpointselector.h77
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediaplayercontrol.cpp518
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediaplayercontrol.h148
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediaplayerservice.cpp326
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediaplayerservice.h97
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediaplayersession.cpp1054
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediaplayersession.h187
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediarecognizer.cpp167
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediarecognizer.h79
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediastreamcontrol.cpp201
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60mediastreamcontrol.h79
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60videooutputinterface.h62
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60videoplayersession.cpp1124
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60videoplayersession.h218
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60videorenderer.cpp95
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60videorenderer.h66
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60videosurface.cpp372
-rw-r--r--src/plugins/symbian/mmf/mediaplayer/s60videosurface.h106
-rw-r--r--src/plugins/symbian/mmf/mmf.pro58
-rw-r--r--src/plugins/symbian/mmf/radio/radio.pri24
-rw-r--r--src/plugins/symbian/mmf/radio/s60radiotunercontrol_31.cpp603
-rw-r--r--src/plugins/symbian/mmf/radio/s60radiotunercontrol_31.h161
-rw-r--r--src/plugins/symbian/mmf/radio/s60radiotunercontrol_since32.cpp685
-rw-r--r--src/plugins/symbian/mmf/radio/s60radiotunercontrol_since32.h296
-rw-r--r--src/plugins/symbian/mmf/radio/s60radiotunerservice.cpp83
-rw-r--r--src/plugins/symbian/mmf/radio/s60radiotunerservice.h71
-rw-r--r--src/plugins/symbian/mmf/s60formatsupported.cpp121
-rw-r--r--src/plugins/symbian/mmf/s60formatsupported.h65
-rw-r--r--src/plugins/symbian/mmf/s60mediaserviceplugin.cpp115
-rw-r--r--src/plugins/symbian/mmf/s60mediaserviceplugin.h69
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/mediaplayer.pri36
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxamediaplayercontrol.cpp288
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxamediaplayercontrol.h99
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxamediastreamscontrol.cpp98
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxamediastreamscontrol.h77
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxametadatacontrol.cpp131
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxametadatacontrol.h78
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxaplaymediaservice.cpp117
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxaplaymediaservice.h74
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxaplaysession.cpp610
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxaplaysession.h192
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxavideowidgetcontrol.cpp182
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxavideowidgetcontrol.h93
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxavideowindowcontrol.cpp222
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxavideowindowcontrol.h105
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxawidget.cpp64
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/qxawidget.h63
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/xaplaysessioncommon.h58
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/xaplaysessionimpl.cpp1259
-rw-r--r--src/plugins/symbian/openmaxal/mediaplayer/xaplaysessionimpl.h210
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/mediarecorder.pri24
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.cpp111
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.h79
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.cpp98
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.h77
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.cpp81
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.h71
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.cpp122
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.h83
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.cpp86
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.h78
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.cpp766
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.h144
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/xarecordsessioncommon.h67
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.cpp1378
-rw-r--r--src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.h179
-rw-r--r--src/plugins/symbian/openmaxal/openmaxal.pro58
-rw-r--r--src/plugins/symbian/openmaxal/qxacommon.h203
-rw-r--r--src/plugins/symbian/openmaxal/qxamediaserviceproviderplugin.cpp87
-rw-r--r--src/plugins/symbian/openmaxal/qxamediaserviceproviderplugin.h60
-rw-r--r--src/plugins/symbian/openmaxal/radiotuner/qxaradiocontrol.cpp202
-rw-r--r--src/plugins/symbian/openmaxal/radiotuner/qxaradiocontrol.h95
-rw-r--r--src/plugins/symbian/openmaxal/radiotuner/qxaradiomediaservice.cpp72
-rw-r--r--src/plugins/symbian/openmaxal/radiotuner/qxaradiomediaservice.h66
-rw-r--r--src/plugins/symbian/openmaxal/radiotuner/qxaradiosession.cpp323
-rw-r--r--src/plugins/symbian/openmaxal/radiotuner/qxaradiosession.h118
-rw-r--r--src/plugins/symbian/openmaxal/radiotuner/radiotuner.pri18
-rw-r--r--src/plugins/symbian/openmaxal/radiotuner/xaradiosessionimpl.cpp715
-rw-r--r--src/plugins/symbian/openmaxal/radiotuner/xaradiosessionimpl.h128
-rw-r--r--src/plugins/symbian/openmaxal/radiotuner/xaradiosessionimplobserver.h64
-rw-r--r--src/plugins/symbian/openmaxal/xacommon.h79
-rw-r--r--src/plugins/symbian/symbian.pro23
-rw-r--r--src/plugins/symbian/videooutput/s60videodisplay.cpp179
-rw-r--r--src/plugins/symbian/videooutput/s60videodisplay.h188
-rw-r--r--src/plugins/symbian/videooutput/s60videooutpututils.cpp119
-rw-r--r--src/plugins/symbian/videooutput/s60videooutpututils.h71
-rw-r--r--src/plugins/symbian/videooutput/s60videowidget.cpp237
-rw-r--r--src/plugins/symbian/videooutput/s60videowidget.h97
-rw-r--r--src/plugins/symbian/videooutput/s60videowidgetcontrol.cpp171
-rw-r--r--src/plugins/symbian/videooutput/s60videowidgetcontrol.h131
-rw-r--r--src/plugins/symbian/videooutput/s60videowidgetdisplay.cpp174
-rw-r--r--src/plugins/symbian/videooutput/s60videowidgetdisplay.h85
-rw-r--r--src/plugins/symbian/videooutput/s60videowindowcontrol.cpp178
-rw-r--r--src/plugins/symbian/videooutput/s60videowindowcontrol.h102
-rw-r--r--src/plugins/symbian/videooutput/s60videowindowdisplay.cpp140
-rw-r--r--src/plugins/symbian/videooutput/s60videowindowdisplay.h73
-rw-r--r--src/plugins/symbian/videooutput/videooutput.pri37
-rw-r--r--src/plugins/v4l/radio/radio.pri29
-rw-r--r--src/plugins/v4l/radio/v4lradiocontrol.cpp538
-rw-r--r--src/plugins/v4l/radio/v4lradiocontrol.h134
-rw-r--r--src/plugins/v4l/radio/v4lradiocontrol_maemo5.cpp755
-rw-r--r--src/plugins/v4l/radio/v4lradiocontrol_maemo5.h144
-rw-r--r--src/plugins/v4l/radio/v4lradioservice.cpp71
-rw-r--r--src/plugins/v4l/radio/v4lradioservice.h67
-rw-r--r--src/plugins/v4l/v4l.pro13
-rw-r--r--src/plugins/v4l/v4lserviceplugin.cpp84
-rw-r--r--src/plugins/v4l/v4lserviceplugin.h63
-rw-r--r--src/plugins/wmp/qevrvideooverlay.cpp357
-rw-r--r--src/plugins/wmp/qevrvideooverlay.h119
-rw-r--r--src/plugins/wmp/qmfactivate.cpp296
-rw-r--r--src/plugins/wmp/qmfactivate.h90
-rw-r--r--src/plugins/wmp/qwmpevents.cpp114
-rw-r--r--src/plugins/wmp/qwmpevents.h222
-rw-r--r--src/plugins/wmp/qwmpglobal.cpp68
-rw-r--r--src/plugins/wmp/qwmpglobal.h83
-rw-r--r--src/plugins/wmp/qwmpmetadata.cpp442
-rw-r--r--src/plugins/wmp/qwmpmetadata.h88
-rw-r--r--src/plugins/wmp/qwmpplayercontrol.cpp465
-rw-r--r--src/plugins/wmp/qwmpplayercontrol.h141
-rw-r--r--src/plugins/wmp/qwmpplayerservice.cpp355
-rw-r--r--src/plugins/wmp/qwmpplayerservice.h125
-rw-r--r--src/plugins/wmp/qwmpplaylist.cpp296
-rw-r--r--src/plugins/wmp/qwmpplaylist.h94
-rw-r--r--src/plugins/wmp/qwmpplaylistcontrol.cpp153
-rw-r--r--src/plugins/wmp/qwmpplaylistcontrol.h85
-rw-r--r--src/plugins/wmp/qwmpserviceprovider.cpp74
-rw-r--r--src/plugins/wmp/qwmpserviceprovider.h58
-rw-r--r--src/plugins/wmp/qwmpvideooverlay.cpp462
-rw-r--r--src/plugins/wmp/qwmpvideooverlay.h145
-rw-r--r--src/plugins/wmp/wmp.pro47
-rw-r--r--src/s60installs/backup_registration.xml8
-rw-r--r--src/s60installs/bwins/QtMultimediaKitu.def1624
-rw-r--r--src/s60installs/deviceconfiguration/.gitignore11
-rw-r--r--src/s60installs/deviceconfiguration/QtBearer{000a0000}.dllbin0 -> 28061 bytes
-rw-r--r--src/s60installs/deviceconfiguration/bld.inf57
-rw-r--r--src/s60installs/deviceconfiguration/mobilityconfig.prf5
-rw-r--r--src/s60installs/deviceconfiguration/qtmobility.confml16
-rw-r--r--src/s60installs/deviceconfiguration/qtmobility.iby134
-rw-r--r--src/s60installs/deviceconfiguration/qtmobility.sisx1
-rw-r--r--src/s60installs/deviceconfiguration/qtmobility_copy.implml10
-rw-r--r--src/s60installs/deviceconfiguration/qtmobility_stub.pkg12
-rw-r--r--src/s60installs/deviceconfiguration/qtmobility_stub.sisbin0 -> 324 bytes
-rw-r--r--src/s60installs/deviceconfiguration/qtmobilityconfig.xml13
-rw-r--r--src/s60installs/deviceconfiguration/qtmobilityexampleapps.pkg111
-rw-r--r--src/s60installs/deviceconfiguration/qtmobilityexamples.iby128
-rw-r--r--src/s60installs/deviceconfiguration/qtmobilityheaders.flm146
-rw-r--r--src/s60installs/deviceconfiguration/qtmobilitytests.iby47
-rw-r--r--src/s60installs/deviceconfiguration/symbian3_config.pri50
-rw-r--r--src/s60installs/deviceconfiguration/symbian3_qtmobility.pkg128
-rw-r--r--src/s60installs/eabi/QtMultimediaKitu.def1640
-rw-r--r--src/s60installs/s60installs.pro514
-rw-r--r--src/src.pro12
-rw-r--r--sync.profile35
-rw-r--r--tests/auto/auto.pro11
-rw-r--r--tests/auto/multimedia.pro41
-rw-r--r--tests/auto/qabstractvideobuffer/qabstractvideobuffer.pro9
-rw-r--r--tests/auto/qabstractvideobuffer/tst_qabstractvideobuffer.cpp134
-rw-r--r--tests/auto/qabstractvideosurface/qabstractvideosurface.pro9
-rw-r--r--tests/auto/qabstractvideosurface/tst_qabstractvideosurface.cpp312
-rw-r--r--tests/auto/qaudiocapturesource/qaudiocapturesource.pro9
-rw-r--r--tests/auto/qaudiocapturesource/tst_qaudiocapturesource.cpp360
-rw-r--r--tests/auto/qaudiodeviceinfo/qaudiodeviceinfo.pro9
-rw-r--r--tests/auto/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp207
-rw-r--r--tests/auto/qaudioformat/qaudioformat.pro9
-rw-r--r--tests/auto/qaudioformat/tst_qaudioformat.cpp184
-rw-r--r--tests/auto/qaudioinput/qaudioinput.pro18
-rwxr-xr-xtests/auto/qaudioinput/tst_qaudioinput.cpp814
-rwxr-xr-xtests/auto/qaudioinput/wavheader.cpp205
-rwxr-xr-xtests/auto/qaudioinput/wavheader.h80
-rw-r--r--tests/auto/qaudiooutput/qaudiooutput.pro18
-rwxr-xr-xtests/auto/qaudiooutput/tst_qaudiooutput.cpp962
-rwxr-xr-xtests/auto/qaudiooutput/wavheader.cpp205
-rwxr-xr-xtests/auto/qaudiooutput/wavheader.h80
-rw-r--r--tests/auto/qcamera/qcamera.pro15
-rw-r--r--tests/auto/qcamera/tst_qcamera.cpp2012
-rw-r--r--tests/auto/qcamerabackend/qcamerabackend.pro15
-rw-r--r--tests/auto/qcamerabackend/tst_qcamerabackend.cpp633
-rw-r--r--tests/auto/qdeclarativeaudio/qdeclarativeaudio.pro18
-rw-r--r--tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp1302
-rw-r--r--tests/auto/qdeclarativevideo/qdeclarativevideo.pro18
-rw-r--r--tests/auto/qdeclarativevideo/tst_qdeclarativevideo.cpp992
-rw-r--r--tests/auto/qgraphicsvideoitem/qgraphicsvideoitem.pro12
-rw-r--r--tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp675
-rw-r--r--tests/auto/qmediacontent/qmediacontent.pro7
-rw-r--r--tests/auto/qmediacontent/tst_qmediacontent.cpp176
-rw-r--r--tests/auto/qmediaimageviewer/images.qrc9
-rw-r--r--tests/auto/qmediaimageviewer/images/coverart.pngbin0 -> 230 bytes
-rw-r--r--tests/auto/qmediaimageviewer/images/image.jpgbin0 -> 2045 bytes
-rw-r--r--tests/auto/qmediaimageviewer/images/image.pngbin0 -> 230 bytes
-rw-r--r--tests/auto/qmediaimageviewer/images/invalid.png2
-rw-r--r--tests/auto/qmediaimageviewer/images/poster.pngbin0 -> 230 bytes
-rw-r--r--tests/auto/qmediaimageviewer/qmediaimageviewer.pro17
-rw-r--r--tests/auto/qmediaimageviewer/tst_qmediaimageviewer.cpp1036
-rw-r--r--tests/auto/qmediaobject/main.cpp77
-rw-r--r--tests/auto/qmediaobject/qmediaobject.pro27
-rw-r--r--tests/auto/qmediaobject/tst_qmediaobject.cpp359
-rw-r--r--tests/auto/qmediaobject/tst_qmediaobject.h177
-rw-r--r--tests/auto/qmediaobject/tst_qmediaobject_mmf.cpp278
-rw-r--r--tests/auto/qmediaobject/tst_qmediaobject_mmf.h81
-rw-r--r--tests/auto/qmediaobject/tst_qmediaobject_xa.cpp158
-rw-r--r--tests/auto/qmediaobject/tst_qmediaobject_xa.h83
-rwxr-xr-xtests/auto/qmediaplayer/main.cpp78
-rw-r--r--tests/auto/qmediaplayer/qmediaplayer.pro25
-rw-r--r--tests/auto/qmediaplayer/tst_qmediaplayer.cpp1019
-rwxr-xr-xtests/auto/qmediaplayer/tst_qmediaplayer.h435
-rwxr-xr-xtests/auto/qmediaplayer/tst_qmediaplayer_s60.cpp1708
-rwxr-xr-xtests/auto/qmediaplayer/tst_qmediaplayer_s60.h137
-rw-r--r--tests/auto/qmediaplayer/tst_qmediaplayer_xa.cpp1413
-rw-r--r--tests/auto/qmediaplayer/tst_qmediaplayer_xa.h194
-rw-r--r--tests/auto/qmediaplayerbackend/qmediaplayerbackend.pro23
-rw-r--r--tests/auto/qmediaplayerbackend/testdata/test.wavbin0 -> 88232 bytes
-rw-r--r--tests/auto/qmediaplayerbackend/tst_qmediaplayerbackend.cpp462
-rw-r--r--tests/auto/qmediaplaylist/qmediaplaylist.pro29
-rw-r--r--tests/auto/qmediaplaylist/testdata/test.m3u11
-rw-r--r--tests/auto/qmediaplaylist/testdata/testfile0
-rw-r--r--tests/auto/qmediaplaylist/testdata/testfile2#suffix0
-rw-r--r--tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp666
-rw-r--r--tests/auto/qmediaplaylistnavigator/qmediaplaylistnavigator.pro9
-rw-r--r--tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp318
-rw-r--r--tests/auto/qmediapluginloader/qmediapluginloader.pro15
-rw-r--r--tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp123
-rwxr-xr-xtests/auto/qmediarecorder/main.cpp80
-rw-r--r--tests/auto/qmediarecorder/qmediarecorder.pro18
-rwxr-xr-xtests/auto/qmediarecorder/s60common.h61
-rw-r--r--tests/auto/qmediarecorder/tst_qmediarecorder.cpp796
-rwxr-xr-xtests/auto/qmediarecorder/tst_qmediarecorder.h516
-rwxr-xr-xtests/auto/qmediarecorder/tst_qmediarecorder_mmf.cpp180
-rwxr-xr-xtests/auto/qmediarecorder/tst_qmediarecorder_mmf.h85
-rwxr-xr-xtests/auto/qmediarecorder/tst_qmediarecorder_xa.cpp323
-rwxr-xr-xtests/auto/qmediarecorder/tst_qmediarecorder_xa.h78
-rw-r--r--tests/auto/qmediaresource/qmediaresource.pro9
-rw-r--r--tests/auto/qmediaresource/tst_qmediaresource.cpp528
-rw-r--r--tests/auto/qmediaservice/qmediaservice.pro9
-rw-r--r--tests/auto/qmediaservice/tst_qmediaservice.cpp196
-rw-r--r--tests/auto/qmediaserviceprovider/qmediaserviceprovider.pro9
-rw-r--r--tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp489
-rw-r--r--tests/auto/qmediatimerange/qmediatimerange.pro9
-rw-r--r--tests/auto/qmediatimerange/tst_qmediatimerange.cpp739
-rw-r--r--tests/auto/qpaintervideosurface/qpaintervideosurface.pro11
-rw-r--r--tests/auto/qpaintervideosurface/tst_qpaintervideosurface.cpp1249
-rwxr-xr-xtests/auto/qradiotuner/main.cpp79
-rw-r--r--tests/auto/qradiotuner/qradiotuner.pro19
-rw-r--r--tests/auto/qradiotuner/tst_qradiotuner.cpp275
-rw-r--r--tests/auto/qradiotuner/tst_qradiotuner.h285
-rw-r--r--tests/auto/qradiotuner/tst_qradiotuner_s60.cpp170
-rw-r--r--tests/auto/qradiotuner/tst_qradiotuner_s60.h79
-rw-r--r--tests/auto/qradiotuner/tst_qradiotuner_xa.cpp224
-rw-r--r--tests/auto/qradiotuner/tst_qradiotuner_xa.h81
-rw-r--r--tests/auto/qvideoframe/qvideoframe.pro9
-rw-r--r--tests/auto/qvideoframe/tst_qvideoframe.cpp793
-rw-r--r--tests/auto/qvideosurfaceformat/qvideosurfaceformat.pro9
-rw-r--r--tests/auto/qvideosurfaceformat/tst_qvideosurfaceformat.cpp738
-rw-r--r--tests/auto/qvideowidget/qvideowidget.pro10
-rw-r--r--tests/auto/qvideowidget/tst_qvideowidget.cpp1567
-rw-r--r--tests/tests.pro5
1048 files changed, 206259 insertions, 0 deletions
diff --git a/bin/pathhelper b/bin/pathhelper
new file mode 100755
index 000000000..ba272d189
--- /dev/null
+++ b/bin/pathhelper
@@ -0,0 +1,59 @@
+#!/usr/bin/perl
+#############################################################################
+##
+## 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$
+## 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$
+##
+#############################################################################
+
+use strict;
+use warnings;
+use Cwd;
+use Cwd "abs_path";
+
+my $path = shift(@ARGV) or usage();
+my $resolvedpath = abs_path($path);
+print "$resolvedpath\n";
+
+exit 0;
+
+sub usage
+{
+ warn " Usage: pathhelper <path>\n";
+ warn " Converts <path> to an absolute path and returns it to the caller\n";
+ exit 2;
+}
diff --git a/config.tests/FmTxClient/FmTxClient.pro b/config.tests/FmTxClient/FmTxClient.pro
new file mode 100644
index 000000000..a6a71858d
--- /dev/null
+++ b/config.tests/FmTxClient/FmTxClient.pro
@@ -0,0 +1,10 @@
+CONFIG -= qt
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
+
+INCLUDEPATH += $$APP_LAYER_SYSTEMINCLUDE
+LIBS += -lhwrmfmtxclient
+
+
diff --git a/config.tests/FmTxClient/main.cpp b/config.tests/FmTxClient/main.cpp
new file mode 100644
index 000000000..32f47369d
--- /dev/null
+++ b/config.tests/FmTxClient/main.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** 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$
+** 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 <e32base.h>
+#include <hwrmfmtx.h>
+
+int main(int, char**)
+{
+ CHWRMFmTx *fmTX = CHWRMFmTx::NewL();
+ delete fmTX;
+}
+
diff --git a/config.tests/audiorouting_s60/audiorouting_s60.pro b/config.tests/audiorouting_s60/audiorouting_s60.pro
new file mode 100644
index 000000000..dc811944b
--- /dev/null
+++ b/config.tests/audiorouting_s60/audiorouting_s60.pro
@@ -0,0 +1,9 @@
+CONFIG -= qt
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
+
+#INCLUDEPATH += $$APP_LAYER_SYSTEMINCLUDE
+LIBS += -laudiooutputrouting
+
diff --git a/config.tests/audiorouting_s60/main.cpp b/config.tests/audiorouting_s60/main.cpp
new file mode 100644
index 000000000..b8ac5cc58
--- /dev/null
+++ b/config.tests/audiorouting_s60/main.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+int main(int, char**)
+{
+ return 0;
+}
+
diff --git a/config.tests/directshow/directshow.pro b/config.tests/directshow/directshow.pro
new file mode 100644
index 000000000..526519851
--- /dev/null
+++ b/config.tests/directshow/directshow.pro
@@ -0,0 +1,9 @@
+CONFIG -= qt
+CONFIG += console
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
+
+LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32
+
diff --git a/config.tests/directshow/main.cpp b/config.tests/directshow/main.cpp
new file mode 100644
index 000000000..69d47c56c
--- /dev/null
+++ b/config.tests/directshow/main.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** 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$
+** 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 <dshow.h>
+#include <d3d9.h>
+#include <vmr9.h>
+
+int main(int, char**)
+{
+ return 0;
+}
diff --git a/config.tests/evr/evr.pro b/config.tests/evr/evr.pro
new file mode 100644
index 000000000..bbdad3ffe
--- /dev/null
+++ b/config.tests/evr/evr.pro
@@ -0,0 +1,6 @@
+CONFIG -= qt
+CONFIG += console
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
diff --git a/config.tests/evr/main.cpp b/config.tests/evr/main.cpp
new file mode 100644
index 000000000..674b2ff8f
--- /dev/null
+++ b/config.tests/evr/main.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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$
+** 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 <evr.h>
+
+int main(int, char**)
+{
+ return 0;
+}
diff --git a/config.tests/gstreamer-appsrc/gstreamer-appsrc.pro b/config.tests/gstreamer-appsrc/gstreamer-appsrc.pro
new file mode 100644
index 000000000..6c003e4d9
--- /dev/null
+++ b/config.tests/gstreamer-appsrc/gstreamer-appsrc.pro
@@ -0,0 +1,19 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp
+
+CONFIG += link_pkgconfig
+
+PKGCONFIG += \
+ gstreamer-0.10 \
+ gstreamer-base-0.10 \
+ gstreamer-interfaces-0.10 \
+ gstreamer-audio-0.10 \
+ gstreamer-video-0.10 \
+ gstreamer-app-0.10
+
+
diff --git a/config.tests/gstreamer-appsrc/main.cpp b/config.tests/gstreamer-appsrc/main.cpp
new file mode 100644
index 000000000..4033efeb4
--- /dev/null
+++ b/config.tests/gstreamer-appsrc/main.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** 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$
+** 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$
+**
+****************************************************************************/
+
+#define GST_USE_UNSTABLE_API
+
+#include <gst/app/gstappsrc.h>
+
+int main(int argc, char** argv)
+{
+ return 0;
+}
diff --git a/config.tests/gstreamer-photography/gstreamer-photography.pro b/config.tests/gstreamer-photography/gstreamer-photography.pro
new file mode 100644
index 000000000..e2b530286
--- /dev/null
+++ b/config.tests/gstreamer-photography/gstreamer-photography.pro
@@ -0,0 +1,19 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp
+
+CONFIG += link_pkgconfig
+
+PKGCONFIG += \
+ gstreamer-0.10 \
+ gstreamer-base-0.10 \
+ gstreamer-interfaces-0.10 \
+ gstreamer-audio-0.10 \
+ gstreamer-video-0.10
+
+LIBS += -lgstphotography-0.10
+
diff --git a/config.tests/gstreamer-photography/main.cpp b/config.tests/gstreamer-photography/main.cpp
new file mode 100644
index 000000000..3a82121c9
--- /dev/null
+++ b/config.tests/gstreamer-photography/main.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** 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$
+** 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$
+**
+****************************************************************************/
+
+#define GST_USE_UNSTABLE_API
+
+#include <gst/interfaces/photography.h>
+#include <gst/interfaces/photography-enumtypes.h>
+
+int main(int argc, char** argv)
+{
+ return 0;
+}
diff --git a/config.tests/make/make.pro b/config.tests/make/make.pro
new file mode 100644
index 000000000..24ff56af2
--- /dev/null
+++ b/config.tests/make/make.pro
@@ -0,0 +1,11 @@
+message($$MAKEFILE_GENERATOR)
+contains(MAKEFILE_GENERATOR, SYMBIAN_ABLD) {
+ message(symbian-abld)
+} else:contains(MAKEFILE_GENERATOR, SYMBIAN_SBSV2) {
+ message(symbian-sbsv2)
+} else:contains(MAKEFILE_GENERATOR, MSVC)|contains(MAKEFILE_GENERATOR, MSVC.NET)|contains(MAKEFILE_GENERATOR, MSBUILD) {
+ message(win32-nmake)
+} else:contains(MAKEFILE_GENERATOR, MINGW) {
+ message(win32-mingw)
+}
+
diff --git a/config.tests/mmf_http_cookies/main.cpp b/config.tests/mmf_http_cookies/main.cpp
new file mode 100644
index 000000000..f4aa1c363
--- /dev/null
+++ b/config.tests/mmf_http_cookies/main.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** 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$
+** 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 "\epoc32\include\platform\mw\MMFSessionInfoCustomCommandConstants.h"
+
+int main(int argc, char *argv[])
+{
+ TMMFSessionInfoControllerMessage m;
+
+ return 0;
+}
diff --git a/config.tests/mmf_http_cookies/mmf_http_cookies.pro b/config.tests/mmf_http_cookies/mmf_http_cookies.pro
new file mode 100644
index 000000000..1f916a4c2
--- /dev/null
+++ b/config.tests/mmf_http_cookies/mmf_http_cookies.pro
@@ -0,0 +1,7 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp
diff --git a/config.tests/openmaxal_symbian/main.cpp b/config.tests/openmaxal_symbian/main.cpp
new file mode 100644
index 000000000..e9179c52e
--- /dev/null
+++ b/config.tests/openmaxal_symbian/main.cpp
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+int main(int, char**)
+{
+ return 0;
+}
diff --git a/config.tests/openmaxal_symbian/openmaxal_symbian.pro b/config.tests/openmaxal_symbian/openmaxal_symbian.pro
new file mode 100644
index 000000000..dd8bd065d
--- /dev/null
+++ b/config.tests/openmaxal_symbian/openmaxal_symbian.pro
@@ -0,0 +1,7 @@
+CONFIG -= qt
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
+
+LIBS += -lopenmaxal
diff --git a/config.tests/pulseaudio/pulseaudio.cpp b/config.tests/pulseaudio/pulseaudio.cpp
new file mode 100644
index 000000000..3c39cc218
--- /dev/null
+++ b/config.tests/pulseaudio/pulseaudio.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** 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$
+** 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 <pulse/pulseaudio.h>
+#include <pulse/glib-mainloop.h>
+
+#if !defined(PA_API_VERSION) || PA_API_VERSION-0 != 12
+# error "Incompatible PulseAudio API version"
+#endif
+
+int main(int, char **)
+{
+ const char *headers = pa_get_headers_version();
+ const char *library = pa_get_library_version();
+ pa_glib_mainloop_new(0);
+ return (headers - library) * 0;
+}
diff --git a/config.tests/pulseaudio/pulseaudio.pro b/config.tests/pulseaudio/pulseaudio.pro
new file mode 100644
index 000000000..6f121fed7
--- /dev/null
+++ b/config.tests/pulseaudio/pulseaudio.pro
@@ -0,0 +1,8 @@
+SOURCES = pulseaudio.cpp
+CONFIG -= qt
+LIBS +=
+CONFIG += link_pkgconfig
+
+PKGCONFIG += \
+ libpulse \
+ libpulse-mainloop-glib
diff --git a/config.tests/radioutility_s60/main.cpp b/config.tests/radioutility_s60/main.cpp
new file mode 100644
index 000000000..b8ac5cc58
--- /dev/null
+++ b/config.tests/radioutility_s60/main.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+int main(int, char**)
+{
+ return 0;
+}
+
diff --git a/config.tests/radioutility_s60/radioutility_s60.pro b/config.tests/radioutility_s60/radioutility_s60.pro
new file mode 100644
index 000000000..af46cacdb
--- /dev/null
+++ b/config.tests/radioutility_s60/radioutility_s60.pro
@@ -0,0 +1,9 @@
+CONFIG -= qt
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
+
+#INCLUDEPATH += $$APP_LAYER_SYSTEMINCLUDE
+LIBS += -lRadio_Utility
+
diff --git a/config.tests/surfaces_s60/main.cpp b/config.tests/surfaces_s60/main.cpp
new file mode 100644
index 000000000..8ee82f940
--- /dev/null
+++ b/config.tests/surfaces_s60/main.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** 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 <videoplayer2.h>
+
+
+int main(int, char**)
+{
+ CVideoPlayerUtility2 *utility;
+ return 0;
+}
diff --git a/config.tests/surfaces_s60/surfaces_s60.pro b/config.tests/surfaces_s60/surfaces_s60.pro
new file mode 100644
index 000000000..4695e6783
--- /dev/null
+++ b/config.tests/surfaces_s60/surfaces_s60.pro
@@ -0,0 +1,8 @@
+CONFIG -= qt
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
+
+INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE
+LIBS += -mediaclientvideo.lib \ No newline at end of file
diff --git a/config.tests/symbian_camera_camautofocus/main.cpp b/config.tests/symbian_camera_camautofocus/main.cpp
new file mode 100644
index 000000000..e9179c52e
--- /dev/null
+++ b/config.tests/symbian_camera_camautofocus/main.cpp
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+int main(int, char**)
+{
+ return 0;
+}
diff --git a/config.tests/symbian_camera_camautofocus/symbian_camera_camautofocus.pro b/config.tests/symbian_camera_camautofocus/symbian_camera_camautofocus.pro
new file mode 100644
index 000000000..276ebd5a1
--- /dev/null
+++ b/config.tests/symbian_camera_camautofocus/symbian_camera_camautofocus.pro
@@ -0,0 +1,7 @@
+CONFIG -= qt
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
+
+LIBS += -lCamAutoFocus_s
diff --git a/config.tests/symbian_camera_devvideorecord/main.cpp b/config.tests/symbian_camera_devvideorecord/main.cpp
new file mode 100644
index 000000000..e9179c52e
--- /dev/null
+++ b/config.tests/symbian_camera_devvideorecord/main.cpp
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+int main(int, char**)
+{
+ return 0;
+}
diff --git a/config.tests/symbian_camera_devvideorecord/symbian_camera_devvideorecord.pro b/config.tests/symbian_camera_devvideorecord/symbian_camera_devvideorecord.pro
new file mode 100644
index 000000000..d2fcab731
--- /dev/null
+++ b/config.tests/symbian_camera_devvideorecord/symbian_camera_devvideorecord.pro
@@ -0,0 +1,7 @@
+CONFIG -= qt
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
+
+LIBS += -ldevvideo
diff --git a/config.tests/symbian_camera_ecamadvsettings/main.cpp b/config.tests/symbian_camera_ecamadvsettings/main.cpp
new file mode 100644
index 000000000..e9179c52e
--- /dev/null
+++ b/config.tests/symbian_camera_ecamadvsettings/main.cpp
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+int main(int, char**)
+{
+ return 0;
+}
diff --git a/config.tests/symbian_camera_ecamadvsettings/symbian_camera_ecamadvsettings.pro b/config.tests/symbian_camera_ecamadvsettings/symbian_camera_ecamadvsettings.pro
new file mode 100644
index 000000000..9006fc6a9
--- /dev/null
+++ b/config.tests/symbian_camera_ecamadvsettings/symbian_camera_ecamadvsettings.pro
@@ -0,0 +1,7 @@
+CONFIG -= qt
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
+
+LIBS += -lecamadvsettings
diff --git a/config.tests/symbian_camera_snapshot/main.cpp b/config.tests/symbian_camera_snapshot/main.cpp
new file mode 100644
index 000000000..e9179c52e
--- /dev/null
+++ b/config.tests/symbian_camera_snapshot/main.cpp
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+int main(int, char**)
+{
+ return 0;
+}
diff --git a/config.tests/symbian_camera_snapshot/symbian_camera_snapshot.pro b/config.tests/symbian_camera_snapshot/symbian_camera_snapshot.pro
new file mode 100644
index 000000000..26a7bc2aa
--- /dev/null
+++ b/config.tests/symbian_camera_snapshot/symbian_camera_snapshot.pro
@@ -0,0 +1,7 @@
+CONFIG -= qt
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
+
+LIBS += -lecamsnapshot
diff --git a/config.tests/tools/which.test b/config.tests/tools/which.test
new file mode 100755
index 000000000..749a73bc3
--- /dev/null
+++ b/config.tests/tools/which.test
@@ -0,0 +1,40 @@
+#!/bin/sh
+#borrowed from Qt
+
+HOME=/dev/null
+export HOME
+
+unset which
+
+WHICH=`which which 2>/dev/null`
+if echo $WHICH | grep 'shell built-in command' >/dev/null 2>&1; then
+ WHICH=which
+elif [ -z "$WHICH" ]; then
+ if which which >/dev/null 2>&1; then
+ WHICH=which
+ else
+ for a in /usr/ucb /usr/bin /bin /usr/local/bin; do
+ if [ -x $a/which ]; then
+ WHICH=$a/which
+ break;
+ fi
+ done
+ fi
+fi
+
+if [ -z "$WHICH" ]; then
+ IFS=:
+ for a in $PATH; do
+ if [ -x $a/$1 ]; then
+ echo "$a/$1"
+ exit 0
+ fi
+ done
+else
+ a=`"$WHICH" "$1" 2>/dev/null`
+ if [ ! -z "$a" -a -x "$a" ]; then
+ echo "$a"
+ exit 0
+ fi
+fi
+exit 1
diff --git a/config.tests/tunerlib_s60/main.cpp b/config.tests/tunerlib_s60/main.cpp
new file mode 100644
index 000000000..763b92453
--- /dev/null
+++ b/config.tests/tunerlib_s60/main.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** 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$
+** 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$
+**
+****************************************************************************/
+
+int main(int, char**)
+{
+ return 0;
+}
+
diff --git a/config.tests/tunerlib_s60/tunerlib_s60.pro b/config.tests/tunerlib_s60/tunerlib_s60.pro
new file mode 100644
index 000000000..24c15a616
--- /dev/null
+++ b/config.tests/tunerlib_s60/tunerlib_s60.pro
@@ -0,0 +1,9 @@
+CONFIG -= qt
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
+
+#INCLUDEPATH += $$APP_LAYER_SYSTEMINCLUDE
+LIBS += -ltunerutility
+
diff --git a/config.tests/wmp/main.cpp b/config.tests/wmp/main.cpp
new file mode 100644
index 000000000..fe8225fb2
--- /dev/null
+++ b/config.tests/wmp/main.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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$
+** 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 <wmp.h>
+
+int main(int, char**)
+{
+ return 0;
+}
diff --git a/config.tests/wmp/wmp.pro b/config.tests/wmp/wmp.pro
new file mode 100644
index 000000000..b00754e59
--- /dev/null
+++ b/config.tests/wmp/wmp.pro
@@ -0,0 +1,9 @@
+CONFIG -= qt
+CONFIG += console
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
+
+LIBS += -lstrmiids -lole32 -lOleaut32 -luser32 -lgdi32
+
diff --git a/config.tests/wmsdk/main.cpp b/config.tests/wmsdk/main.cpp
new file mode 100644
index 000000000..e73ceafa6
--- /dev/null
+++ b/config.tests/wmsdk/main.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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$
+** 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 <wmsdk.h>
+
+int main(int, char**)
+{
+ return 0;
+}
diff --git a/config.tests/wmsdk/wmsdk.pro b/config.tests/wmsdk/wmsdk.pro
new file mode 100644
index 000000000..bbdad3ffe
--- /dev/null
+++ b/config.tests/wmsdk/wmsdk.pro
@@ -0,0 +1,6 @@
+CONFIG -= qt
+CONFIG += console
+TEMPLATE = app
+
+# Input
+SOURCES += main.cpp
diff --git a/configure b/configure
new file mode 100755
index 000000000..da1033a65
--- /dev/null
+++ b/configure
@@ -0,0 +1,443 @@
+#!/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 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$
+##
+#############################################################################
+
+# return status of 1 if absolute path as first argument
+# also prints the return status
+isAbsPath() {
+ slash=$(echo $1 | cut -c 1)
+ if [ "$slash" != "/" ]; then
+ echo 0
+ return 0
+ fi
+ echo 1
+ return 1
+}
+
+# Returns the absolute path for $1 for target $2
+# as an example $2 might have value "maemo5".
+# This is required because when building in scratchbox for
+# maemo we do not want to follow symbolic links that are
+# introduced by scratchbox
+absPath() {
+ if [ "$2" = "maemo5" -o "$2" = "maemo6" -o "$2" = "meego" ]; then
+ if [ `isAbsPath $1` = '1' ]; then
+ echo $1;
+ else
+ echo >&2 "Relative prefix/bin/lib/header/plugin paths are not supported for Maemo"
+ exit 1;
+ fi
+ else
+ PATH=`$relpath/bin/pathhelper $1`
+ echo $PATH
+ fi
+}
+
+
+# the current directory (shadow build dir)
+shadowpath=`/bin/pwd`
+# the name of this script
+relconf=`basename $0`
+# the directory of this script is the "source tree"
+relpath=`dirname $0`
+relpath=`(cd "$relpath"; /bin/pwd)`
+
+CONFIG_IN="$shadowpath/config.in"
+BUILD_UNITTESTS=
+BUILD_PUBLIC_UNITTESTS=
+BUILD_EXAMPLES=
+BUILD_DEMOS=
+BUILD_DOCS=yes
+BUILD_TOOLS=yes
+RELEASEMODE=
+BUILD_SILENT=
+LINUX_TARGET=
+LANGUAGES=
+QMAKE_CACHE="$shadowpath/.qmake.cache"
+QMAKE_EXEC=qmake
+LIB_PATH="lib"
+BIN_PATH="bin"
+PLUGIN_PATH="plugins"
+PLATFORM_CONFIG=
+MAC_SDK=
+QMKSPEC=
+OS="other"
+# By default, all modules are requested. Reset this later if -modules is supplied
+ORGANIZER_REQUESTED=yes
+TEST_USE_SIMULATOR=
+NFC_SYMBIAN=auto
+MAC_DEPLOY=
+
+usage()
+{
+ echo "Usage: configure [-prefix <dir>] [headerdir <dir>] [libdir <dir>]"
+ echo " [-bindir <dir>] [-tests] [-examples] [-no-docs]"
+ echo " [-no-tools] [-debug] [-release] [-silent]"
+ echo " [-modules <list>]"
+ echo
+ echo "Options:"
+ echo
+ echo "-prefix <dir> ..... This will install everything relative to <dir>"
+ echo " (default prefix: $shadowpath/install)"
+ echo "-headerdir <dir> .. Header files will be installed to <dir>"
+ echo " (default prefix: PREFIX/include)"
+ echo "-libdir <dir> ..... Libraries will be installed to <dir>"
+ echo " (default: PREFIX/lib)"
+ echo "-bindir <dir> ..... Executables will be installed to <dir>"
+ echo " (default: PREFIX/bin)"
+ echo "-plugindir <dir> .. Plug-ins will be installed to <dir>"
+ echo " (default: PREFIX/plugins)"
+ echo "-demosdir <dir> ... Demos will be installed to <dir>"
+ echo " (default: PREFIX/bin)"
+ echo "-examplesdir <dir> Examples will be installed to <dir>"
+ echo " (default PREFIX/bin)"
+ echo "-debug ............ Build with debugging symbols"
+ echo "-release .......... Build without debugging symbols"
+ echo "-silent ........... Reduces build output"
+ echo "-tests ............ Build unit tests (not build by default)"
+ echo " Note, this adds test symbols to all libraries"
+ echo " and should not be used for release builds."
+ echo "-examples ......... Build example applications"
+ echo "-demos ............ Build demo applications"
+ echo "-no-docs .......... Do not build documentation (build by default)"
+ echo "-no-tools ......... Do not build tools (build by default)"
+ echo "-modules <list> ... Restrict list of modules to build (default all supported)"
+ echo " Choose from: bearer contacts gallery location publishsubscribe"
+ echo " messaging multimedia systeminfo serviceframework"
+ echo " sensors versit organizer feedback connectivity"
+ echo " Modules should be separated by a space and surrounded"
+ echo " by double quotation. If a selected module depends on other modules"
+ echo " those modules (and their dependencies) will automatically be enabled."
+ echo "-maemo6 ........... Build Qt Mobility for Maemo6 (Harmattan)."
+ echo "-maemo5 ........... Build Qt Mobility for Maemo5 (Fremantle)."
+ echo "-meego ........... Build Qt Mobility for MeeGo."
+ echo "-sdk <sdk> ........ Build using Apple provided SDK <path/to/sdk>."
+ echo " example: -sdk /Developer/SDKs/MacOSX10.6.sdk"
+ echo "-languages ........ Languages/translations to be installed (e.g.: \"ar de ko\")."
+ echo " (default is empty)"
+ echo "-qmake-exec <name> Sets custom binary name for qmake binary"
+ echo " (default: qmake)"
+ echo "-no-nfc-symbian Disables the NFC Sybmian backend."
+# echo "-test-sim Use simulator backend for testing systeminfo"
+# echo "-staticconfig <name>"
+# echo " Avoids running of configuration tests. The default"
+# echo " values are sourced from features/platformconfig/<name>.pri"
+ echo "-mac-deploy .... Use this option for deploying QtMobility into Qt for use with macdeployqt tool"
+ echo " This overrides any -prefix that may be set."
+ echo
+
+ rm -f "$CONFIG_IN"
+ exit 1
+}
+
+rm -rf "$QMAKE_CACHE"
+CONFIG_LOG="$shadowpath/config.log"
+rm -rf "$CONFIG_LOG"
+
+while [ "$#" -gt 0 ]; do
+ case "$1" in
+ -h|-help|--help)
+ usage
+ ;;
+ -tests)
+ BUILD_UNITTESTS="yes"
+ ;;
+ -public-tests-only)
+ BUILD_PUBLIC_UNITTESTS="yes"
+ ;;
+ -demos)
+ BUILD_DEMOS="yes"
+ ;;
+ -examples)
+ BUILD_EXAMPLES="yes"
+ ;;
+ -no-docs)
+ BUILD_DOCS=
+ ;;
+ -no-tools)
+ BUILD_TOOLS=
+ ;;
+ -debug)
+ RELEASEMODE=debug
+ ;;
+ -release)
+ RELEASEMODE=release
+ ;;
+ -silent)
+ BUILD_SILENT=yes
+ ;;
+ -maemo5)
+ LINUX_TARGET=maemo5
+ ;;
+ -maemo6)
+ LINUX_TARGET=maemo6
+ ;;
+ -meego)
+ LINUX_TARGET=meego
+ ;;
+ -sdk)
+ MAC_SDK="$2"
+ shift
+ ;;
+ -qmake-exec)
+ QMAKE_EXEC="$2"
+ shift
+ ;;
+ -staticconfig)
+ PLATFORM_CONFIG=$2
+ shift
+ ;;
+ -languages)
+ LANGUAGES=$2
+ shift
+ ;;
+ -test-sim)
+ TEST_USE_SIMULATOR="yes"
+ ;;
+ -no-nfc-symbian)
+ NFC_SYMBIAN=no
+ ;;
+ -mac-deploy)
+ MAC_DEPLOY='yes'
+ shift
+ ;;
+ *)
+ echo "Unknown option: $1"
+ usage
+ ;;
+ esac
+ shift
+done
+
+if [ -z "$RELEASEMODE" ]; then
+ RELEASEMODE="debug"
+fi
+echo "CONFIG += $RELEASEMODE" > "$CONFIG_IN"
+
+
+if [ -n "$BUILD_SILENT" ]; then
+ echo "CONFIG += silent" >> "$CONFIG_IN"
+fi
+
+checkostype()
+{
+ match="Darwin"
+ if [ `uname -s` = "${match}" ]; then
+ OS="darwin"
+ QMKSPEC="-spec macx-g++"
+ if [[ `gcc --version` =~ .*llvm.* ]]; then
+ QMKSPEC="-spec macx-llvm"
+ else
+ QMKSPEC="-spec macx-g++"
+ fi
+ echo "QMAKESPEC = "$QMKSPEC >> "$CONFIG_IN"
+ fi
+}
+
+checkostype
+
+findUniversal()
+{
+ if [ -e "mac.inc" ]; then
+ rm mac.inc
+ fi
+ echo "contains(QT_CONFIG,x86): system(echo CONFIG+=x86 >> mac.inc)" > 2.pro
+ echo "contains(QT_CONFIG,ppc): system(echo CONFIG+=ppc >> mac.inc)" >> 2.pro
+ echo "contains(QT_CONFIG,ppc64): system(echo CONFIG+=ppc64 >> mac.inc)" >> 2.pro
+ echo "contains(QT_CONFIG,x86_64): system(echo CONFIG+=x86_64 >> mac.inc)" >> 2.pro
+ SOMETIME=`$QMAKE_EXEC $QMKSPEC 2.pro 2>&1`
+ rm 2.pro
+ if [ -e "mac.inc" ]; then
+ echo "exists(mac.inc): include(mac.inc)" >> "$CONFIG_IN"
+ fi
+}
+
+if [ "$OS" = "darwin" ] ; then
+ findUniversal
+fi
+
+if [ -n "$MAC_SDK" ]; then
+ QMAKE_MAC_SDK="$MAC_SDK"
+ echo "QMAKE_MAC_SDK = $QMAKE_MAC_SDK" >> "$CONFIG_IN"
+fi
+
+if [ -z "$BUILD_UNITTESTS" ]; then
+ echo "build_unit_tests = no" >> "$CONFIG_IN"
+else
+ echo "build_unit_tests = yes" >> "$CONFIG_IN"
+fi
+
+if [ -z "$BUILD_PUBLIC_UNITTESTS" ]; then
+ echo "build_public_unit_tests = no" >> "$CONFIG_IN"
+else
+ echo "build_public_unit_tests = yes" >> "$CONFIG_IN"
+fi
+
+if [ -z "$BUILD_EXAMPLES" ]; then
+ echo "build_examples = no" >> "$CONFIG_IN"
+else
+ echo "build_examples = yes" >> "$CONFIG_IN"
+fi
+
+if [ -z "$BUILD_DEMOS" ]; then
+ echo "build_demos = no" >> "$CONFIG_IN"
+else
+ echo "build_demos = yes" >> "$CONFIG_IN"
+fi
+
+if [ -z "$BUILD_DOCS" ]; then
+ echo "build_docs = no" >> "$CONFIG_IN"
+else
+ echo "build_docs = yes" >> "$CONFIG_IN"
+fi
+
+if [ -z "$BUILD_TOOLS" ]; then
+ echo "build_tools = no" >> "$CONFIG_IN"
+else
+ echo "build_tools = yes" >> "$CONFIG_IN"
+fi
+
+if [ -z "$TEST_USE_SIMULATOR" ]; then
+ echo "test_use_sim = no" >> "$CONFIG_IN"
+else
+ echo "test_use_sim = yes" >> "$CONFIG_IN"
+fi
+
+#process languages
+if [ -z "LANGUAGES" ]; then
+ echo "selected_languages =" >> "$CONFIG_IN"
+else
+ echo "selected_languages = $LANGUAGES" >> "$CONFIG_IN"
+fi
+
+
+echo "Configuring Qt MultimediaKit"
+echo
+
+WHICH="$relpath/config.tests/tools/which.test"
+
+printf "Checking available Qt"
+if ! "$WHICH" $QMAKE_EXEC 2>/dev/null 1>&2; then
+ QMAKE_EXEC_ALTERNATIVE=
+ if "$WHICH" qmake4 2>/dev/null 1>&2; then
+ QMAKE_EXEC_ALTERNATIVE=qmake4
+ elif "$WHICH" qmake-qt4 2>/dev/null 1>&2; then
+ QMAKE_EXEC_ALTERNATIVE=qmake-qt4
+ fi
+
+ if [ -z "$QMAKE_EXEC_ALTERNATIVE" ]; then
+ printf " ... Not found\n\n" >&2
+ echo >&2 "Cannot find "$QMAKE_EXEC" in your PATH.";
+ echo >&2 "Aborting."
+ exit 1
+ else
+ QMAKE_EXEC="$QMAKE_EXEC_ALTERNATIVE"
+ fi
+fi
+
+#we found a qmake binary
+printf " ... "
+$QMAKE_EXEC -query QT_VERSION
+
+# find out which make we want to use
+MAKE=
+for m in make gmake; do
+ if "$WHICH" $m >/dev/null 2>&1; then
+ MAKE=`$WHICH $m`
+ break
+ fi
+done
+if [ -z "$MAKE" ]; then
+ echo >&2 "Cannot find 'make' or 'gmake' in your PATH";
+ echo >&2 "Aborting."
+ exit 1
+fi
+
+compileTest()
+{
+ printf "Checking $1"
+ CURRENT_PWD=`pwd`
+
+ if [ "$shadowpath" = "$relpath" ]; then
+ #doing source tree build
+ cd "$relpath/config.tests/$2"
+ rm -rf ./$2
+ else
+ #using shadow build
+ rm -rf config.tests/$2
+ mkdir -p config.tests/$2
+ cd config.tests/$2
+ fi
+
+ $QMAKE_EXEC $QMKSPEC "$relpath/config.tests/$2/$2.pro" 2>> "$CONFIG_LOG" >> "$CONFIG_LOG"
+ printf " ."
+ "$MAKE" clean >> "$CONFIG_LOG"
+ printf "."
+ "$MAKE" >> "$CONFIG_LOG" 2>&1
+ printf ". "
+ if [ -e ./$2 ]; then
+ echo "OK"
+ echo "$2_enabled = yes" >> "$CONFIG_IN"
+ else
+ echo "Not Found"
+ echo "$2_enabled = no" >> "$CONFIG_IN"
+ fi
+ cd "$CURRENT_PWD"
+}
+
+if [ -z "$PLATFORM_CONFIG" ]; then
+#compile tests
+ compileTest "Gstreamer Photography" gstreamer-photography
+ compileTest "Gstreamer AppSrc" gstreamer-appsrc
+ compileTest "Pulse Audio" pulseaudio
+else
+ echo "Skipping configure tests"
+ echo "Loading ... features/platformconfig/$PLATFORM_CONFIG.pri"
+ if [ ! -f "$relpath/features/platformconfig/$PLATFORM_CONFIG.pri" ]; then
+ echo "Invalid platform configuration $PLATFORM_CONFIG.pri"
+ exit 1;
+ else
+ echo "include(\$\${QT_MOBILITY_SOURCE_TREE}/features/platformconfig/$PLATFORM_CONFIG.pri)" >> "$CONFIG_IN"
+ fi
+fi
+
+mv "$CONFIG_IN" config.pri
+
diff --git a/configure.bat b/configure.bat
new file mode 100644
index 000000000..0b57a3fad
--- /dev/null
+++ b/configure.bat
@@ -0,0 +1,806 @@
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: 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$
+:: 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$
+::
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+@echo off
+
+set QT_MOBILITY_PREFIX= C:\QtMobility
+set BUILD_PATH=%CD%
+set SOURCE_PATH= %~dp0
+cd /D %SOURCE_PATH%
+set SOURCE_PATH=%CD%
+cd /D %BUILD_PATH%
+
+set PROJECT_CONFIG=%BUILD_PATH%\config.in
+set PROJECT_LOG=%BUILD_PATH%\config.log
+set RELEASEMODE=release
+set WIN32_RELEASEMODE=debug_and_release build_all
+set QT_MOBILITY_LIB=
+set BUILD_UNITTESTS=no
+set BUILD_PUBLIC_UNITTESTS=no
+set BUILD_EXAMPLES=no
+set BUILD_DEMOS=no
+set BUILD_DOCS=yes
+set BUILD_TOOLS=yes
+set LANGUAGES_CONFIG=
+set MOBILITY_MODULES=bearer location contacts systeminfo publishsubscribe versit messaging sensors serviceframework multimedia gallery organizer feedback connectivity
+set MOBILITY_MODULES_UNPARSED=
+set VC_TEMPLATE_OPTION=
+set QT_PATH=
+set QMAKE_CACHE=%BUILD_PATH%\.qmake.cache
+set PLATFORM_CONFIG=
+set NFC_SYMBIAN=auto
+
+REM By default, all modules are requested. Reset this later if -modules is supplied
+set ORGANIZER_REQUESTED=yes
+
+if exist "%QMAKE_CACHE%" del /Q %QMAKE_CACHE%
+if exist "%PROJECT_LOG%" del /Q %PROJECT_LOG%
+if exist "%PROJECT_CONFIG%" del /Q %PROJECT_CONFIG%
+
+echo QT_MOBILITY_SOURCE_TREE = %SOURCE_PATH:\=/% > %QMAKE_CACHE%
+echo QT_MOBILITY_BUILD_TREE = %BUILD_PATH:\=/% >> %QMAKE_CACHE%
+set QMAKE_CACHE=
+
+:cmdline_parsing
+if "%1" == "" goto startProcessing
+if "%1" == "-debug" goto debugTag
+if "%1" == "-release" goto releaseTag
+if "%1" == "-silent" goto silentTag
+if "%1" == "-prefix" goto prefixTag
+if "%1" == "-libdir" goto libTag
+if "%1" == "-bindir" goto binTag
+if "%1" == "-headerdir" goto headerTag
+if "%1" == "-plugindir" goto pluginTag
+if "%1" == "-examplesdir" goto examplesDirTag
+if "%1" == "-demosdir" goto demosDirTag
+if "%1" == "-tests" goto testTag
+if "%1" == "-public-tests-only" goto publicTestTag
+if "%1" == "-examples" goto exampleTag
+if "%1" == "-demos" goto demosTag
+if "%1" == "-qt" goto qtTag
+if "%1" == "-vc" goto vcTag
+if "%1" == "-no-docs" goto nodocsTag
+if "%1" == "-no-tools" goto noToolsTag
+if "%1" == "-modules" goto modulesTag
+if "%1" == "/?" goto usage
+if "%1" == "-h" goto usage
+if "%1" == "-help" goto usage
+if "%1" == "--help" goto usage
+if "%1" == "-symbian-unfrozen" goto unfrozenTag
+if "%1" == "-staticconfig" goto staticConfigTag
+if "%1" == "-languages" goto languagesTag
+if "%1" == "-no-nfc-symbian" goto noNfcSymbianTag
+
+echo Unknown option: "%1"
+goto usage
+
+:usage
+echo Usage: configure.bat [-prefix (dir)] [headerdir (dir)] [libdir (dir)]
+ echo [-bindir (dir)] [-tests] [-examples]
+ echo [-debug] [-release] [-silent]
+ echo.
+ echo Options:
+ echo.
+ echo -prefix (dir) ..... This will install everything relative to dir
+ echo (default prefix: C:\QtMobility)
+ echo -headerdir (dir) .. Header files will be installed to dir
+ echo (default prefix: PREFIX/include)
+ echo -libdir (dir) ..... Libraries will be installed to dir
+ echo (default PREFIX/lib)
+ echo -bindir (dir) ..... Executables will be installed to dir
+ echo (default PREFIX/bin)
+ echo -plugindir (dir) .. Plug-ins will be installed to dir
+ echo (default PREFIX/plugins)
+ echo -examplesdir (dir) Examples will be installed to dir
+ echo (default PREFIX/bin)
+ echo -demosdir (dir) ... Demos will be installed to dir
+ echo (default PREFIX/bin)
+ echo -debug ............ Build with debugging symbols
+ echo -release .......... Build without debugging symbols
+ echo -silent ........... Reduces build output
+ echo -tests ............ Build unit tests (not build by default)
+ echo Note, this adds test symbols to all libraries
+ echo and should not be used for release builds.
+ echo -examples ......... Build example applications
+ echo -demos ............ Build demo applications
+ echo -no-docs .......... Do not build documentation (build by default)
+ echo -modules ^<list^> ... Build only the specified modules (default all)
+ echo Choose from: bearer contacts gallery location publishsubscribe
+ echo messaging multimedia systeminfo serviceframework
+ echo sensors versit organizer feedback connectivity
+ echo Modules should be separated by a space and surrounded
+ echo by double quotation. If a selected module depends on other modules
+ echo those modules (and their dependencies) will automatically be enabled.
+ echo -vc ............... Generate Visual Studio make files
+ echo -languages ........ Languages/translations to be installed (e.g.: ar de ko)
+ echo (default is empty)
+ echo -no-nfc-symbian ... Disables the NFC Symbian backend.
+
+
+if exist "%PROJECT_CONFIG%" del %PROJECT_CONFIG%
+goto exitTag
+
+:qtTag
+shift
+set QT_PATH=%1\
+shift
+goto cmdline_parsing
+
+:noNfcSymbianTag
+shift
+set NFC_SYMBIAN=no
+goto cmdline_parsing
+
+:languagesTag
+shift
+:: %1 can have leading/trailing quotes, so we can't use if "%1" == ""
+if xx%1xx == xxxx (
+ echo. >&2
+ echo >&2The -languages option requires a list of languages.
+ echo. >&2
+ goto usage
+)
+
+:: Remove leading/trailing quotes, if we have them
+set MOBILITY_LANGUAGES_UNPARSED=xxx%1xxx
+set MOBILITY_LANGUAGES_UNPARSED=%MOBILITY_LANGUAGES_UNPARSED:"xxx=%
+set MOBILITY_LANGUAGES_UNPARSED=%MOBILITY_LANGUAGES_UNPARSED:xxx"=%
+set MOBILITY_LANGUAGES_UNPARSED=%MOBILITY_LANGUAGES_UNPARSED:xxx=%
+
+REM for now we don't check the languages for their validity
+set LANGUAGES_CONFIG=
+set LANGUAGES_CONFIG= %MOBILITY_LANGUAGES_UNPARSED%
+echo Selected Languages: %LANGUAGES_CONFIG%
+shift
+goto cmdline_parsing
+
+:staticConfigTag
+shift
+set PLATFORM_CONFIG=%1
+shift
+goto cmdline_parsing
+
+:debugTag
+if "%RELEASEMODE%" == "release" set RELEASEMODE=debug
+set WIN32_RELEASEMODE=
+shift
+goto cmdline_parsing
+
+:releaseTag
+if "%RELEASEMODE%" == "debug" set RELEASEMODE=release
+set WIN32_RELEASEMODE=
+shift
+goto cmdline_parsing
+
+:silentTag
+echo CONFIG += silent > %PROJECT_CONFIG%
+shift
+goto cmdline_parsing
+
+:prefixTag
+shift
+set QT_MOBILITY_PREFIX=%1
+shift
+goto cmdline_parsing
+
+:libTag
+shift
+echo QT_MOBILITY_LIB = %1 >> %PROJECT_CONFIG%
+shift
+goto cmdline_parsing
+
+:binTag
+shift
+echo QT_MOBILITY_BIN = %1 >> %PROJECT_CONFIG%
+shift
+goto cmdline_parsing
+
+:headerTag
+shift
+echo QT_MOBILITY_INCLUDE = %1 >> %PROJECT_CONFIG%
+shift
+goto cmdline_parsing
+
+:pluginTag
+shift
+echo QT_MOBILITY_PLUGINS = %1 >> %PROJECT_CONFIG%
+shift
+echo
+goto cmdline_parsing
+
+:examplesDirTag
+shift
+echo QT_MOBILITY_EXAMPLES = %1 >> %PROJECT_CONFIG%
+shift
+echo
+goto cmdline_parsing
+
+:demosDirTag
+shift
+echo QT_MOBILITY_DEMOS =%1 >> %PROJECT_CONFIG%
+shift
+echo
+goto cmdline_parsing
+
+:unfrozenTag
+REM Should never be used in release builds
+REM Some SDK's seem to exclude Q_AUTOTEST_EXPORT symbols if the
+REM libraries are frozen. This breaks unit tests relying on the auto test exports
+REM This flag unfreezes the SYMBIAN libraries for the purpose of unit test building.
+REM Ideally this should be connected to '-tests' option but that would prevent
+REM integration testing for frozen symbols as the CI system should test unit tests
+REM and frozen symbol compliance.
+echo symbian_symbols_unfrozen = 1 >> %PROJECT_CONFIG%
+shift
+goto cmdline_parsing
+
+:testTag
+set BUILD_UNITTESTS=yes
+shift
+goto cmdline_parsing
+
+:publicTestTag
+set BUILD_PUBLIC_UNITTESTS=yes
+shift
+goto cmdline_parsing
+
+:exampleTag
+set BUILD_EXAMPLES=yes
+shift
+goto cmdline_parsing
+
+:demosTag
+set BUILD_DEMOS=yes
+shift
+goto cmdline_parsing
+
+:vcTag
+shift
+set VC_TEMPLATE_OPTION=-tp vc
+goto cmdline_parsing
+
+:nodocsTag
+set BUILD_DOCS=no
+shift
+goto cmdline_parsing
+
+:noToolsTag
+set BUILD_TOOLS=no
+shift
+goto cmdline_parsing
+
+:modulesTag
+shift
+:: %1 can have leading/trailing quotes, so we can't use if "%1" == ""
+if xx%1xx == xxxx (
+ echo. >&2
+ echo >&2The -modules option requires a list of modules.
+ echo. >&2
+ goto usage
+)
+
+:: Remove leading/trailing quotes, if we have them
+set MOBILITY_MODULES_UNPARSED=xxx%1xxx
+set MOBILITY_MODULES_UNPARSED=%MOBILITY_MODULES_UNPARSED:"xxx=%
+set MOBILITY_MODULES_UNPARSED=%MOBILITY_MODULES_UNPARSED:xxx"=%
+set MOBILITY_MODULES_UNPARSED=%MOBILITY_MODULES_UNPARSED:xxx=%
+
+REM reset default modules as we expect a modules list
+set MOBILITY_MODULES=
+set ORGANIZER_REQUESTED=no
+
+echo Checking selected modules:
+:modulesTag2
+
+for /f "tokens=1,*" %%a in ("%MOBILITY_MODULES_UNPARSED%") do (
+ set FIRST=%%a
+ set REMAINING=%%b
+)
+
+: What we want is a switch as we need to check module name and only want to
+: distinguish between false and correct module names being passed
+if %FIRST% == bearer (
+ echo Bearer Management selected
+) else if %FIRST% == contacts (
+ echo Contacts selected
+) else if %FIRST% == location (
+ echo Location selected
+) else if %FIRST% == messaging (
+ echo Messaging selected
+) else if %FIRST% == multimedia (
+ echo Multimedia selected
+) else if %FIRST% == publishsubscribe (
+ echo PublishSubscribe selected
+) else if %FIRST% == systeminfo (
+ echo Systeminfo selected
+) else if %FIRST% == serviceframework (
+ echo ServiceFramework selected
+) else if %FIRST% == versit (
+ echo Versit selected ^(implies Contacts^)
+) else if %FIRST% == organizer (
+ echo Organizer selected
+ set ORGANIZER_REQUESTED=yes
+) else if %FIRST% == feedback (
+ echo Feedback selected
+) else if %FIRST% == sensors (
+ echo Sensors selected
+) else if %FIRST% == gallery (
+ echo Gallery selected
+) else if %FIRST% == connectivity (
+ echo Connectivity selected
+) else (
+ echo Unknown module %FIRST%
+ goto errorTag
+)
+
+set MOBILITY_MODULES=%MOBILITY_MODULES% %FIRST%
+
+if "%REMAINING%" == "" (
+ shift
+) else (
+ set MOBILITY_MODULES_UNPARSED=%REMAINING%
+ goto modulesTag2
+)
+
+SET REMAINING=
+SET FIRST=
+goto cmdline_parsing
+
+:startProcessing
+
+echo CONFIG += %RELEASEMODE% >> %PROJECT_CONFIG%
+echo CONFIG_WIN32 += %WIN32_RELEASEMODE% %RELEASEMODE% >> %PROJECT_CONFIG%
+set RELEASEMODE=
+set WIN32_RELEASEMODE=
+
+set CURRENTDIR=%CD%
+echo %CURRENTDIR%
+if exist %QT_MOBILITY_PREFIX% goto prefixExists
+mkdir %QT_MOBILITY_PREFIX%
+if errorlevel 1 goto invalidPrefix
+cd /D %QT_MOBILITY_PREFIX%
+set QT_MOBILITY_PREFIX=%CD%
+cd /D %CURRENTDIR%
+rd /S /Q %QT_MOBILITY_PREFIX%
+goto endprefixProcessing
+
+:invalidPrefix
+echo "%QT_MOBILITY_PREFIX%" is not a valid directory path.
+goto :exitTag
+
+:prefixExists
+cd /D %QT_MOBILITY_PREFIX%
+set QT_MOBILITY_PREFIX=%CD%
+cd /D %CURRENTDIR%
+
+:endprefixProcessing
+echo QT_MOBILITY_PREFIX = %QT_MOBILITY_PREFIX:\=/% >> %PROJECT_CONFIG%
+
+echo build_unit_tests = %BUILD_UNITTESTS% >> %PROJECT_CONFIG%
+set BUILD_UNITTESTS=
+
+echo build_public_unit_tests = %BUILD_PUBLIC_UNITTESTS% >> %PROJECT_CONFIG%
+set BUILD_PUBLIC_UNITTESTS=
+
+echo build_examples = %BUILD_EXAMPLES% >> %PROJECT_CONFIG%
+set BUILD_EXAMPLES=
+
+echo build_demos = %BUILD_DEMOS% >> %PROJECT_CONFIG%
+set BUILD_DEMOS=
+
+echo build_docs = %BUILD_DOCS% >> %PROJECT_CONFIG%
+set BUILD_DOCS=
+
+echo build_tools = %BUILD_TOOLS% >> %PROJECT_CONFIG%
+set BUILD_TOOLS=
+
+echo qmf_enabled = no >> %PROJECT_CONFIG%
+
+echo !symbian:isEmpty($$QT_MOBILITY_INCLUDE):QT_MOBILITY_INCLUDE=$$QT_MOBILITY_PREFIX/include >> %PROJECT_CONFIG%
+echo isEmpty($$QT_MOBILITY_LIB):QT_MOBILITY_LIB=$$QT_MOBILITY_PREFIX/lib >> %PROJECT_CONFIG%
+echo isEmpty($$QT_MOBILITY_BIN):QT_MOBILITY_BIN=$$QT_MOBILITY_PREFIX/bin >> %PROJECT_CONFIG%
+echo isEmpty($$QT_MOBILITY_PLUGINS):QT_MOBILITY_PLUGINS=$$QT_MOBILITY_PREFIX/plugins >> %PROJECT_CONFIG%
+echo isEmpty($$QT_MOBILITY_EXAMPLES):QT_MOBILITY_EXAMPLES=$$QT_MOBILITY_PREFIX/bin >> %PROJECT_CONFIG%
+echo isEmpty($$QT_MOBILITY_DEMOS):QT_MOBILITY_DEMOS=$$QT_MOBILITY_PREFIX/bin >> %PROJECT_CONFIG%
+
+echo selected_languages = %LANGUAGES_CONFIG% >> %PROJECT_CONFIG%
+
+echo mobility_modules = %MOBILITY_MODULES% >> %PROJECT_CONFIG%
+echo contains(mobility_modules,versit): mobility_modules *= contacts >> %PROJECT_CONFIG%
+echo contains(mobility_modules,connectivity): mobility_modules *= serviceframework >> %PROJECT_CONFIG%
+
+echo Checking available Qt
+call %QT_PATH%qmake -v >> %PROJECT_LOG% 2>&1
+if errorlevel 1 goto qmakeNotFound
+goto qmakeFound
+:qmakeNotFound
+echo ... Not found >> %PROJECT_LOG% 2>&1
+if "%QT_PATH%" == "" (
+ echo >&2Cannot find 'qmake' in your PATH.
+ echo >&2Your PATH is: "%PATH%"
+) else (
+ echo >&2Cannot find 'qmake' in "%QT_PATH%".
+)
+echo >&2Aborting.
+goto errorTag
+
+:qmakeFound
+call %QT_PATH%qmake -query QT_VERSION
+
+goto checkMake
+
+REM Detect make tool
+:makeTest
+setlocal
+ set CURRENT_PWD=%CD%
+
+ if %BUILD_PATH% == %SOURCE_PATH% (
+ cd %SOURCE_PATH%\config.tests\make
+ if exist make del make
+ ) else (
+ rmdir /S /Q config.tests\make
+ mkdir config.tests\make
+ cd config.tests\make
+ )
+
+ for /f "tokens=2,3" %%a in ('call %QT_PATH%qmake %SOURCE_PATH%\config.tests\make\make.pro 2^>^&1 1^>NUL') do (
+ if "%%a" == "MESSAGE:" (
+ set BUILDSYSTEM=%%b)
+ )
+
+ if "%BUILDSYSTEM%" == "symbian-abld" (
+ call make -h >> %PROJECT_LOG% 2>&1
+ if not errorlevel 1 (
+ echo ... Symbian abld make found.
+ set MAKE=make
+ )
+ ) else if "%BUILDSYSTEM%" == "symbian-sbsv2" (
+ call make -h >> %PROJECT_LOG% 2>&1
+ if not errorlevel 1 (
+ echo ... Symbian sbsv2 make found.
+ set MAKE=make
+ )
+ ) else if "%BUILDSYSTEM%" == "win32-nmake" (
+ call nmake /? >> %PROJECT_LOG% 2>&1
+ if not errorlevel 1 (
+ echo ... nmake found.
+ set MAKE=nmake
+ )
+ ) else if "%BUILDSYSTEM%" == "win32-mingw" (
+ call mingw32-make -v >> %PROJECT_LOG% 2>&1
+ if not errorlevel 1 (
+ echo ... mingw32-make found.
+ set MAKE=mingw32-make
+ )
+ ) else (
+ echo ... Unknown target environment %BUILDSYSTEM%.
+ )
+ call cd %CURRENT_PWD%
+call endlocal&set %1=%MAKE%&set %2=%BUILDSYSTEM%&goto :EOF
+
+:checkMake
+echo Checking make
+call :makeTest MOBILITY_MAKE MOBILITY_BUILDSYSTEM
+if not "%MOBILITY_MAKE%" == "" goto compileTests
+
+echo >&2Cannot find 'nmake', 'mingw32-make' or 'make' in your PATH
+echo >&2Aborting.
+goto errorTag
+
+:compileTest
+setlocal
+ @echo off
+ echo Checking %1
+ set CURRENT_PWD=%CD%
+
+ if %BUILD_PATH% == %SOURCE_PATH% (
+ cd %SOURCE_PATH%\config.tests\%2
+ if exist %2 del %2
+ ) else (
+ rmdir /S /Q config.tests\%2
+ mkdir config.tests\%2
+ cd config.tests\%2
+ )
+
+ call %QT_PATH%qmake %SOURCE_PATH%\config.tests\%2\%2.pro >> %PROJECT_LOG% 2>&1
+
+ set FAILED=0
+ if "%MOBILITY_BUILDSYSTEM%" == "symbian-sbsv2" (
+ call %MOBILITY_MAKE% release-armv5 >> %PROJECT_LOG% 2>&1
+ for /f "tokens=2" %%i in ('%MOBILITY_MAKE% release-armv5 SBS^="@sbs --check"') do set FAILED=1
+ ) else if "%MOBILITY_BUILDSYSTEM%" == "symbian-abld" (
+ call %MOBILITY_MAKE% release-gcce >> %PROJECT_LOG% 2>&1
+ for /f "tokens=2" %%i in ('%MOBILITY_MAKE% release-gcce ABLD^="@ABLD.BAT -c" 2^>^&1') do if not %%i == bldfiles set FAILED=1
+ ) else (
+ REM Make for other builds
+ call %MOBILITY_MAKE% >> %PROJECT_LOG% 2>&1
+ REM have to check error level for windows / other builds to be sure.
+ if errorlevel 1 (
+ set FAILED=1
+ )
+ )
+
+ if %FAILED% == 0 (
+ echo ... OK
+ echo %2_enabled = yes >> %PROJECT_CONFIG%
+ ) else (
+ echo ... Not Found
+ echo %2_enabled = no >> %PROJECT_CONFIG%
+ )
+
+ cd %CURRENT_PWD%
+endlocal&goto :EOF
+
+:compileTests
+
+REM No reason to do config tests if we got a platform configuration
+if not "%PLATFORM_CONFIG%" == "" goto platformconfig
+
+REM We shouldn't enable some of these if the corresponding modules are not enabled
+echo.
+echo Start of compile tests
+REM compile tests go here.
+for /f "tokens=3" %%i in ('call %QT_PATH%qmake %SOURCE_PATH%\config.tests\make\make.pro 2^>^&1 1^>NUL') do set BUILDSYSTEM=%%i
+if "%BUILDSYSTEM%" == "symbian-abld" goto symbianTests
+if "%BUILDSYSTEM%" == "symbian-sbsv2" (
+ perl -S %SOURCE_PATH%\bin\compilercheck.pl
+ goto symbianTests
+)
+goto windowsTests
+
+:symbianTests
+
+call :compileTest LBT lbt
+call :compileTest SNAP snap
+call :compileTest OCC occ
+call :compileTest SymbianENote symbianenote
+call :compileTest SymbianContactSIM symbiancntsim
+call :compileTest SymbianContactModel symbiancntmodel
+call :compileTest SymbianContactModelv2 symbiancntmodelv2
+call :compileTest S60_Sensor_API sensors_s60_31
+call :compileTest Symbian_Sensor_Framework sensors_symbian
+call :compileTest Sensor_Framework_Light sensors_symbian_light
+call :compileTest Symbian_Hb hb_symbian
+call :compileTest Audiorouting_s60 audiorouting_s60
+call :compileTest Tunerlibrary_for_3.1 tunerlib_s60
+call :compileTest RadioUtility_for_post_3.1 radioutility_s60
+REM Currently not being supported
+REM call :compileTest OpenMaxAl_support openmaxal_symbian
+call :compileTest Surfaces_s60 surfaces_s60
+call :compileTest Symbian_Messaging_Freestyle messaging_freestyle
+call :compileTest Symbian_Messaging_Freestyle_MAPI12 messaging_freestyle_mapi12
+call :compileTest callinformation_symbian callinformation_symbian
+call :compileTest IMMERSION immersion
+call :compileTest Symbian_CamAutoFocus_31 symbian_camera_camautofocus
+call :compileTest Symbian_ECamAdvancedSettings_Post31 symbian_camera_ecamadvsettings
+call :compileTest Symbian_DevVideoRecord symbian_camera_devvideorecord
+call :compileTest Symbian_SnapShotAPI symbian_camera_snapshot
+call :compileTest AdvancedTouchFeedback advancedtouchfeedback
+call :compileTest CHWRMHaptics chwrmhaptics
+call :compileTest MDS mds
+call :compileTest MDS_25 mds_25
+call :compileTest MDS_25_92MCL mds_25_92mcl
+if "%NFC_SYMBIAN%" == "auto" (
+ call :compileTest Symbian_NFC nfc_symbian
+) else (
+ echo nfc_symbian_enabled = no >> %PROJECT_CONFIG%
+)
+call :compileTest BTEngineConnectionManager_Symbian btengconnman_symbian
+call :compileTest BTEngineDeviceManager_Symbian btengdevman_symbian
+call :compileTest LockandFlipKeys LockandFlipPSkeys
+call :compileTest FmTxClientCheck FmTxClient
+call :compileTest DiskNotifyClientCheck DiskNotifyClient
+call :compileTest ThermalStatus_Symbian thermalstatus_symbian
+call :compileTest Flextimer_Symbian symbianflextimer
+call :compileTest ETelPacketservice_symbian etelpacketservice_symbian
+call :compileTest mmf_http_cookies mmf_http_cookies
+goto noTests
+
+:windowsTests
+
+call :compileTest DirectShow directshow
+call :compileTest WindowsMediaSDK wmsdk
+call :compileTest WindowMediaPlayer wmp
+call :compileTest EnhancedVideoRenderer evr
+
+:noTests
+
+echo End of compile tests
+echo.
+echo.
+goto processHeaders
+
+:platformconfig
+
+echo.
+echo Skipping configure tests
+echo Loading ... features\platformconfig\%PLATFORM_CONFIG%.pri
+
+if not exist "%SOURCE_PATH%\features\platformconfig\%PLATFORM_CONFIG%.pri" (
+ echo >&2Invalid platform configuration %PLATFORM_CONFIG%.pri
+ goto errorTag
+)
+echo include($${QT_MOBILITY_SOURCE_TREE}/features/platformconfig/%PLATFORM_CONFIG%.pri) >> %PROJECT_CONFIG%
+
+:processHeaders
+REM we could skip generating headers if a module is not enabled
+if not exist "%BUILD_PATH%\features" mkdir %BUILD_PATH%\features
+if not exist "%BUILD_PATH%\features\strict_flags.prf" copy %SOURCE_PATH%\features\strict_flags.prf %BUILD_PATH%\features
+
+echo Generating Mobility Headers...
+rd /s /q %BUILD_PATH%\include
+mkdir %BUILD_PATH%\include
+perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include %SOURCE_PATH%\src\global
+
+set MODULES_TEMP=%MOBILITY_MODULES%
+
+:generateHeaders
+
+for /f "tokens=1,*" %%a in ("%MODULES_TEMP%") do (
+ set FIRST=%%a
+ set REMAINING=%%b
+)
+
+if %FIRST% == bearer (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtBearer %SOURCE_PATH%\src\bearer
+) else if %FIRST% == contacts (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtContacts %SOURCE_PATH%\src\contacts
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtContacts %SOURCE_PATH%\src\contacts\requests
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtContacts %SOURCE_PATH%\src\contacts\filters
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtContacts %SOURCE_PATH%\src\contacts\details
+) else if %FIRST% == location (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtLocation %SOURCE_PATH%\src\location
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtLocation %SOURCE_PATH%\src\location\landmarks
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtLocation %SOURCE_PATH%\src\location\maps
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtLocation %SOURCE_PATH%\src\location\maps\tiled
+) else if %FIRST% == messaging (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtMessaging %SOURCE_PATH%\src\messaging
+) else if %FIRST% == multimedia (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtMultimediaKit %SOURCE_PATH%\src\multimedia
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtMultimediaKit %SOURCE_PATH%\src\multimedia\audio
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtMultimediaKit %SOURCE_PATH%\src\multimedia\video
+) else if %FIRST% == publishsubscribe (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtPublishSubscribe %SOURCE_PATH%\src\publishsubscribe
+) else if %FIRST% == systeminfo (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtSystemInfo %SOURCE_PATH%\src\systeminfo
+) else if %FIRST% == serviceframework (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtServiceFramework %SOURCE_PATH%\src\serviceframework
+) else if %FIRST% == versit (
+ REM versit implies contacts. organizer includes might also be necessary
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtVersit %SOURCE_PATH%\src\versit
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtContacts %SOURCE_PATH%\src\contacts
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtContacts %SOURCE_PATH%\src\contacts\requests
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtContacts %SOURCE_PATH%\src\contacts\filters
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtContacts %SOURCE_PATH%\src\contacts\details
+ if %ORGANIZER_REQUESTED% == yes (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtVersitOrganizer %SOURCE_PATH%\src\versitorganizer
+ )
+) else if %FIRST% == sensors (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtSensors %SOURCE_PATH%\src\sensors
+) else if %FIRST% == gallery (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtGallery %SOURCE_PATH%\src\gallery
+) else if %FIRST% == organizer (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtOrganizer %SOURCE_PATH%\src\organizer
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtOrganizer %SOURCE_PATH%\src\organizer\items
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtOrganizer %SOURCE_PATH%\src\organizer\requests
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtOrganizer %SOURCE_PATH%\src\organizer\filters
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtOrganizer %SOURCE_PATH%\src\organizer\details
+) else if %FIRST% == feedback (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtFeedback %SOURCE_PATH%\src\feedback
+) else if %FIRST% == connectivity (
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtConnectivity %SOURCE_PATH%\src\connectivity
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtConnectivity %SOURCE_PATH%\src\connectivity\nfc
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtConnectivity %SOURCE_PATH%\src\connectivity\bluetooth
+ REM connectivity/nfc implies sfw
+ perl -S %SOURCE_PATH%\bin\syncheaders %BUILD_PATH%\include\QtServiceFramework %SOURCE_PATH%\src\serviceframework
+)
+
+if "%REMAINING%" == "" (
+ shift
+) else (
+ set MODULES_TEMP=%REMAINING%
+ goto generateHeaders
+)
+
+SET REMAINING=
+SET FIRST=
+SET MODULES_TEMP=
+
+if exist config.pri del config.pri
+ren %PROJECT_CONFIG% config.pri
+
+echo.
+echo Running qmake...
+call %QT_PATH%qmake -recursive %VC_TEMPLATE_OPTION% %SOURCE_PATH%\qtmultimediakit.pro
+if errorlevel 1 goto qmakeRecError
+echo.
+echo configure has finished. You may run %MOBILITY_MAKE% to build the project now.
+goto exitTag
+
+:qmakeRecError
+echo.
+echo configure failed.
+goto errorTag
+
+REM Unset the internal variables
+:errorTag
+set BUILD_PATH=
+set CURRENTDIR=
+set MOBILITY_MAKE=
+set MOBILITY_BUILDSYSTEM=
+set PROJECT_CONFIG=
+set PROJECT_LOG=
+set QT_MOBILITY_PREFIX=
+set QT_PATH=
+set SOURCE_PATH=
+set MOBILITY_MODULES=
+set MOBILITY_MODULES_UNPARSED=
+set REMAINING=
+set FIRST=
+set MODULES_TEMP=
+set QT_MOBILITY_EXAMPLES=
+set QT_MOBILITY_DEMOS=
+set ORGANIZER_REQUESTED=
+set PLATFORM_CONFIG=
+set LANGUAGES_CONFIG=
+exit /b 1
+
+:exitTag
+set BUILD_PATH=
+set CURRENTDIR=
+set MOBILITY_MAKE=
+set MOBILITY_BUILDSYSTEM=
+set PROJECT_CONFIG=
+set PROJECT_LOG=
+set QT_MOBILITY_PREFIX=
+set QT_PATH=
+set SOURCE_PATH=
+set MOBILITY_MODULES=
+set MOBILITY_MODULES_UNPARSED=
+set REMAINING=
+set FIRST=
+set MODULES_TEMP=
+set QT_MOBILITY_EXAMPLES=
+set QT_MOBILITY_DEMOS=
+set ORGANIZER_REQUESTED=
+set PLATFORM_CONFIG=
+set LANGUAGES_CONFIG=
+exit /b 0
diff --git a/demos/demos.pri b/demos/demos.pri
new file mode 100644
index 000000000..48c8bf2fc
--- /dev/null
+++ b/demos/demos.pri
@@ -0,0 +1,10 @@
+include(../features/basic_examples_setup.pri)
+
+!plugin {
+ target.path=$$QT_MOBILITY_DEMOS
+} else {
+ target.path = $${QT_MOBILITY_PLUGINS}/$${PLUGIN_TYPE}
+}
+INSTALLS += target
+
+
diff --git a/demos/demos.pro b/demos/demos.pro
new file mode 100644
index 000000000..22d06f518
--- /dev/null
+++ b/demos/demos.pro
@@ -0,0 +1,7 @@
+TEMPLATE = subdirs
+
+SUBDIRS += \
+ player
+
+sources.path = $$QT_MOBILITY_DEMOS
+INSTALLS += sources
diff --git a/demos/player/main.cpp b/demos/player/main.cpp
new file mode 100644
index 000000000..403a085f0
--- /dev/null
+++ b/demos/player/main.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "player.h"
+
+#include <QtGui>
+
+int main(int argc, char *argv[])
+{
+#ifdef Q_WS_MAEMO_6
+ //Meego graphics system conflicts with xvideo during fullscreen transition
+ QApplication::setGraphicsSystem("raster");
+#endif
+ QApplication app(argc, argv);
+
+ Player player;
+
+#if defined(Q_OS_SYMBIAN) || defined(Q_WS_SIMULATOR)
+# if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 2))
+ player.setAttribute(Qt::WA_LockLandscapeOrientation);
+# else
+ // lock screen orientation
+ CAknAppUi* appUi = dynamic_cast<CAknAppUi*>(CEikonEnv::Static()->AppUi());
+ if(appUi){
+ QT_TRAP_THROWING(appUi ->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape));
+ }
+# endif
+ player.showMaximized();
+#else
+ player.show();
+#endif
+ return app.exec();
+};
diff --git a/demos/player/player.cpp b/demos/player/player.cpp
new file mode 100644
index 000000000..8fa387916
--- /dev/null
+++ b/demos/player/player.cpp
@@ -0,0 +1,434 @@
+/****************************************************************************
+**
+** 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:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "player.h"
+
+#include "playercontrols.h"
+#include "playlistmodel.h"
+
+#include <qmediaservice.h>
+#include <qmediaplaylist.h>
+
+#include <QtGui>
+
+
+Player::Player(QWidget *parent)
+ : QWidget(parent)
+ , videoWidget(0)
+ , coverLabel(0)
+ , slider(0)
+#ifndef PLAYER_NO_COLOROPTIONS
+ , colorDialog(0)
+#endif
+{
+//! [create-objs]
+ player = new QMediaPlayer(this);
+ // owned by PlaylistModel
+ playlist = new QMediaPlaylist();
+ player->setPlaylist(playlist);
+//! [create-objs]
+
+ connect(player, SIGNAL(durationChanged(qint64)), SLOT(durationChanged(qint64)));
+ connect(player, SIGNAL(positionChanged(qint64)), SLOT(positionChanged(qint64)));
+ connect(player, SIGNAL(metaDataChanged()), SLOT(metaDataChanged()));
+ connect(playlist, SIGNAL(currentIndexChanged(int)), SLOT(playlistPositionChanged(int)));
+ connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
+ this, SLOT(statusChanged(QMediaPlayer::MediaStatus)));
+ connect(player, SIGNAL(bufferStatusChanged(int)), this, SLOT(bufferingProgress(int)));
+ connect(player, SIGNAL(videoAvailableChanged(bool)), this, SLOT(videoAvailableChanged(bool)));
+ connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(displayErrorMessage()));
+
+//! [2]
+ videoWidget = new VideoWidget(this);
+ player->setVideoOutput(videoWidget);
+
+ playlistModel = new PlaylistModel(this);
+ playlistModel->setPlaylist(playlist);
+//! [2]
+
+ playlistView = new QListView(this);
+ playlistView->setModel(playlistModel);
+ playlistView->setCurrentIndex(playlistModel->index(playlist->currentIndex(), 0));
+
+ connect(playlistView, SIGNAL(activated(QModelIndex)), this, SLOT(jump(QModelIndex)));
+
+ slider = new QSlider(Qt::Horizontal, this);
+ slider->setRange(0, player->duration() / 1000);
+
+ labelDuration = new QLabel(this);
+ connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(seek(int)));
+
+
+ QPushButton *openButton = new QPushButton(tr("Open"), this);
+
+ connect(openButton, SIGNAL(clicked()), this, SLOT(open()));
+
+ PlayerControls *controls = new PlayerControls(this);
+ controls->setState(player->state());
+ controls->setVolume(player->volume());
+ controls->setMuted(controls->isMuted());
+
+ connect(controls, SIGNAL(play()), player, SLOT(play()));
+ connect(controls, SIGNAL(pause()), player, SLOT(pause()));
+ connect(controls, SIGNAL(stop()), player, SLOT(stop()));
+ connect(controls, SIGNAL(next()), playlist, SLOT(next()));
+ connect(controls, SIGNAL(previous()), this, SLOT(previousClicked()));
+ connect(controls, SIGNAL(changeVolume(int)), player, SLOT(setVolume(int)));
+ connect(controls, SIGNAL(changeMuting(bool)), player, SLOT(setMuted(bool)));
+ connect(controls, SIGNAL(changeRate(qreal)), player, SLOT(setPlaybackRate(qreal)));
+
+ connect(controls, SIGNAL(stop()), videoWidget, SLOT(update()));
+
+ connect(player, SIGNAL(stateChanged(QMediaPlayer::State)),
+ controls, SLOT(setState(QMediaPlayer::State)));
+ connect(player, SIGNAL(volumeChanged(int)), controls, SLOT(setVolume(int)));
+ connect(player, SIGNAL(mutedChanged(bool)), controls, SLOT(setMuted(bool)));
+
+ fullScreenButton = new QPushButton(tr("FullScreen"), this);
+ fullScreenButton->setCheckable(true);
+
+#ifndef PLAYER_NO_COLOROPTIONS
+ colorButton = new QPushButton(tr("Color Options..."), this);
+ colorButton->setEnabled(false);
+ connect(colorButton, SIGNAL(clicked()), this, SLOT(showColorDialog()));
+#endif
+
+ QBoxLayout *displayLayout = new QHBoxLayout;
+ displayLayout->addWidget(videoWidget, 2);
+ displayLayout->addWidget(playlistView);
+
+ QBoxLayout *controlLayout = new QHBoxLayout;
+ controlLayout->setMargin(0);
+ controlLayout->addWidget(openButton);
+ controlLayout->addStretch(1);
+ controlLayout->addWidget(controls);
+ controlLayout->addStretch(1);
+ controlLayout->addWidget(fullScreenButton);
+#ifndef PLAYER_NO_COLOROPTIONS
+ controlLayout->addWidget(colorButton);
+#endif
+
+ QBoxLayout *layout = new QVBoxLayout;
+ layout->addLayout(displayLayout);
+ QHBoxLayout *hLayout = new QHBoxLayout;
+ hLayout->addWidget(slider);
+ hLayout->addWidget(labelDuration);
+ layout->addLayout(hLayout);
+ layout->addLayout(controlLayout);
+
+ setLayout(layout);
+
+ if (!player->isAvailable()) {
+ QMessageBox::warning(this, tr("Service not available"),
+ tr("The QMediaPlayer object does not have a valid service.\n"\
+ "Please check the media service plugins are installed."));
+
+ controls->setEnabled(false);
+ playlistView->setEnabled(false);
+ openButton->setEnabled(false);
+#ifndef PLAYER_NO_COLOROPTIONS
+ colorButton->setEnabled(false);
+#endif
+ fullScreenButton->setEnabled(false);
+ }
+
+ metaDataChanged();
+
+ QStringList arguments = qApp->arguments();
+ arguments.removeAt(0);
+ addToPlaylist(arguments);
+}
+
+Player::~Player()
+{
+}
+
+void Player::open()
+{
+#ifdef Q_WS_MAEMO_5
+ QStringList fileNames;
+ QString fileName = QFileDialog::getOpenFileName(this, tr("Open Files"), "/");
+ if (!fileName.isEmpty())
+ fileNames << fileName;
+#else
+ QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open Files"));
+#endif
+ addToPlaylist(fileNames);
+}
+
+void Player::addToPlaylist(const QStringList& fileNames)
+{
+ foreach (QString const &argument, fileNames) {
+ QFileInfo fileInfo(argument);
+ if (fileInfo.exists()) {
+ QUrl url = QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+ if (fileInfo.suffix().toLower() == QLatin1String("m3u")) {
+ playlist->load(url);
+ } else
+ playlist->addMedia(url);
+ } else {
+ QUrl url(argument);
+ if (url.isValid()) {
+ playlist->addMedia(url);
+ }
+ }
+ }
+}
+
+void Player::durationChanged(qint64 duration)
+{
+ this->duration = duration/1000;
+ slider->setMaximum(duration / 1000);
+}
+
+void Player::positionChanged(qint64 progress)
+{
+ if (!slider->isSliderDown()) {
+ slider->setValue(progress / 1000);
+ }
+ updateDurationInfo(progress / 1000);
+}
+
+void Player::metaDataChanged()
+{
+ //qDebug() << "update metadata" << player->metaData(QtMultimediaKit::Title).toString();
+ if (player->isMetaDataAvailable()) {
+ setTrackInfo(QString("%1 - %2")
+ .arg(player->metaData(QtMultimediaKit::AlbumArtist).toString())
+ .arg(player->metaData(QtMultimediaKit::Title).toString()));
+
+ if (coverLabel) {
+ QUrl url = player->metaData(QtMultimediaKit::CoverArtUrlLarge).value<QUrl>();
+
+ coverLabel->setPixmap(!url.isEmpty()
+ ? QPixmap(url.toString())
+ : QPixmap());
+ }
+ }
+}
+
+void Player::previousClicked()
+{
+ // Go to previous track if we are within the first 5 seconds of playback
+ // Otherwise, seek to the beginning.
+ if(player->position() <= 5000)
+ playlist->previous();
+ else
+ player->setPosition(0);
+}
+
+void Player::jump(const QModelIndex &index)
+{
+ if (index.isValid()) {
+ playlist->setCurrentIndex(index.row());
+ player->play();
+ }
+}
+
+void Player::playlistPositionChanged(int currentItem)
+{
+ playlistView->setCurrentIndex(playlistModel->index(currentItem, 0));
+}
+
+void Player::seek(int seconds)
+{
+ player->setPosition(seconds * 1000);
+}
+
+void Player::statusChanged(QMediaPlayer::MediaStatus status)
+{
+ handleCursor(status);
+
+ // handle status message
+ switch (status) {
+ case QMediaPlayer::UnknownMediaStatus:
+ case QMediaPlayer::NoMedia:
+ case QMediaPlayer::LoadedMedia:
+ case QMediaPlayer::BufferingMedia:
+ case QMediaPlayer::BufferedMedia:
+ setStatusInfo(QString());
+ break;
+ case QMediaPlayer::LoadingMedia:
+ setStatusInfo(tr("Loading..."));
+ break;
+ case QMediaPlayer::StalledMedia:
+ setStatusInfo(tr("Media Stalled"));
+ break;
+ case QMediaPlayer::EndOfMedia:
+ QApplication::alert(this);
+ break;
+ case QMediaPlayer::InvalidMedia:
+ displayErrorMessage();
+ break;
+ }
+}
+
+void Player::handleCursor(QMediaPlayer::MediaStatus status)
+{
+#ifndef QT_NO_CURSOR
+ if( status == QMediaPlayer::LoadingMedia ||
+ status == QMediaPlayer::BufferingMedia ||
+ status == QMediaPlayer::StalledMedia)
+ setCursor(QCursor(Qt::BusyCursor));
+ else
+ unsetCursor();
+#endif
+}
+
+void Player::bufferingProgress(int progress)
+{
+ setStatusInfo(tr("Buffering %4%").arg(progress));
+}
+
+void Player::videoAvailableChanged(bool available)
+{
+ if (!available) {
+ disconnect(fullScreenButton, SIGNAL(clicked(bool)),
+ videoWidget, SLOT(setFullScreen(bool)));
+ disconnect(videoWidget, SIGNAL(fullScreenChanged(bool)),
+ fullScreenButton, SLOT(setChecked(bool)));
+ videoWidget->setFullScreen(false);
+ } else {
+ connect(fullScreenButton, SIGNAL(clicked(bool)),
+ videoWidget, SLOT(setFullScreen(bool)));
+ connect(videoWidget, SIGNAL(fullScreenChanged(bool)),
+ fullScreenButton, SLOT(setChecked(bool)));
+
+ if (fullScreenButton->isChecked())
+ videoWidget->setFullScreen(true);
+ }
+#ifndef PLAYER_NO_COLOROPTIONS
+ colorButton->setEnabled(available);
+#endif
+}
+
+void Player::setTrackInfo(const QString &info)
+{
+ trackInfo = info;
+ if (!statusInfo.isEmpty())
+ setWindowTitle(QString("%1 | %2").arg(trackInfo).arg(statusInfo));
+ else
+ setWindowTitle(trackInfo);
+}
+
+void Player::setStatusInfo(const QString &info)
+{
+ statusInfo = info;
+ if (!statusInfo.isEmpty())
+ setWindowTitle(QString("%1 | %2").arg(trackInfo).arg(statusInfo));
+ else
+ setWindowTitle(trackInfo);
+}
+
+void Player::displayErrorMessage()
+{
+ setStatusInfo(player->errorString());
+}
+
+void Player::updateDurationInfo(qint64 currentInfo)
+{
+ QString tStr;
+ if (currentInfo || duration) {
+ QTime currentTime((currentInfo/3600)%60, (currentInfo/60)%60, currentInfo%60, (currentInfo*1000)%1000);
+ QTime totalTime((duration/3600)%60, (duration/60)%60, duration%60, (duration*1000)%1000);
+ QString format = "mm:ss";
+ if (duration > 3600)
+ format = "hh:mm:ss";
+ tStr = currentTime.toString(format) + " / " + totalTime.toString(format);
+ }
+ labelDuration->setText(tStr);
+}
+
+
+#ifndef PLAYER_NO_COLOROPTIONS
+void Player::showColorDialog()
+{
+ if (!colorDialog) {
+ QSlider *brightnessSlider = new QSlider(Qt::Horizontal);
+ brightnessSlider->setRange(-100, 100);
+ brightnessSlider->setValue(videoWidget->brightness());
+ connect(brightnessSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setBrightness(int)));
+ connect(videoWidget, SIGNAL(brightnessChanged(int)), brightnessSlider, SLOT(setValue(int)));
+
+ QSlider *contrastSlider = new QSlider(Qt::Horizontal);
+ contrastSlider->setRange(-100, 100);
+ contrastSlider->setValue(videoWidget->contrast());
+ connect(contrastSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setContrast(int)));
+ connect(videoWidget, SIGNAL(contrastChanged(int)), contrastSlider, SLOT(setValue(int)));
+
+ QSlider *hueSlider = new QSlider(Qt::Horizontal);
+ hueSlider->setRange(-100, 100);
+ hueSlider->setValue(videoWidget->hue());
+ connect(hueSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setHue(int)));
+ connect(videoWidget, SIGNAL(hueChanged(int)), hueSlider, SLOT(setValue(int)));
+
+ QSlider *saturationSlider = new QSlider(Qt::Horizontal);
+ saturationSlider->setRange(-100, 100);
+ saturationSlider->setValue(videoWidget->saturation());
+ connect(saturationSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setSaturation(int)));
+ connect(videoWidget, SIGNAL(saturationChanged(int)), saturationSlider, SLOT(setValue(int)));
+
+#if defined(Q_OS_SYMBIAN)
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
+#endif
+ QFormLayout *layout = new QFormLayout;
+ layout->addRow(tr("Brightness"), brightnessSlider);
+ layout->addRow(tr("Contrast"), contrastSlider);
+ layout->addRow(tr("Hue"), hueSlider);
+ layout->addRow(tr("Saturation"), saturationSlider);
+#if defined(Q_OS_SYMBIAN)
+ layout->addWidget(buttonBox);
+#endif
+
+ QPushButton *button = new QPushButton(tr("Close"));
+ layout->addRow(button);
+
+ colorDialog = new QDialog(this);
+#if defined(Q_OS_SYMBIAN)
+ connect(buttonBox, SIGNAL(clicked(QAbstractButton*)), colorDialog, SLOT(hide()));
+#endif
+ colorDialog->setWindowTitle(tr("Color Options"));
+ colorDialog->setLayout(layout);
+
+ connect(button, SIGNAL(clicked()), colorDialog, SLOT(close()));
+ }
+ colorDialog->show();
+}
+#endif
diff --git a/demos/player/player.h b/demos/player/player.h
new file mode 100644
index 000000000..e5c075ebe
--- /dev/null
+++ b/demos/player/player.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** 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:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PLAYER_H
+#define PLAYER_H
+
+#include <QtGui/QWidget>
+
+#include <qmediaplayer.h>
+#include <qmediaplaylist.h>
+#include "videowidget.h"
+
+
+QT_BEGIN_NAMESPACE
+class QAbstractItemView;
+class QLabel;
+class QModelIndex;
+class QSlider;
+class QPushButton;
+
+class QMediaPlayer;
+class QVideoWidget;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class PlaylistModel;
+
+class Player : public QWidget
+{
+ Q_OBJECT
+public:
+ Player(QWidget *parent = 0);
+ ~Player();
+
+Q_SIGNALS:
+ void fullScreenChanged(bool fullScreen);
+
+private slots:
+ void open();
+ void durationChanged(qint64 duration);
+ void positionChanged(qint64 progress);
+ void metaDataChanged();
+
+ void previousClicked();
+
+ void seek(int seconds);
+ void jump(const QModelIndex &index);
+ void playlistPositionChanged(int);
+
+ void statusChanged(QMediaPlayer::MediaStatus status);
+ void bufferingProgress(int progress);
+ void videoAvailableChanged(bool available);
+
+ void displayErrorMessage();
+
+#ifndef PLAYER_NO_COLOROPTIONS
+ void showColorDialog();
+#endif
+ void addToPlaylist(const QStringList& fileNames);
+
+private:
+ void setTrackInfo(const QString &info);
+ void setStatusInfo(const QString &info);
+ void handleCursor(QMediaPlayer::MediaStatus status);
+ void updateDurationInfo(qint64 currentInfo);
+
+ QMediaPlayer *player;
+ QMediaPlaylist *playlist;
+ VideoWidget *videoWidget;
+ QLabel *coverLabel;
+ QSlider *slider;
+ QLabel *labelDuration;
+ QPushButton *fullScreenButton;
+#ifndef PLAYER_NO_COLOROPTIONS
+ QPushButton *colorButton;
+ QDialog *colorDialog;
+#endif
+ PlaylistModel *playlistModel;
+ QAbstractItemView *playlistView;
+ QString trackInfo;
+ QString statusInfo;
+ qint64 duration;
+};
+
+#endif
diff --git a/demos/player/player.pro b/demos/player/player.pro
new file mode 100644
index 000000000..6f369aef4
--- /dev/null
+++ b/demos/player/player.pro
@@ -0,0 +1,30 @@
+TEMPLATE = app
+TARGET = player
+QT += network \
+ xml
+
+INCLUDEPATH += ../../src/multimedia ../../src/multimedia/audio
+
+include(../demos.pri)
+CONFIG += mobility
+MOBILITY = multimedia
+
+HEADERS = \
+ player.h \
+ playercontrols.h \
+ playlistmodel.h \
+ videowidget.h
+SOURCES = main.cpp \
+ player.cpp \
+ playercontrols.cpp \
+ playlistmodel.cpp \
+ videowidget.cpp
+
+maemo* {
+ DEFINES += PLAYER_NO_COLOROPTIONS
+}
+
+symbian {
+ LIBS += -lavkon -lcone -leikcore
+ TARGET.CAPABILITY = ReadUserData
+}
diff --git a/demos/player/playercontrols.cpp b/demos/player/playercontrols.cpp
new file mode 100644
index 000000000..bf4d96b2f
--- /dev/null
+++ b/demos/player/playercontrols.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** 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:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "playercontrols.h"
+
+#include <QtGui/qboxlayout.h>
+#include <QtGui/qslider.h>
+#include <QtGui/qstyle.h>
+#include <QtGui/qtoolbutton.h>
+#include <QtGui/qcombobox.h>
+
+PlayerControls::PlayerControls(QWidget *parent)
+ : QWidget(parent)
+ , playerState(QMediaPlayer::StoppedState)
+ , playerMuted(false)
+ , playButton(0)
+ , stopButton(0)
+ , nextButton(0)
+ , previousButton(0)
+ , muteButton(0)
+ , volumeSlider(0)
+ , rateBox(0)
+{
+ playButton = new QToolButton(this);
+ playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
+
+ connect(playButton, SIGNAL(clicked()), this, SLOT(playClicked()));
+
+ stopButton = new QToolButton(this);
+ stopButton->setIcon(style()->standardIcon(QStyle::SP_MediaStop));
+ stopButton->setEnabled(false);
+
+ connect(stopButton, SIGNAL(clicked()), this, SIGNAL(stop()));
+
+ nextButton = new QToolButton(this);
+ nextButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipForward));
+
+ connect(nextButton, SIGNAL(clicked()), this, SIGNAL(next()));
+
+ previousButton = new QToolButton(this);
+ previousButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipBackward));
+
+ connect(previousButton, SIGNAL(clicked()), this, SIGNAL(previous()));
+
+ muteButton = new QToolButton(this);
+ muteButton->setIcon(style()->standardIcon(QStyle::SP_MediaVolume));
+
+ connect(muteButton, SIGNAL(clicked()), this, SLOT(muteClicked()));
+
+#ifndef Q_WS_MAEMO_5
+ volumeSlider = new QSlider(Qt::Horizontal, this);
+ volumeSlider->setRange(0, 100);
+
+ connect(volumeSlider, SIGNAL(sliderMoved(int)), this, SIGNAL(changeVolume(int)));
+
+
+ rateBox = new QComboBox(this);
+ rateBox->addItem("0.5x", QVariant(0.5));
+ rateBox->addItem("1.0x", QVariant(1.0));
+ rateBox->addItem("2.0x", QVariant(2.0));
+ rateBox->setCurrentIndex(1);
+
+ connect(rateBox, SIGNAL(activated(int)), SLOT(updateRate()));
+#endif
+
+ QBoxLayout *layout = new QHBoxLayout;
+ layout->setMargin(0);
+ layout->addWidget(stopButton);
+ layout->addWidget(previousButton);
+ layout->addWidget(playButton);
+ layout->addWidget(nextButton);
+ layout->addWidget(muteButton);
+ if (volumeSlider)
+ layout->addWidget(volumeSlider);
+
+ if (rateBox)
+ layout->addWidget(rateBox);
+ setLayout(layout);
+}
+
+QMediaPlayer::State PlayerControls::state() const
+{
+ return playerState;
+}
+
+void PlayerControls::setState(QMediaPlayer::State state)
+{
+ if (state != playerState) {
+ playerState = state;
+
+ switch (state) {
+ case QMediaPlayer::StoppedState:
+ stopButton->setEnabled(false);
+ playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
+ break;
+ case QMediaPlayer::PlayingState:
+ stopButton->setEnabled(true);
+ playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
+ break;
+ case QMediaPlayer::PausedState:
+ stopButton->setEnabled(true);
+ playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
+ break;
+ }
+ }
+}
+
+int PlayerControls::volume() const
+{
+ return volumeSlider ? volumeSlider->value() : 0;
+}
+
+void PlayerControls::setVolume(int volume)
+{
+ if (volumeSlider)
+ volumeSlider->setValue(volume);
+}
+
+bool PlayerControls::isMuted() const
+{
+ return playerMuted;
+}
+
+void PlayerControls::setMuted(bool muted)
+{
+ if (muted != playerMuted) {
+ playerMuted = muted;
+
+ muteButton->setIcon(style()->standardIcon(muted
+ ? QStyle::SP_MediaVolumeMuted
+ : QStyle::SP_MediaVolume));
+ }
+}
+
+void PlayerControls::playClicked()
+{
+ switch (playerState) {
+ case QMediaPlayer::StoppedState:
+ case QMediaPlayer::PausedState:
+ emit play();
+ break;
+ case QMediaPlayer::PlayingState:
+ emit pause();
+ break;
+ }
+}
+
+void PlayerControls::muteClicked()
+{
+ emit changeMuting(!playerMuted);
+}
+
+qreal PlayerControls::playbackRate() const
+{
+ return rateBox->itemData(rateBox->currentIndex()).toDouble();
+}
+
+void PlayerControls::setPlaybackRate(float rate)
+{
+ for (int i=0; i<rateBox->count(); i++) {
+ if (qFuzzyCompare(rate, float(rateBox->itemData(i).toDouble()))) {
+ rateBox->setCurrentIndex(i);
+ return;
+ }
+ }
+
+ rateBox->addItem( QString("%1x").arg(rate), QVariant(rate));
+ rateBox->setCurrentIndex(rateBox->count()-1);
+}
+
+void PlayerControls::updateRate()
+{
+ emit changeRate(playbackRate());
+}
diff --git a/demos/player/playercontrols.h b/demos/player/playercontrols.h
new file mode 100644
index 000000000..89dc3fd9e
--- /dev/null
+++ b/demos/player/playercontrols.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** 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:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PLAYERCONTROLS_H
+#define PLAYERCONTROLS_H
+
+#include <qmediaplayer.h>
+
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_NAMESPACE
+class QAbstractButton;
+class QAbstractSlider;
+class QComboBox;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class PlayerControls : public QWidget
+{
+ Q_OBJECT
+public:
+ PlayerControls(QWidget *parent = 0);
+
+ QMediaPlayer::State state() const;
+
+ int volume() const;
+ bool isMuted() const;
+ qreal playbackRate() const;
+
+public slots:
+ void setState(QMediaPlayer::State state);
+ void setVolume(int volume);
+ void setMuted(bool muted);
+ void setPlaybackRate(float rate);
+
+signals:
+ void play();
+ void pause();
+ void stop();
+ void next();
+ void previous();
+ void changeVolume(int volume);
+ void changeMuting(bool muting);
+ void changeRate(qreal rate);
+
+private slots:
+ void playClicked();
+ void muteClicked();
+ void updateRate();
+
+private:
+ QMediaPlayer::State playerState;
+ bool playerMuted;
+ QAbstractButton *playButton;
+ QAbstractButton *stopButton;
+ QAbstractButton *nextButton;
+ QAbstractButton *previousButton;
+ QAbstractButton *muteButton;
+ QAbstractSlider *volumeSlider;
+ QComboBox *rateBox;
+};
+
+#endif
diff --git a/demos/player/playlistmodel.cpp b/demos/player/playlistmodel.cpp
new file mode 100644
index 000000000..21bc4ccf4
--- /dev/null
+++ b/demos/player/playlistmodel.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** 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:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "playlistmodel.h"
+
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qurl.h>
+
+#include <qmediaplaylist.h>
+
+PlaylistModel::PlaylistModel(QObject *parent)
+ : QAbstractItemModel(parent)
+ , m_playlist(0)
+{
+}
+
+int PlaylistModel::rowCount(const QModelIndex &parent) const
+{
+ return m_playlist && !parent.isValid() ? m_playlist->mediaCount() : 0;
+}
+
+int PlaylistModel::columnCount(const QModelIndex &parent) const
+{
+ return !parent.isValid() ? ColumnCount : 0;
+}
+
+QModelIndex PlaylistModel::index(int row, int column, const QModelIndex &parent) const
+{
+ return m_playlist && !parent.isValid()
+ && row >= 0 && row < m_playlist->mediaCount()
+ && column >= 0 && column < ColumnCount
+ ? createIndex(row, column)
+ : QModelIndex();
+}
+
+QModelIndex PlaylistModel::parent(const QModelIndex &child) const
+{
+ Q_UNUSED(child);
+
+ return QModelIndex();
+}
+
+QVariant PlaylistModel::data(const QModelIndex &index, int role) const
+{
+ if (index.isValid() && role == Qt::DisplayRole) {
+ QVariant value = m_data[index];
+ if (!value.isValid() && index.column() == Title) {
+ QUrl location = m_playlist->media(index.row()).canonicalUrl();
+ return QFileInfo(location.path()).fileName();
+ }
+
+ return value;
+ }
+ return QVariant();
+}
+
+QMediaPlaylist *PlaylistModel::playlist() const
+{
+ return m_playlist;
+}
+
+void PlaylistModel::setPlaylist(QMediaPlaylist *playlist)
+{
+ if (m_playlist) {
+ disconnect(m_playlist, SIGNAL(mediaAboutToBeInserted(int,int)), this, SLOT(beginInsertItems(int,int)));
+ disconnect(m_playlist, SIGNAL(mediaInserted(int,int)), this, SLOT(endInsertItems()));
+ disconnect(m_playlist, SIGNAL(mediaAboutToBeRemoved(int,int)), this, SLOT(beginRemoveItems(int,int)));
+ disconnect(m_playlist, SIGNAL(mediaRemoved(int,int)), this, SLOT(endRemoveItems()));
+ disconnect(m_playlist, SIGNAL(mediaChanged(int,int)), this, SLOT(changeItems(int,int)));
+ }
+
+ m_playlist = playlist;
+
+ if (m_playlist) {
+ connect(m_playlist, SIGNAL(mediaAboutToBeInserted(int,int)), this, SLOT(beginInsertItems(int,int)));
+ connect(m_playlist, SIGNAL(mediaInserted(int,int)), this, SLOT(endInsertItems()));
+ connect(m_playlist, SIGNAL(mediaAboutToBeRemoved(int,int)), this, SLOT(beginRemoveItems(int,int)));
+ connect(m_playlist, SIGNAL(mediaRemoved(int,int)), this, SLOT(endRemoveItems()));
+ connect(m_playlist, SIGNAL(mediaChanged(int,int)), this, SLOT(changeItems(int,int)));
+ }
+
+
+ reset();
+}
+
+bool PlaylistModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ Q_UNUSED(role);
+ m_data[index] = value;
+ emit dataChanged(index, index);
+ return true;
+}
+
+void PlaylistModel::beginInsertItems(int start, int end)
+{
+ m_data.clear();
+ beginInsertRows(QModelIndex(), start, end);
+}
+
+void PlaylistModel::endInsertItems()
+{
+ endInsertRows();
+}
+
+void PlaylistModel::beginRemoveItems(int start, int end)
+{
+ m_data.clear();
+ beginRemoveRows(QModelIndex(), start, end);
+}
+
+void PlaylistModel::endRemoveItems()
+{
+ endInsertRows();
+}
+
+void PlaylistModel::changeItems(int start, int end)
+{
+ m_data.clear();
+ emit dataChanged(index(start,0), index(end,ColumnCount));
+}
+
+
diff --git a/demos/player/playlistmodel.h b/demos/player/playlistmodel.h
new file mode 100644
index 000000000..cf580d8f5
--- /dev/null
+++ b/demos/player/playlistmodel.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PLAYLISTMODEL_H
+#define PLAYLISTMODEL_H
+
+#include <qmobilityglobal.h>
+#include <QtCore/qabstractitemmodel.h>
+
+QT_BEGIN_NAMESPACE
+class QMediaPlaylist;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class PlaylistModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ enum Column
+ {
+ Title = 0,
+ ColumnCount
+ };
+
+ PlaylistModel(QObject *parent = 0);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &child) const;
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+ QMediaPlaylist *playlist() const;
+ void setPlaylist(QMediaPlaylist *playlist);
+
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole);
+
+private slots:
+ void beginInsertItems(int start, int end);
+ void endInsertItems();
+ void beginRemoveItems(int start, int end);
+ void endRemoveItems();
+ void changeItems(int start, int end);
+
+private:
+ QMediaPlaylist *m_playlist;
+ QMap<QModelIndex, QVariant> m_data;
+};
+
+#endif
diff --git a/demos/player/videowidget.cpp b/demos/player/videowidget.cpp
new file mode 100644
index 000000000..46f1b33ff
--- /dev/null
+++ b/demos/player/videowidget.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "videowidget.h"
+
+#include <QtGui>
+
+VideoWidget::VideoWidget(QWidget *parent)
+ : QVideoWidget(parent)
+{
+ setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
+
+ QPalette p = palette();
+ p.setColor(QPalette::Window, Qt::black);
+ setPalette(p);
+
+ setAttribute(Qt::WA_OpaquePaintEvent);
+}
+
+void VideoWidget::keyPressEvent(QKeyEvent *event)
+{
+#ifdef Q_OS_SYMBIAN
+ if (isFullScreen())
+ setFullScreen(false);
+#endif
+
+ if (event->key() == Qt::Key_Escape && isFullScreen()) {
+ showNormal();
+
+ event->accept();
+ } else if (event->key() == Qt::Key_Enter && event->modifiers() & Qt::Key_Alt) {
+ setFullScreen(!isFullScreen());
+
+ event->accept();
+ } else {
+ QVideoWidget::keyPressEvent(event);
+ }
+}
+
+void VideoWidget::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ setFullScreen(!isFullScreen());
+
+ event->accept();
+}
+
+void VideoWidget::mousePressEvent(QMouseEvent *event)
+{
+#ifdef Q_WS_MAEMO_5
+ if (isFullScreen())
+ setFullScreen(false);
+
+ event->accept();
+#else
+ QVideoWidget::mousePressEvent(event);
+#endif
+}
+
diff --git a/demos/player/videowidget.h b/demos/player/videowidget.h
new file mode 100644
index 000000000..5d382f981
--- /dev/null
+++ b/demos/player/videowidget.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** 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:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef VIDEOWIDGET_H
+#define VIDEOWIDGET_H
+
+#include <qvideowidget.h>
+
+QT_USE_NAMESPACE
+
+class VideoWidget : public QVideoWidget
+{
+ Q_OBJECT
+public:
+ VideoWidget(QWidget *parent = 0);
+
+protected:
+ void keyPressEvent(QKeyEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+};
+
+#endif
diff --git a/doc/config/compat.qdocconf b/doc/config/compat.qdocconf
new file mode 100644
index 000000000..d19072fd1
--- /dev/null
+++ b/doc/config/compat.qdocconf
@@ -0,0 +1,31 @@
+#alias.i = e
+alias.include = input
+
+macro.0 = "\\\\0"
+macro.b = "\\\\b"
+macro.n = "\\\\n"
+macro.r = "\\\\r"
+#macro.i = "\\o"
+macro.i11 = "\\o{1,1}"
+macro.i12 = "\\o{1,2}"
+macro.i13 = "\\o{1,3}"
+macro.i14 = "\\o{1,4}"
+macro.i15 = "\\o{1,5}"
+macro.i16 = "\\o{1,6}"
+macro.i17 = "\\o{1,7}"
+macro.i18 = "\\o{1,8}"
+macro.i19 = "\\o{1,9}"
+macro.i21 = "\\o{2,1}"
+macro.i31 = "\\o{3,1}"
+macro.i41 = "\\o{4,1}"
+macro.i51 = "\\o{5,1}"
+macro.i61 = "\\o{6,1}"
+macro.i71 = "\\o{7,1}"
+macro.i81 = "\\o{8,1}"
+macro.i91 = "\\o{9,1}"
+macro.img = "\\image"
+macro.endquote = "\\endquotation"
+macro.relatesto = "\\relates"
+
+spurious = "Missing comma in .*" \
+ "Missing pattern .*"
diff --git a/doc/config/images/arrow_down.png b/doc/config/images/arrow_down.png
new file mode 100644
index 000000000..9d01e97f6
--- /dev/null
+++ b/doc/config/images/arrow_down.png
Binary files differ
diff --git a/doc/config/images/bg_l.png b/doc/config/images/bg_l.png
new file mode 100755
index 000000000..90b1da10b
--- /dev/null
+++ b/doc/config/images/bg_l.png
Binary files differ
diff --git a/doc/config/images/bg_l_blank.png b/doc/config/images/bg_l_blank.png
new file mode 100755
index 000000000..5a9673d81
--- /dev/null
+++ b/doc/config/images/bg_l_blank.png
Binary files differ
diff --git a/doc/config/images/bg_ll_blank.png b/doc/config/images/bg_ll_blank.png
new file mode 100644
index 000000000..95a1c45e0
--- /dev/null
+++ b/doc/config/images/bg_ll_blank.png
Binary files differ
diff --git a/doc/config/images/bg_r.png b/doc/config/images/bg_r.png
new file mode 100755
index 000000000..f0fb121de
--- /dev/null
+++ b/doc/config/images/bg_r.png
Binary files differ
diff --git a/doc/config/images/bg_ul_blank.png b/doc/config/images/bg_ul_blank.png
new file mode 100644
index 000000000..70512614c
--- /dev/null
+++ b/doc/config/images/bg_ul_blank.png
Binary files differ
diff --git a/doc/config/images/box_bg.png b/doc/config/images/box_bg.png
new file mode 100755
index 000000000..3322f923f
--- /dev/null
+++ b/doc/config/images/box_bg.png
Binary files differ
diff --git a/doc/config/images/breadcrumb.png b/doc/config/images/breadcrumb.png
new file mode 100755
index 000000000..0ded5514d
--- /dev/null
+++ b/doc/config/images/breadcrumb.png
Binary files differ
diff --git a/doc/config/images/bullet_dn.png b/doc/config/images/bullet_dn.png
new file mode 100644
index 000000000..f7762472e
--- /dev/null
+++ b/doc/config/images/bullet_dn.png
Binary files differ
diff --git a/doc/config/images/bullet_gt.png b/doc/config/images/bullet_gt.png
new file mode 100755
index 000000000..7561b4edc
--- /dev/null
+++ b/doc/config/images/bullet_gt.png
Binary files differ
diff --git a/doc/config/images/bullet_sq.png b/doc/config/images/bullet_sq.png
new file mode 100755
index 000000000..a84845e3c
--- /dev/null
+++ b/doc/config/images/bullet_sq.png
Binary files differ
diff --git a/doc/config/images/bullet_up.png b/doc/config/images/bullet_up.png
new file mode 100644
index 000000000..7de2f0695
--- /dev/null
+++ b/doc/config/images/bullet_up.png
Binary files differ
diff --git a/doc/config/images/feedbackground.png b/doc/config/images/feedbackground.png
new file mode 100755
index 000000000..3a38d995d
--- /dev/null
+++ b/doc/config/images/feedbackground.png
Binary files differ
diff --git a/doc/config/images/header_bg.png b/doc/config/images/header_bg.png
new file mode 100644
index 000000000..a436aa61e
--- /dev/null
+++ b/doc/config/images/header_bg.png
Binary files differ
diff --git a/doc/config/images/horBar.png b/doc/config/images/horBar.png
new file mode 100755
index 000000000..100fe91c6
--- /dev/null
+++ b/doc/config/images/horBar.png
Binary files differ
diff --git a/doc/config/images/page.png b/doc/config/images/page.png
new file mode 100644
index 000000000..1db151bd3
--- /dev/null
+++ b/doc/config/images/page.png
Binary files differ
diff --git a/doc/config/images/page_bg.png b/doc/config/images/page_bg.png
new file mode 100755
index 000000000..9b3bd999d
--- /dev/null
+++ b/doc/config/images/page_bg.png
Binary files differ
diff --git a/doc/config/images/qt-logo.png b/doc/config/images/qt-logo.png
new file mode 100644
index 000000000..14ddf2a02
--- /dev/null
+++ b/doc/config/images/qt-logo.png
Binary files differ
diff --git a/doc/config/images/spinner.gif b/doc/config/images/spinner.gif
new file mode 100644
index 000000000..1ed786f2e
--- /dev/null
+++ b/doc/config/images/spinner.gif
Binary files differ
diff --git a/doc/config/images/sprites-combined.png b/doc/config/images/sprites-combined.png
new file mode 100755
index 000000000..7f9686637
--- /dev/null
+++ b/doc/config/images/sprites-combined.png
Binary files differ
diff --git a/doc/config/macros.qdocconf b/doc/config/macros.qdocconf
new file mode 100644
index 000000000..2262daa98
--- /dev/null
+++ b/doc/config/macros.qdocconf
@@ -0,0 +1,37 @@
+macro.aacute.HTML = "&aacute;"
+macro.Aring.HTML = "&Aring;"
+macro.aring.HTML = "&aring;"
+macro.Auml.HTML = "&Auml;"
+macro.author = "\\bold{Author:}"
+macro.br.HTML = "<br />"
+macro.BR.HTML = "<br />"
+macro.copyright.HTML = "&copy;"
+macro.eacute.HTML = "&eacute;"
+macro.gui = "\\bold"
+macro.hr.HTML = "<hr />"
+macro.iacute.HTML = "&iacute;"
+macro.key = "\\bold"
+macro.menu = "\\bold"
+macro.note = "\\bold{Note:}"
+macro.oslash.HTML = "&oslash;"
+macro.ouml.HTML = "&ouml;"
+macro.QA = "\\e{Qt Assistant}"
+macro.QD = "\\e{Qt Designer}"
+macro.QL = "\\e{Qt Linguist}"
+macro.QQV = "\\e{Qt QML Viewer}"
+macro.param = "\\e"
+macro.raisedaster.HTML = "<sup>*</sup>"
+macro.rarrow.HTML = "&rarr;"
+macro.reg.HTML = "<sup>&reg;</sup>"
+macro.return = "Returns"
+macro.starslash = "\\c{*/}"
+macro.begincomment = "\\c{/*}"
+macro.endcomment = "\\c{*/}"
+macro.uuml.HTML = "&uuml;"
+macro.mdash.HTML = "&mdash;"
+
+macro.beginfloatleft.HTML = "<div style=\"float: left; margin-right: 2em\">"
+macro.beginfloatright.HTML = "<div style=\"float: right; margin-left: 2em\">"
+macro.endfloat.HTML = "</div>"
+macro.clearfloat.HTML = "<br style=\"clear: both\" />"
+macro.emptyspan.HTML = "<span></span>"
diff --git a/doc/config/qt-cpp-ignore.qdocconf b/doc/config/qt-cpp-ignore.qdocconf
new file mode 100644
index 000000000..9b09a60aa
--- /dev/null
+++ b/doc/config/qt-cpp-ignore.qdocconf
@@ -0,0 +1,99 @@
+Cpp.ignoretokens = QAXFACTORY_EXPORT \
+ QDESIGNER_COMPONENTS_LIBRARY \
+ QDESIGNER_EXTENSION_LIBRARY \
+ QDESIGNER_SDK_LIBRARY \
+ QDESIGNER_SHARED_LIBRARY \
+ QDESIGNER_UILIB_LIBRARY \
+ QM_EXPORT_CANVAS \
+ QM_EXPORT_DNS \
+ QM_EXPORT_DOM \
+ QM_EXPORT_FTP \
+ QM_EXPORT_HTTP \
+ QM_EXPORT_ICONVIEW \
+ QM_EXPORT_NETWORK \
+ QM_EXPORT_OPENGL \
+ QM_EXPORT_OPENVG \
+ QM_EXPORT_SQL \
+ QM_EXPORT_TABLE \
+ QM_EXPORT_WORKSPACE \
+ QM_EXPORT_XML \
+ QT_ASCII_CAST_WARN \
+ QT_ASCII_CAST_WARN_CONSTRUCTOR \
+ QT_BEGIN_HEADER \
+ QT_DESIGNER_STATIC \
+ QT_END_HEADER \
+ QT_FASTCALL \
+ QT_WIDGET_PLUGIN_EXPORT \
+ Q_COMPAT_EXPORT \
+ Q_CORE_EXPORT \
+ Q_CORE_EXPORT_INLINE \
+ Q_EXPLICIT \
+ Q_EXPORT \
+ Q_EXPORT_CODECS_CN \
+ Q_EXPORT_CODECS_JP \
+ Q_EXPORT_CODECS_KR \
+ Q_EXPORT_PLUGIN \
+ Q_GFX_INLINE \
+ Q_AUTOTEST_EXPORT \
+ QM_AUTOTEST_EXPORT \
+ Q_GUI_EXPORT \
+ Q_GUI_EXPORT_INLINE \
+ Q_GUI_EXPORT_STYLE_CDE \
+ Q_GUI_EXPORT_STYLE_COMPACT \
+ Q_GUI_EXPORT_STYLE_MAC \
+ Q_GUI_EXPORT_STYLE_MOTIF \
+ Q_GUI_EXPORT_STYLE_MOTIFPLUS \
+ Q_GUI_EXPORT_STYLE_PLATINUM \
+ Q_GUI_EXPORT_STYLE_POCKETPC \
+ Q_GUI_EXPORT_STYLE_SGI \
+ Q_GUI_EXPORT_STYLE_WINDOWS \
+ Q_GUI_EXPORT_STYLE_WINDOWSXP \
+ QHELP_EXPORT \
+ Q_INLINE_TEMPLATE \
+ Q_INTERNAL_WIN_NO_THROW \
+ Q_NETWORK_EXPORT \
+ Q_OPENGL_EXPORT \
+ Q_OPENVG_EXPORT \
+ Q_OUTOFLINE_TEMPLATE \
+ Q_SQL_EXPORT \
+ Q_SVG_EXPORT \
+ Q_SCRIPT_EXPORT \
+ Q_SCRIPTTOOLS_EXPORT \
+ Q_TESTLIB_EXPORT \
+ Q_TYPENAME \
+ Q_XML_EXPORT \
+ Q_XMLSTREAM_EXPORT \
+ Q_XMLPATTERNS_EXPORT \
+ QDBUS_EXPORT \
+ Q_DBUS_EXPORT \
+ QT_BEGIN_NAMESPACE \
+ QT_BEGIN_INCLUDE_NAMESPACE \
+ QT_END_NAMESPACE \
+ QT_END_INCLUDE_NAMESPACE \
+ PHONON_EXPORT \
+ Q_DECLARATIVE_EXPORT \
+ Q_GADGET \
+ QWEBKIT_EXPORT \
+ Q_INVOKABLE
+Cpp.ignoredirectives = Q_DECLARE_HANDLE \
+ Q_DECLARE_INTERFACE \
+ Q_DECLARE_METATYPE \
+ Q_DECLARE_OPERATORS_FOR_FLAGS \
+ Q_DECLARE_PRIVATE \
+ Q_DECLARE_PUBLIC \
+ Q_DECLARE_SHARED \
+ Q_DECLARE_TR_FUNCTIONS \
+ Q_DECLARE_TYPEINFO \
+ Q_DISABLE_COPY \
+ QT_FORWARD_DECLARE_CLASS \
+ Q_DUMMY_COMPARISON_OPERATOR \
+ Q_ENUMS \
+ Q_FLAGS \
+ Q_INTERFACES \
+ __attribute__ \
+ K_DECLARE_PRIVATE \
+ PHONON_OBJECT \
+ PHONON_HEIR \
+ Q_PRIVATE_PROPERTY \
+ Q_DECLARE_PRIVATE_D \
+ Q_CLASSINFO
diff --git a/doc/config/qt-defines.qdocconf b/doc/config/qt-defines.qdocconf
new file mode 100644
index 000000000..50a355f04
--- /dev/null
+++ b/doc/config/qt-defines.qdocconf
@@ -0,0 +1,17 @@
+defines = Q_QDOC \
+ QT_.*_SUPPORT \
+ QT_.*_LIB \
+ QT_COMPAT \
+ QT_KEYPAD_NAVIGATION \
+ QT_NO_EGL \
+ QT3_SUPPORT \
+ Q_WS_.* \
+ Q_OS_.* \
+ Q_BYTE_ORDER \
+ QT_DEPRECATED \
+ Q_NO_USING_KEYWORD \
+ __cplusplus
+
+versionsym = QT_VERSION_STR
+
+codeindent = 1
diff --git a/doc/config/qt-html-default-styles.qdocconf b/doc/config/qt-html-default-styles.qdocconf
new file mode 100644
index 000000000..47e550bcc
--- /dev/null
+++ b/doc/config/qt-html-default-styles.qdocconf
@@ -0,0 +1,32 @@
+# Define the location of the templates to use. Style sheets and scripts are
+# specified relative to the template directory and will be copied into
+# subdirectories of the output directory.
+
+HTML.templatedir = .
+
+HTML.stylesheets = style/offline.css
+
+HTML.scripts =
+
+# Files not referenced in any qdoc file (last four needed by qtdemo)
+# See also qhp.Qt.extraFiles
+extraimages.HTML = qt-logo.png \
+ arrow_down.png \
+ breadcrumb.png \
+ bullet_gt.png \
+ bullet_dn.png \
+ bullet_sq.png \
+ bullet_up.png \
+ horBar.png \
+ sprites-combined.png
+
+# Include the style sheets and scripts used.
+
+HTML.headerstyles = \
+ " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/offline.css\" />\n"
+
+HTML.headerscripts =
+
+HTML.endheader = \
+ "</head>\n" \
+ "<body>\n"
diff --git a/doc/config/qt-html-online-styles.qdocconf b/doc/config/qt-html-online-styles.qdocconf
new file mode 100644
index 000000000..f915cb449
--- /dev/null
+++ b/doc/config/qt-html-online-styles.qdocconf
@@ -0,0 +1,72 @@
+# Define the location of the templates to use. Style sheets and scripts are
+# specified relative to the template directory and will be copied into
+# subdirectories of the output directory.
+
+HTML.templatedir = .
+
+HTML.stylesheets = style/narrow.css \
+ style/style.css \
+ style/style_ie6.css \
+ style/style_ie7.css \
+ style/style_ie8.css \
+ style/superfish.css
+
+# Adding jquery and functions - providing online tools and search features
+HTML.scripts = scripts/functions.js \
+ scripts/narrow.js \
+ scripts/superfish.js \
+ scripts/jquery.js
+
+
+# Files not referenced in any qdoc file.
+# See also qhp.Qt.extraFiles
+extraimages.HTML = qt-logo.png \
+ bg_l.png \
+ bg_l_blank.png \
+ bg_ll_blank.png \
+ bg_ul_blank.png \
+ header_bg.png \
+ bg_r.png \
+ box_bg.png \
+ breadcrumb.png \
+ bullet_gt.png \
+ bullet_dn.png \
+ bullet_sq.png \
+ bullet_up.png \
+ arrow_down.png \
+ feedbackground.png \
+ horBar.png \
+ page.png \
+ page_bg.png \
+ sprites-combined.png \
+ spinner.gif
+
+# Include the style sheets and scripts used.
+
+HTML.headerstyles = \
+ " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\" />\n" \
+ " <script src=\"scripts/jquery.js\" type=\"text/javascript\"></script>\n" \
+ " <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n" \
+ " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/superfish.css\" />\n" \
+ " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/narrow.css\" />\n" \
+ " <!--[if IE]>\n" \
+ "<meta name=\"MSSmartTagsPreventParsing\" content=\"true\">\n" \
+ "<meta http-equiv=\"imagetoolbar\" content=\"no\">\n" \
+ "<![endif]-->\n" \
+ "<!--[if lt IE 7]>\n" \
+ "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie6.css\">\n" \
+ "<![endif]-->\n" \
+ "<!--[if IE 7]>\n" \
+ "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie7.css\">\n" \
+ "<![endif]-->\n" \
+ "<!--[if IE 8]>\n" \
+ "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie8.css\">\n" \
+ "<![endif]-->\n\n"
+
+HTML.headerscripts = \
+ "<script src=\"scripts/superfish.js\" type=\"text/javascript\"></script>\n" \
+ "<script src=\"scripts/narrow.js\" type=\"text/javascript\"></script>\n\n"
+
+HTML.endheader = \
+ "</head>\n" \
+ "<body class=\"\" onload=\"CheckEmptyAndLoadList();\">\n"
diff --git a/doc/config/qt-html-templates-online.qdocconf b/doc/config/qt-html-templates-online.qdocconf
new file mode 100644
index 000000000..bbcce442a
--- /dev/null
+++ b/doc/config/qt-html-templates-online.qdocconf
@@ -0,0 +1,142 @@
+include(qt-html-online-styles.qdocconf)
+
+HTML.postheader = \
+ " <div class=\"header\" id=\"qtdocheader\">\n" \
+ " <div class=\"content\"> \n" \
+ " <div id=\"nav-logo\">\n" \
+ " <a href=\"index.html\">Home</a></div>\n" \
+ " <a href=\"index.html\" class=\"qtref\"><span>QtMobility Reference Documentation</span></a>\n" \
+ " <div id=\"narrowsearch\"></div>\n" \
+ " <div id=\"nav-topright\">\n" \
+ " <ul>\n" \
+ " <li class=\"nav-topright-home\"><a href=\"http://qt.nokia.com/\">Qt HOME</a></li>\n" \
+ " <li class=\"nav-topright-dev\"><a href=\"http://developer.qt.nokia.com/\">DEV</a></li>\n" \
+ " <li class=\"nav-topright-labs\"><a href=\"http://labs.qt.nokia.com/blogs/\">LABS</a></li>\n" \
+ " <li class=\"nav-topright-doc nav-topright-doc-active\"><a href=\"http://doc.qt.nokia.com/\">\n" \
+ " DOC</a></li>\n" \
+ " <li class=\"nav-topright-blog\"><a href=\"http://blog.qt.nokia.com/\">BLOG</a></li>\n" \
+ " </ul>\n" \
+ " </div>\n" \
+ " <div id=\"shortCut\">\n" \
+ " <ul>\n" \
+ " <li class=\"shortCut-topleft-inactive\"><span><a href=\"index.html\">QtMobility 1.2</a></span></li>\n" \
+ " <li class=\"shortCut-topleft-active\"><a href=\"http://doc.qt.nokia.com\">ALL VERSIONS" \
+ " </a></li>\n" \
+ " </ul>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " <div class=\"wrapper\">\n" \
+ " <div class=\"hd\">\n" \
+ " <span></span>\n" \
+ " </div>\n" \
+ " <div class=\"bd group\">\n" \
+ " <div class=\"sidebar\">\n" \
+ " <div class=\"box first bottombar\" id=\"lookup\">\n" \
+ " <h2 title=\"API Lookup\">\n" \
+ " API Lookup</h2>\n" \
+ " <div id=\"list001\" class=\"list\">\n" \
+ " <ul id=\"ul001\" >\n" \
+ " <li class=\"defaultLink\"><a href=\"classes.html\">Class index</a></li>\n" \
+ " <li class=\"defaultLink\"><a href=\"functions.html\">Function index</a></li>\n" \
+ " <li class=\"defaultLink\"><a href=\"modules.html\">Modules</a></li>\n" \
+ " <li class=\"defaultLink\"><a href=\"qml-plugins.html\">QML Plugins</a></li>\n" \
+ " </ul> \n" \
+ " </div>\n" \
+ " </div>\n" \
+ " <div class=\"box bottombar\" id=\"topics\">\n" \
+ " <h2 title=\"QtMobility Topics\"><span></span>\n" \
+ " Qt Topics</h2>\n" \
+ " <div id=\"list002\" class=\"list\">\n" \
+ " <ul id=\"ul002\" >\n" \
+ " <li class=\"defaultLink\"><a href=\"quickstart.html\">Quickstart Guide</a></li> \n" \
+ " <li class=\"defaultLink\"><a href=\"index.html#platform-compatibility\">Platform-specific info</a></li> \n" \
+ " </ul> \n" \
+ " </div>\n" \
+ " </div>\n" \
+ " <div class=\"box\" id=\"examples\">\n" \
+ " <h2 title=\"Examples\"><span></span>\n" \
+ " Examples</h2>\n" \
+ " <div id=\"list003\" class=\"list\">\n" \
+ " <ul id=\"ul003\">\n" \
+ " <li class=\"defaultLink\"><a href=\"all-examples.html\">Examples</a></li>\n" \
+ " <li class=\"defaultLink\"><a href=\"tutorials.html\">Tutorials</a></li>\n" \
+ " </ul> \n" \
+ " </div>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " <div class=\"wrap\">\n" \
+ " <div class=\"toolbar\">\n" \
+ " <div class=\"breadcrumb toolblock\">\n" \
+ " <ul>\n" \
+ " <li class=\"first\"><a href=\"index.html\">Home</a></li>\n" \
+ " <!-- Breadcrumbs go here -->\n"
+
+HTML.postpostheader = \
+ " </ul>\n" \
+ " </div>\n" \
+ " <div class=\"toolbuttons toolblock\">\n" \
+ " <ul>\n" \
+ " <li id=\"smallA\" class=\"t_button\">A</li>\n" \
+ " <li id=\"medA\" class=\"t_button active\">A</li>\n" \
+ " <li id=\"bigA\" class=\"t_button\">A</li>\n" \
+ " <li id=\"print\" class=\"t_button\"><a href=\"javascript:this.print();\">\n" \
+ " <span>Print</span></a></li>\n" \
+ " </ul>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " <div class=\"content mainContent\">\n"
+
+HTML.footer = \
+ " <div class=\"feedback t_button\">\n" \
+ " [+] Documentation Feedback</div>\n" \
+ " </div>\n" \
+ " </div>\n" \
+ " </div> \n" \
+ " <div class=\"ft\">\n" \
+ " <span></span>\n" \
+ " </div>\n" \
+ " </div> \n" \
+ " <div class=\"footer\">\n" \
+ " <p>\n" \
+ " <acronym title=\"Copyright\">&copy;</acronym> 2008-2011 Nokia Corporation and/or its\n" \
+ " subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation \n" \
+ " in Finland and/or other countries worldwide.</p>\n" \
+ " <p>\n" \
+ " All other trademarks are property of their respective owners. <a title=\"Privacy Policy\"\n" \
+ " href=\"http://qt.nokia.com/about/privacy-policy\">Privacy Policy</a></p>\n" \
+ " <br />\n" \
+ " <p>\n" \
+ " Licensees holding valid Qt Commercial licenses may use this document in accordance with the" \
+ " Qt Commercial License Agreement provided with the Software or, alternatively, in accordance" \
+ " with the terms contained in a written agreement between you and Nokia.</p>\n" \
+ " <p>\n" \
+ " Alternatively, this document may be used under the terms of the <a href=\"http://www.gnu.org/licenses/fdl.html\">GNU\n" \
+ " Free Documentation License version 1.3</a>\n" \
+ " as published by the Free Software Foundation.</p>\n" \
+ " </div>\n" \
+ " <div id=\"feedbackBox\">\n" \
+ " <div id=\"feedcloseX\" class=\"feedclose t_button\">X</div>\n" \
+ " <form id=\"feedform\" action=\"http://doc.qt.nokia.com/docFeedbck/feedback.php\" method=\"get\">\n" \
+ " <p id=\"noteHead\">Thank you for giving your feedback.</p> <p class=\"note\">Make sure it is related to this specific page. For more general bugs and \n" \
+ " requests, please use the <a href=\"http://bugreports.qt.nokia.com/secure/Dashboard.jspa\">Qt Bug Tracker</a>.</p>\n" \
+ " <p><textarea id=\"feedbox\" name=\"feedText\" rows=\"5\" cols=\"40\"></textarea></p>\n" \
+ " <p><input id=\"feedsubmit\" class=\"feedclose\" type=\"submit\" name=\"feedback\" /></p>\n" \
+ " </form>\n" \
+ " </div>\n" \
+ " <div id=\"blurpage\">\n" \
+ " </div>\n" \
+ "\n" \
+ " <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n" \
+ " <script type=\"text/javascript\">\n" \
+ " var _gaq = _gaq || [];\n" \
+ " _gaq.push(['_setAccount', 'UA-4457116-5']);\n" \
+ " _gaq.push(['_trackPageview']);\n" \
+ " (function() {\n" \
+ " var ga = document.createElement('script'); " \
+ "ga.type = 'text/javascript'; ga.async = true;\n" \
+ " ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + " \
+ "'.google-analytics.com/ga.js';\n" \
+ " var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n" \
+ " })();\n" \
+ " </script>\n"
diff --git a/doc/config/qt-html-templates.qdocconf b/doc/config/qt-html-templates.qdocconf
new file mode 100644
index 000000000..c1a6569a6
--- /dev/null
+++ b/doc/config/qt-html-templates.qdocconf
@@ -0,0 +1,54 @@
+include(qt-html-default-styles.qdocconf)
+
+HTML.postheader = \
+ "<div class=\"header\" id=\"qtdocheader\">\n" \
+ " <div class=\"content\"> \n" \
+ " <a href=\"index.html\" class=\"qtref\"><span>QtMobility Reference Documentation</span></a>\n" \
+ " </div>\n" \
+ " <div class=\"breadcrumb toolblock\">\n" \
+ " <ul>\n" \
+ " <li class=\"first\"><a href=\"index.html\">Home</a></li>\n" \
+ " <!-- Breadcrumbs go here -->\n"
+
+HTML.postpostheader = \
+ " </ul>\n" \
+ " </div>\n" \
+ "</div>\n" \
+ "<div class=\"content mainContent\">\n"
+
+HTML.footer = \
+ " <div class=\"ft\">\n" \
+ " <span></span>\n" \
+ " </div>\n" \
+ "</div> \n" \
+ "<div class=\"footer\">\n" \
+ " <p>\n" \
+ " <acronym title=\"Copyright\">&copy;</acronym> 2008-2011 Nokia Corporation and/or its\n" \
+ " subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation \n" \
+ " in Finland and/or other countries worldwide.</p>\n" \
+ " <p>\n" \
+ " All other trademarks are property of their respective owners. <a title=\"Privacy Policy\"\n" \
+ " href=\"http://qt.nokia.com/about/privacy-policy\">Privacy Policy</a></p>\n" \
+ " <br />\n" \
+ " <p>\n" \
+ " Licensees holding valid Qt Commercial licenses may use this document in accordance with the" \
+ " Qt Commercial License Agreement provided with the Software or, alternatively, in accordance" \
+ " with the terms contained in a written agreement between you and Nokia.</p>\n" \
+ " <p>\n" \
+ " Alternatively, this document may be used under the terms of the <a href=\"http://www.gnu.org/licenses/fdl.html\">GNU\n" \
+ " Free Documentation License version 1.3</a>\n" \
+ " as published by the Free Software Foundation.</p>\n" \
+ "</div>\n" \
+
+# Files not referenced in any qdoc file.
+# See also extraimages.HTML
+qhp.QtMobility.extraFiles = index.html \
+ images/arrow_down.png \
+ images/breadcrumb.png \
+ images/bullet_gt.png \
+ images/bullet_dn.png \
+ images/bullet_sq.png \
+ images/bullet_up.png \
+ images/horBar.png \
+ images/sprites-combined.png \
+ style/offline.css
diff --git a/doc/config/qtmobility-cpp-ignore.qdocconf b/doc/config/qtmobility-cpp-ignore.qdocconf
new file mode 100644
index 000000000..faa9fe135
--- /dev/null
+++ b/doc/config/qtmobility-cpp-ignore.qdocconf
@@ -0,0 +1,18 @@
+Cpp.ignoretokens += \
+ QTM_BEGIN_NAMESPACE \
+ QTM_END_NAMESPACE \
+ Q_BEARER_EXPORT \
+ Q_PUBLISHSUBSCRIBE_EXPORT \
+ Q_CONTACTS_EXPORT \
+ Q_VERSIT_EXPORT \
+ Q_LOCATION_EXPORT \
+ Q_MULTIMEDIA_EXPORT \
+ Q_MESSAGING_EXPORT \
+ Q_SERVICEFW_EXPORT \
+ Q_SYSINFO_EXPORT \
+ Q_SENSORS_EXPORT \
+ Q_FEEDBACK_EXPORT \
+ Q_GALLERY_EXPORT \
+ Q_ORGANIZER_EXPORT
+Cpp.ignoredirectives += \
+ Q_DECLARE_NDEF_RECORD
diff --git a/doc/config/qtmobility-ditaxml.qdocconf b/doc/config/qtmobility-ditaxml.qdocconf
new file mode 100644
index 000000000..338e40863
--- /dev/null
+++ b/doc/config/qtmobility-ditaxml.qdocconf
@@ -0,0 +1,13 @@
+include(qtmobility-project.qdocconf)
+
+outputdir = ../ditaxml
+outputformats = DITAXML
+
+generateindex = true
+url = .
+
+macro.beginfloatleft.HTML = " "
+macro.beginfloatright.HTML = " "
+macro.endfloat.HTML = " "
+macro.clearfloat.HTML = " "
+macro.emptyspan.DITAXML = " "
diff --git a/doc/config/qtmobility-online.qdocconf b/doc/config/qtmobility-online.qdocconf
new file mode 100644
index 000000000..515003a34
--- /dev/null
+++ b/doc/config/qtmobility-online.qdocconf
@@ -0,0 +1,2 @@
+include(qtmobility-project.qdocconf)
+include(qt-html-templates-online.qdocconf)
diff --git a/doc/config/qtmobility-project.qdocconf b/doc/config/qtmobility-project.qdocconf
new file mode 100644
index 000000000..8a29b0a8f
--- /dev/null
+++ b/doc/config/qtmobility-project.qdocconf
@@ -0,0 +1,142 @@
+include(compat.qdocconf)
+include(macros.qdocconf)
+include(qt-cpp-ignore.qdocconf)
+include(qt-defines.qdocconf)
+include(qtmobility-cpp-ignore.qdocconf)
+
+indexes = ../src/qt.index
+
+language = Cpp
+
+sourceencoding = UTF-8
+outputencoding = UTF-8
+naturallanguage = en_US
+
+project = Qt Mobility
+description = Qt Mobility Project Library Reference Documentation
+versionsym =
+version = 1.2
+url = http://qt.nokia.com/doc/qtmobility-1.2
+
+sources.fileextensions = "*.cpp *.qdoc *.mm *.qml"
+headers.fileextensions = "*.ch *.h *.h++ *.hh *.hpp *.hxx"
+examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml"
+examples.imageextensions = "*.png *.jpeg *.jpg *.gif *.mng"
+
+headerdirs = ../../src/global \
+ ../../src/bearer \
+ ../../src/feedback \
+ ../../src/serviceframework \
+ ../../src/location \
+ ../../src/publishsubscribe \
+ ../../src/systeminfo \
+ ../../src/contacts \
+ ../../src/contacts/details \
+ ../../src/multimedia \
+ ../../plugins/declarative/multimedia \
+ ../../plugins/declarative/location \
+ ../../plugins/declarative/organizer \
+ ../../plugins/declarative/connectivity \
+ ../../plugins/declarative/contacts \
+ ../../plugins/declarative/contacts/details \
+ ../../plugins/declarative/contacts/filters \
+ ../../plugins/declarative/gallery \
+ ../../plugins/declarative/serviceframework \
+ ../../plugins/declarative/organizer \
+ ../../plugins/declarative/contacts \
+ ../../plugins/declarative/feedback \
+ ../../plugins/declarative/messaging \
+ ../../plugins/declarative/sensors \
+ ../../plugins/declarative/publishsubscribe \
+ ../../plugins/declarative/systeminfo \
+ ../../src/messaging \
+ ../../src/versit \
+ ../../src/sensors \
+ ../../src/gallery \
+ ../../src/camera \
+ ../../src/organizer \
+ ../../src/versitorganizer \
+ ../../src/connectivity \
+ ../src
+
+sourcedirs = ../../src/global \
+ ../../src/bearer \
+ ../../src/feedback \
+ ../../src/serviceframework \
+ ../../src/location \
+ ../../src/publishsubscribe \
+ ../../src/systeminfo \
+ ../../src/contacts \
+ ../../src/contacts/details \
+ ../../src/multimedia \
+ ../../plugins/declarative/multimedia \
+ ../../plugins/declarative/location \
+ ../../plugins/declarative/organizer \
+ ../../plugins/declarative/connectivity \
+ ../../plugins/declarative/contacts \
+ ../../plugins/declarative/contacts/details \
+ ../../plugins/declarative/contacts/filters \
+ ../../plugins/declarative/messaging \
+ ../../plugins/declarative/serviceframework \
+ ../../plugins/declarative/organizer \
+ ../../plugins/declarative/contacts \
+ ../../plugins/declarative/feedback \
+ ../../plugins/declarative/gallery \
+ ../../plugins/declarative/sensors \
+ ../../plugins/declarative/publishsubscribe \
+ ../../plugins/declarative/systeminfo \
+ ../../plugins/declarative/sensors \
+ ../../src/messaging \
+ ../../src/versit \
+ ../../src/sensors \
+ ../../src/gallery \
+ ../../src/camera \
+ ../../src/organizer \
+ ../../src/connectivity \
+ ../../src/versitorganizer \
+ ../src
+
+excludedirs = ../../src/messaging/win32wce \
+ ../../src/publishsubscribe/symbian \
+ ../../src/serviceframework/ipc/metaobjectbuilder47
+
+exampledirs = ../../examples \
+ ../../demos \
+ ../.. \
+ ../src
+
+imagedirs = images \
+ ../src/images
+
+outputdir = ../html
+tagfile = ../html/qtmobility.tags
+base = file:../html
+
+qhp.projects = QtMobility
+
+qhp.QtMobility.file = qtmobility.qhp
+qhp.QtMobility.namespace = com.nokia.qtmobility.114
+qhp.QtMobility.virtualFolder = mobility
+qhp.QtMobility.indexTitle = Qt Mobility Project Reference Documentation
+qhp.QtMobility.indexRoot =
+
+qhp.QtMobility.filterAttributes = qtmobility 1.2.0
+qhp.QtMobility.customFilters.QtMobility.name = Qt Mobility 1.2.0
+qhp.QtMobility.customFilters.QtMobility.filterAttributes = qtmobility 1.2.0
+qhp.QtMobility.subprojects = classes overviews examples
+qhp.QtMobility.subprojects.classes.title = Classes
+qhp.QtMobility.subprojects.classes.indexTitle = All Qt Mobility Project Classes
+qhp.QtMobility.subprojects.classes.selectors = class
+qhp.QtMobility.subprojects.classes.sortPages = true
+qhp.QtMobility.subprojects.overviews.title = Overviews
+qhp.QtMobility.subprojects.overviews.indexTitle = Qt Mobility Project Overview
+qhp.QtMobility.subprojects.overviews.selectors = fake:page,group
+qhp.QtMobility.subprojects.overviews.sortPages = true
+qhp.QtMobility.subprojects.examples.title = Examples
+qhp.QtMobility.subprojects.examples.indexTitle = Qt Mobility Project Examples
+qhp.QtMobility.subprojects.examples.selectors = fake:example
+qhp.QtMobility.subprojects.examples.sortPages = true
+qhp.QtMobility.subprojects.tutorials.title = Tutorials
+qhp.QtMobility.subprojects.tutorials.indexTitle = Qt Mobility Project Tutorials
+qhp.QtMobility.subprojects.tutorials.selectors = fake:tutorial
+qhp.QtMobility.subprojects.tutorials.sortPages = true
diff --git a/doc/config/qtmobility.qdocconf b/doc/config/qtmobility.qdocconf
new file mode 100644
index 000000000..75fba31d3
--- /dev/null
+++ b/doc/config/qtmobility.qdocconf
@@ -0,0 +1,2 @@
+include(qtmobility-project.qdocconf)
+include(qt-html-templates.qdocconf)
diff --git a/doc/config/scripts/functions.js b/doc/config/scripts/functions.js
new file mode 100644
index 000000000..62bc53508
--- /dev/null
+++ b/doc/config/scripts/functions.js
@@ -0,0 +1,258 @@
+// Removing search results
+function hideSearchResults() {
+/* hiding search results as the user clicks on the different categories */
+ $('#resultdialog').removeClass('active');
+ $("#resultlist").removeClass().addClass('all');
+ $("#resultlinks").removeClass().addClass('all');
+ $("#searchcount").removeClass().addClass('all');
+}
+/* closing the searhc result dialog */
+$('#resultclose').click(function(e) {
+ e.preventDefault();
+ hideSearchResults();
+});
+
+$(document.body).click(function() {
+});
+
+/* START non link areas where cursor should change to pointing hand */
+$('.t_button').mouseover(function() {
+ $('.t_button').css('cursor','pointer');
+});
+/* END non link areas */
+/* Changing font size to smaller */
+$('#smallA').click(function() {
+ $('.mainContent .heading,.mainContent h1, .mainContent h2, .mainContent h3, .mainContent p, .mainContent li, .mainContent table').css('font-size','smaller');
+ $('.t_button').removeClass('active')
+ $(this).addClass('active')
+});
+
+/* Reset font size */
+$('#medA').click(function() {
+ $('.mainContent .heading').css('font','600 16px/1 Arial');
+ $('.mainContent h1').css('font','600 18px/1.2 Arial');
+ $('.mainContent h2').css('font','600 16px/1.2 Arial');
+ $('.mainContent h3').css('font','600 14px/1.2 Arial');
+ $('.mainContent p').css('font','13px/20px Verdana');
+ $('.mainContent li').css('font','400 13px/1 Verdana');
+ $('.mainContent li').css('line-height','14px');
+ $('.mainContent .toc li').css('font', 'normal 10px/1.2 Verdana');
+ $('.mainContent table').css('font','13px/1.2 Verdana');
+ $('.mainContent .heading').css('font','600 16px/1 Arial');
+ $('.mainContent .indexboxcont li').css('font','600 13px/1 Verdana');
+ $('.t_button').removeClass('active')
+ $(this).addClass('active')
+});
+/* Changing font size to bigger */
+$('#bigA').click(function() {
+ $('.mainContent .heading,.mainContent h1, .mainContent h2, .mainContent h3, .mainContent p, .mainContent li, .mainContent table').css('font-size','large');
+ $('.mainContent .heading,.mainContent h1, .mainContent h2, .mainContent h3, .mainContent p, .mainContent li, .mainContent table').css('line-height','25px');
+ $('.t_button').removeClass('active')
+ $(this).addClass('active')
+});
+
+/* Show page content after closing feedback box */
+$('.feedclose').click(function() {
+ $('.bd').show();
+ $('.hd').show();
+ $('.footer').show();
+ $('#feedbackBox').hide();
+ $('#blurpage').hide();
+});
+
+/* Hide page content and show feedback box */
+$('.feedback').click(function() {
+ $('.bd').hide();
+ $('.hd').hide();
+ $('.footer').hide();
+ $('#feedbackBox').show();
+ $('#blurpage').show();
+});
+/* Default search URL */
+var qturl = "";
+
+/* The next function handles the response data (in xml) returned by the search engine */
+
+// Process data sent back from the server. The data is structured as a XML.
+/*
+XML structure handled by function processNokiaData()
+<page> - container for each page returned
+<pageWords/> - contains keywords
+<pageTitle/> - contains page title/header content
+<pageUrl/> - contains page URL - URL relative to root
+<pageType> - contains page type - APIPage/Article/Example
+</page>
+*/
+
+
+function processNokiaData(response){
+/* fetch the responce from the server using page as the root element */
+ var propertyTags = response.getElementsByTagName('page');
+ /* reset counters */
+ var apiCount = 0;
+ var articleCount = 0;
+ var exampleCount = 0;
+ var full_li_element;
+
+/* remove any old results */
+ $('#resultlist li').remove();
+
+
+ /* running through the elements in the xml structure */
+ for (var i=0; i<propertyTags.length; i++) {
+ /* for every element named pageWords*/
+ for (var j=0; j< propertyTags[i].getElementsByTagName('pageWords').length; j++) {
+ /* start a new list element */
+ full_li_element = '<li';
+ /* if the pageType element reads APIPage, add class name api */
+ if (propertyTags[i].getElementsByTagName('pageType')[0].firstChild.nodeValue == 'APIPage') {
+ full_li_element += ' class="api"';
+ apiCount++;
+ }
+ /* if the pageType element reads Article, add class name article */
+ else if (propertyTags[i].getElementsByTagName('pageType')[0].firstChild.nodeValue == 'Article') {
+ full_li_element += ' class="article"';
+ articleCount++;
+ }
+ /* if the pageType element reads Example, add class name example */
+ else if (propertyTags[i].getElementsByTagName('pageType')[0].firstChild.nodeValue == 'Example') {
+ full_li_element += ' class="example"';
+ exampleCount++;
+ }
+ /* adding the link element*/
+ full_li_element += '><a href="'+qturl;
+ /* adding the URL attribute*/
+ full_li_element += propertyTags[i].getElementsByTagName('pageUrl')[j].firstChild.nodeValue;
+ /* adding the link title and closing the link and list elements */
+ full_li_element += '">' + propertyTags[i].getElementsByTagName('pageWords')[0].firstChild.nodeValue + '</a></li>';
+ /* appending the list element to the #resultlist div*/
+ $('#resultlist').append(full_li_element);
+ }
+ }
+
+ /* if the result is not empty */
+ if (propertyTags.length > 0) {
+ /* add class name active to show the dialog */
+ $('#resultdialog').addClass('active');
+ /* setting number of hits*/
+ $('#resultcount').html(propertyTags.length);
+ $('#apicount').html(apiCount);
+ $('#articlecount').html(articleCount);
+ $('#examplecount').html(exampleCount);
+
+ }
+ else {
+ $('#pageType').addClass('red');
+ }
+
+
+
+ // Filtering results in display
+ $('p#resultlinks a').click(function(e) {
+ e.preventDefault();
+ // Displays API ref pages
+ if (this.id == "showapiresults") {
+ $("#resultlist").removeClass().addClass('api');
+ $("#resultlinks").removeClass().addClass('api');
+ $("#searchcount").removeClass().addClass('api');
+ }
+ // Displays Articles
+ else if (this.id == "showarticleresults") {
+ $("#resultlist").removeClass().addClass('article');
+ $("#resultlinks").removeClass().addClass('article');
+ $("#searchcount").removeClass().addClass('article');
+ }
+ // Displays Examples
+ if (this.id == "showexampleresults") {
+ $("#resultlist").removeClass().addClass('example');
+ $("#resultlinks").removeClass().addClass('example');
+ $("#searchcount").removeClass().addClass('example');
+ }
+ // Displays All
+ if (this.id == "showallresults") {
+ $("#resultlist").removeClass().addClass('all');
+ $("#resultlinks").removeClass().addClass('all');
+ $("#searchcount").removeClass().addClass('all');
+ }
+ });
+}
+
+//build regular expression object to find empty string or any number of blank
+var blankRE=/^\s*$/;
+
+
+function CheckEmptyAndLoadList()
+{
+ /* Start Extracting information for feedback and adding this to the feedback form */
+ var pageUrl = window.location.href;
+ var pageVal = $('title').html();
+ $('#pageType').removeClass('red');
+ $('#feedUrl').remove();
+ $('#pageVal').remove();
+ $('.menuAlert').remove();
+ $('#feedform').append('<input id="feedUrl" name="feedUrl" value="'+pageUrl+'" style="display:none;">');
+ $('#feedform').append('<input id="pageVal" name="pageVal" value="'+pageVal+'" style="display:none;">');
+ /* End Extracting information for feedback and adding this to the feedback form */
+
+ /* extracts search query */
+ var value = document.getElementById('pageType').value;
+ /* if the search is less than three chars long remove class names and remove elements from old search*/
+ if((blankRE.test(value)) || (value.length < 3))
+ {
+ $('#resultdialog').removeClass('active');
+ $('#resultlist li').remove();
+ }
+}
+
+// Loads on doc ready - prepares search
+ $(document).ready(function () {
+ /* fetch page title*/
+ var pageTitle = $('title').html();
+ /* getting content from search box */
+ var currentString = $('#pageType').val() ;
+ /* if the search box is not empty run CheckEmptyAndLoadList*/
+ if(currentString.length < 1){
+ CheckEmptyAndLoadList();
+ }
+
+ /* on key-up in the search box execute the following */
+ $('#pageType').keyup(function () {
+ /* extract the search box content */
+ var searchString = $('#pageType').val() ;
+ /* if the string is less than three characters */
+ if ((searchString == null) || (searchString.length < 3)) {
+ /* remove classes and elements*/
+ $('#pageType').removeClass('loading');
+ $('.searching').remove();
+ /* run CheckEmptyAndLoadList */
+ CheckEmptyAndLoadList();
+
+ $('.report').remove();
+ return;
+ }
+ /* if timer checks out */
+ if (this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(function () {
+ /* add loading image by adding loading class */
+ $('#pageType').addClass('loading');
+ $('.searching').remove();
+
+ /* run the actual search */
+ $.ajax({
+ contentType: "application/x-www-form-urlencoded",
+ url: 'http://' + location.host + '/nokiasearch/GetDataServlet',
+ data: 'searchString='+searchString,
+ dataType:'xml',
+ type: 'post',
+ success: function (response, textStatus) {
+ /* on success remove loading img */
+ $('.searching').remove();
+ $('#pageType').removeClass('loading');
+
+ processNokiaData(response);
+
+ }
+ });
+ }, 500); /* timer set to 500 ms */
+ });
+ }); \ No newline at end of file
diff --git a/doc/config/scripts/jquery.js b/doc/config/scripts/jquery.js
new file mode 100644
index 000000000..0c7294c90
--- /dev/null
+++ b/doc/config/scripts/jquery.js
@@ -0,0 +1,152 @@
+/*!
+ * jQuery JavaScript Library v1.4.1
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Mon Jan 25 19:43:33 2010 -0500
+ */
+(function(z,v){function la(){if(!c.isReady){try{r.documentElement.doScroll("left")}catch(a){setTimeout(la,1);return}c.ready()}}function Ma(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,i){var j=a.length;if(typeof b==="object"){for(var n in b)X(a,n,b[n],f,e,d);return a}if(d!==v){f=!i&&f&&c.isFunction(d);for(n=0;n<j;n++)e(a[n],b,f?d.call(a[n],n,e(a[n],b)):d,i);return a}return j?
+e(a[0],b):null}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function ma(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function na(a){var b,d=[],f=[],e=arguments,i,j,n,o,m,s,x=c.extend({},c.data(this,"events").live);if(!(a.button&&a.type==="click")){for(o in x){j=x[o];if(j.live===a.type||j.altLive&&c.inArray(a.type,j.altLive)>-1){i=j.data;i.beforeFilter&&i.beforeFilter[a.type]&&!i.beforeFilter[a.type](a)||f.push(j.selector)}else delete x[o]}i=c(a.target).closest(f,
+a.currentTarget);m=0;for(s=i.length;m<s;m++)for(o in x){j=x[o];n=i[m].elem;f=null;if(i[m].selector===j.selector){if(j.live==="mouseenter"||j.live==="mouseleave")f=c(a.relatedTarget).closest(j.selector)[0];if(!f||f!==n)d.push({elem:n,fn:j})}}m=0;for(s=d.length;m<s;m++){i=d[m];a.currentTarget=i.elem;a.data=i.fn.data;if(i.fn.apply(i.elem,e)===false){b=false;break}}return b}}function oa(a,b){return"live."+(a?a+".":"")+b.replace(/\./g,"`").replace(/ /g,"&")}function pa(a){return!a||!a.parentNode||a.parentNode.nodeType===
+11}function qa(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var i in f)for(var j in f[i])c.event.add(this,i,f[i][j],f[i][j].data)}}})}function ra(a,b,d){var f,e,i;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&a[0].indexOf("<option")<0&&(c.support.checkClone||!sa.test(a[0]))){e=true;if(i=c.fragments[a[0]])if(i!==1)f=i}if(!f){b=b&&b[0]?b[0].ownerDocument||b[0]:r;f=b.createDocumentFragment();
+c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=i?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(ta.concat.apply([],ta.slice(0,b)),function(){d[this]=a});return d}function ua(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Na=z.jQuery,Oa=z.$,r=z.document,S,Pa=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Qa=/^.[^:#\[\.,]*$/,Ra=/\S/,Sa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Ta=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,O=navigator.userAgent,
+va=false,P=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,Q=Array.prototype.slice,wa=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(typeof a==="string")if((d=Pa.exec(a))&&(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:r;if(a=Ta.exec(a))if(c.isPlainObject(b)){a=[r.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=ra([d[1]],
+[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}}else{if(b=r.getElementById(d[2])){if(b.id!==d[2])return S.find(a);this.length=1;this[0]=b}this.context=r;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=r;a=r.getElementsByTagName(a)}else return!b||b.jquery?(b||S).find(a):c(b).find(a);else if(c.isFunction(a))return S.ready(a);if(a.selector!==v){this.selector=a.selector;this.context=a.context}return c.isArray(a)?this.setArray(a):c.makeArray(a,
+this)},selector:"",jquery:"1.4.1",length:0,size:function(){return this.length},toArray:function(){return Q.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){a=c(a||null);a.prevObject=this;a.context=this.context;if(b==="find")a.selector=this.selector+(this.selector?" ":"")+d;else if(b)a.selector=this.selector+"."+b+"("+d+")";return a},setArray:function(a){this.length=0;ba.apply(this,a);return this},each:function(a,b){return c.each(this,
+a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(r,c);else P&&P.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(Q.apply(this,arguments),"slice",Q.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};
+c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,i,j,n;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(i in e){j=a[i];n=e[i];if(a!==n)if(f&&n&&(c.isPlainObject(n)||c.isArray(n))){j=j&&(c.isPlainObject(j)||c.isArray(j))?j:c.isArray(n)?[]:{};a[i]=c.extend(f,j,n)}else if(n!==v)a[i]=n}return a};c.extend({noConflict:function(a){z.$=
+Oa;if(a)z.jQuery=Na;return c},isReady:false,ready:function(){if(!c.isReady){if(!r.body)return setTimeout(c.ready,13);c.isReady=true;if(P){for(var a,b=0;a=P[b++];)a.call(r,c);P=null}c.fn.triggerHandler&&c(r).triggerHandler("ready")}},bindReady:function(){if(!va){va=true;if(r.readyState==="complete")return c.ready();if(r.addEventListener){r.addEventListener("DOMContentLoaded",L,false);z.addEventListener("load",c.ready,false)}else if(r.attachEvent){r.attachEvent("onreadystatechange",L);z.attachEvent("onload",
+c.ready);var a=false;try{a=z.frameElement==null}catch(b){}r.documentElement.doScroll&&a&&la()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,"isPrototypeOf"))return false;var b;for(b in a);return b===v||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;
+return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return z.JSON&&z.JSON.parse?z.JSON.parse(a):(new Function("return "+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Ra.test(a)){var b=r.getElementsByTagName("head")[0]||
+r.documentElement,d=r.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(r.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,i=a.length,j=i===v||c.isFunction(a);if(d)if(j)for(f in a){if(b.apply(a[f],d)===false)break}else for(;e<i;){if(b.apply(a[e++],d)===false)break}else if(j)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=
+a[0];e<i&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Sa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==
+v;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,i=a.length;e<i;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,i=0,j=a.length;i<j;i++){e=b(a[i],i,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=v}else if(b&&!c.isFunction(b)){d=b;b=v}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},
+uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});O=c.uaMatch(O);if(O.browser){c.browser[O.browser]=true;c.browser.version=O.version}if(c.browser.webkit)c.browser.safari=true;if(wa)c.inArray=function(a,b){return wa.call(b,a)};S=c(r);if(r.addEventListener)L=function(){r.removeEventListener("DOMContentLoaded",
+L,false);c.ready()};else if(r.attachEvent)L=function(){if(r.readyState==="complete"){r.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=r.documentElement,b=r.createElement("script"),d=r.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var e=d.getElementsByTagName("*"),i=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!i)){c.support=
+{leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(i.getAttribute("style")),hrefNormalized:i.getAttribute("href")==="/a",opacity:/^0.55$/.test(i.style.opacity),cssFloat:!!i.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:r.createElement("select").appendChild(r.createElement("option")).selected,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};
+b.type="text/javascript";try{b.appendChild(r.createTextNode("window."+f+"=1;"))}catch(j){}a.insertBefore(b,a.firstChild);if(z[f]){c.support.scriptEval=true;delete z[f]}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function n(){c.support.noCloneEvent=false;d.detachEvent("onclick",n)});d.cloneNode(true).fireEvent("onclick")}d=r.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=r.createDocumentFragment();a.appendChild(d.firstChild);
+c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var n=r.createElement("div");n.style.width=n.style.paddingLeft="1px";r.body.appendChild(n);c.boxModel=c.support.boxModel=n.offsetWidth===2;r.body.removeChild(n).style.display="none"});a=function(n){var o=r.createElement("div");n="on"+n;var m=n in o;if(!m){o.setAttribute(n,"return;");m=typeof o[n]==="function"}return m};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=i=null}})();c.props=
+{"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ua=0,xa={},Va={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==z?xa:a;var f=a[G],e=c.cache;if(!b&&!f)return null;f||(f=++Ua);if(typeof b==="object"){a[G]=f;e=e[f]=c.extend(true,
+{},b)}else e=e[f]?e[f]:typeof d==="undefined"?Va:(e[f]={});if(d!==v){a[G]=f;e[b]=d}return typeof b==="string"?e[b]:e}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==z?xa:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{try{delete a[G]}catch(i){a.removeAttribute&&a.removeAttribute(G)}delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,
+a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===v){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===v&&this.length)f=c.data(this[0],a);return f===v&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);
+return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===v)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||
+a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var ya=/[\n\t]/g,ca=/\s+/,Wa=/\r/g,Xa=/href|src|style/,Ya=/(button|input)/i,Za=/(button|input|object|select|textarea)/i,$a=/^(a|area)$/i,za=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(o){var m=
+c(this);m.addClass(a.call(this,o,m.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className)for(var i=" "+e.className+" ",j=0,n=b.length;j<n;j++){if(i.indexOf(" "+b[j]+" ")<0)e.className+=" "+b[j]}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(o){var m=c(this);m.removeClass(a.call(this,o,m.attr("class")))});if(a&&typeof a==="string"||a===v)for(var b=(a||"").split(ca),
+d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var i=(" "+e.className+" ").replace(ya," "),j=0,n=b.length;j<n;j++)i=i.replace(" "+b[j]+" "," ");e.className=i.substring(1,i.length-1)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var i=c(this);i.toggleClass(a.call(this,e,i.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,i=0,j=c(this),n=b,o=
+a.split(ca);e=o[i++];){n=f?n:!j.hasClass(e);j[n?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(ya," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===v){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||
+{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var i=b?d:0;for(d=b?d+1:e.length;i<d;i++){var j=e[i];if(j.selected){a=c(j).val();if(b)return a;f.push(a)}}return f}if(za.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Wa,"")}return v}var n=c.isFunction(a);return this.each(function(o){var m=c(this),s=a;if(this.nodeType===1){if(n)s=a.call(this,o,m.val());
+if(typeof s==="number")s+="";if(c.isArray(s)&&za.test(this.type))this.checked=c.inArray(m.val(),s)>=0;else if(c.nodeName(this,"select")){var x=c.makeArray(s);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),x)>=0});if(!x.length)this.selectedIndex=-1}else this.value=s}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return v;if(f&&b in c.attrFn)return c(a)[b](d);
+f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==v;b=f&&c.props[b]||b;if(a.nodeType===1){var i=Xa.test(b);if(b in a&&f&&!i){if(e){b==="type"&&Ya.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Za.test(a.nodeName)||$a.test(a.nodeName)&&a.href?0:v;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=
+""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&i?a.getAttribute(b,2):a.getAttribute(b);return a===null?v:a}return c.style(a,b,d)}});var ab=function(a){return a.replace(/[^\w\s\.\|`]/g,function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==z&&!a.frameElement)a=z;if(!d.guid)d.guid=c.guid++;if(f!==v){d=c.proxy(d);d.data=f}var e=c.data(a,"events")||c.data(a,"events",{}),i=c.data(a,"handle"),j;if(!i){j=
+function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(j.elem,arguments):v};i=c.data(a,"handle",j)}if(i){i.elem=a;b=b.split(/\s+/);for(var n,o=0;n=b[o++];){var m=n.split(".");n=m.shift();if(o>1){d=c.proxy(d);if(f!==v)d.data=f}d.type=m.slice(0).sort().join(".");var s=e[n],x=this.special[n]||{};if(!s){s=e[n]={};if(!x.setup||x.setup.call(a,f,m,d)===false)if(a.addEventListener)a.addEventListener(n,i,false);else a.attachEvent&&a.attachEvent("on"+n,i)}if(x.add)if((m=x.add.call(a,
+d,f,m,s))&&c.isFunction(m)){m.guid=m.guid||d.guid;m.data=m.data||d.data;m.type=m.type||d.type;d=m}s[d.guid]=d;this.global[n]=true}a=null}}},global:{},remove:function(a,b,d){if(!(a.nodeType===3||a.nodeType===8)){var f=c.data(a,"events"),e,i,j;if(f){if(b===v||typeof b==="string"&&b.charAt(0)===".")for(i in f)this.remove(a,i+(b||""));else{if(b.type){d=b.handler;b=b.type}b=b.split(/\s+/);for(var n=0;i=b[n++];){var o=i.split(".");i=o.shift();var m=!o.length,s=c.map(o.slice(0).sort(),ab);s=new RegExp("(^|\\.)"+
+s.join("\\.(?:.*\\.)?")+"(\\.|$)");var x=this.special[i]||{};if(f[i]){if(d){j=f[i][d.guid];delete f[i][d.guid]}else for(var A in f[i])if(m||s.test(f[i][A].type))delete f[i][A];x.remove&&x.remove.call(a,o,j);for(e in f[i])break;if(!e){if(!x.teardown||x.teardown.call(a,o)===false)if(a.removeEventListener)a.removeEventListener(i,c.data(a,"handle"),false);else a.detachEvent&&a.detachEvent("on"+i,c.data(a,"handle"));e=null;delete f[i]}}}}for(e in f)break;if(!e){if(A=c.data(a,"handle"))A.elem=null;c.removeData(a,
+"events");c.removeData(a,"handle")}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();this.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return v;a.result=v;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,
+b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(i){}if(!a.isPropagationStopped()&&f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){d=a.target;var j;if(!(c.nodeName(d,"a")&&e==="click")&&!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()])){try{if(d[e]){if(j=d["on"+e])d["on"+e]=null;this.triggered=true;d[e]()}}catch(n){}if(j)d["on"+e]=j;this.triggered=false}}},handle:function(a){var b,
+d;a=arguments[0]=c.event.fix(a||z.event);a.currentTarget=this;d=a.type.split(".");a.type=d.shift();b=!d.length&&!a.exclusive;var f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)");d=(c.data(this,"events")||{})[a.type];for(var e in d){var i=d[e];if(b||f.test(i.type)){a.handler=i;a.data=i.data;i=i.apply(this,arguments);if(i!==v){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||r;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=r.documentElement;d=r.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==v)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a,b){c.extend(a,b||{});a.guid+=b.selector+b.live;b.liveProxy=a;c.event.add(this,b.live,na,b)},remove:function(a){if(a.length){var b=
+0,d=new RegExp("(^|\\.)"+a[0]+"(\\.|$)");c.each(c.data(this,"events").live||{},function(){d.test(this.type)&&b++});b<1&&c.event.remove(this,a[0],na)}},special:{}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};
+c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y};var Aa=function(a){for(var b=
+a.relatedTarget;b&&b!==this;)try{b=b.parentNode}catch(d){break}if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}},Ba=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ba:Aa,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ba:Aa)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(a,b,d){if(this.nodeName.toLowerCase()!==
+"form"){c.event.add(this,"click.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="submit"||i==="image")&&c(e).closest("form").length)return ma("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="text"||i==="password")&&c(e).closest("form").length&&f.keyCode===13)return ma("submit",this,arguments)})}else return false},remove:function(a,b){c.event.remove(this,"click.specialSubmit"+(b?"."+b.guid:""));c.event.remove(this,
+"keypress.specialSubmit"+(b?"."+b.guid:""))}};if(!c.support.changeBubbles){var da=/textarea|input|select/i;function Ca(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d}function ea(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Ca(d);if(a.type!=="focusout"||
+d.type!=="radio")c.data(d,"_change_data",e);if(!(f===v||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}}c.event.special.change={filters:{focusout:ea,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return ea.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return ea.call(this,a)},beforeactivate:function(a){a=
+a.target;a.nodeName.toLowerCase()==="input"&&a.type==="radio"&&c.data(a,"_change_data",Ca(a))}},setup:function(a,b,d){for(var f in T)c.event.add(this,f+".specialChange."+d.guid,T[f]);return da.test(this.nodeName)},remove:function(a,b){for(var d in T)c.event.remove(this,d+".specialChange"+(b?"."+b.guid:""),T[d]);return da.test(this.nodeName)}};var T=c.event.special.change.filters}r.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,
+f)}c.event.special[b]={setup:function(){this.addEventListener(a,d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var i in d)this[b](i,f,d[i],e);return this}if(c.isFunction(f)){e=f;f=v}var j=b==="one"?c.proxy(e,function(n){c(this).unbind(n,j);return e.apply(this,arguments)}):e;return d==="unload"&&b!=="one"?this.one(d,f,e):this.each(function(){c.event.add(this,d,j,f)})}});c.fn.extend({unbind:function(a,
+b){if(typeof a==="object"&&!a.preventDefault){for(var d in a)this.unbind(d,a[d]);return this}return this.each(function(){c.event.remove(this,a,b)})},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+
+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e){var i,j=0;if(c.isFunction(f)){e=f;f=v}for(d=(d||"").split(/\s+/);(i=d[j++])!=null;){i=i==="focus"?"focusin":i==="blur"?"focusout":i==="hover"?d.push("mouseleave")&&"mouseenter":i;b==="live"?c(this.context).bind(oa(i,this.selector),{data:f,selector:this.selector,
+live:i},e):c(this.context).unbind(oa(i,this.selector),e?{guid:e.guid+this.selector+i}:null)}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});z.attachEvent&&!z.addEventListener&&z.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});
+(function(){function a(g){for(var h="",k,l=0;g[l];l++){k=g[l];if(k.nodeType===3||k.nodeType===4)h+=k.nodeValue;else if(k.nodeType!==8)h+=a(k.childNodes)}return h}function b(g,h,k,l,q,p){q=0;for(var u=l.length;q<u;q++){var t=l[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===k){y=l[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=k;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}l[q]=y}}}function d(g,h,k,l,q,p){q=0;for(var u=l.length;q<u;q++){var t=l[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===
+k){y=l[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=k;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(o.filter(h,[t]).length>0){y=t;break}}t=t[g]}l[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,i=Object.prototype.toString,j=false,n=true;[0,0].sort(function(){n=false;return 0});var o=function(g,h,k,l){k=k||[];var q=h=h||r;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||
+typeof g!=="string")return k;for(var p=[],u,t,y,R,H=true,M=w(h),I=g;(f.exec(""),u=f.exec(I))!==null;){I=u[3];p.push(u[1]);if(u[2]){R=u[3];break}}if(p.length>1&&s.exec(g))if(p.length===2&&m.relative[p[0]])t=fa(p[0]+p[1],h);else for(t=m.relative[p[0]]?[h]:o(p.shift(),h);p.length;){g=p.shift();if(m.relative[g])g+=p.shift();t=fa(g,t)}else{if(!l&&p.length>1&&h.nodeType===9&&!M&&m.match.ID.test(p[0])&&!m.match.ID.test(p[p.length-1])){u=o.find(p.shift(),h,M);h=u.expr?o.filter(u.expr,u.set)[0]:u.set[0]}if(h){u=
+l?{expr:p.pop(),set:A(l)}:o.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=u.expr?o.filter(u.expr,u.set):u.set;if(p.length>0)y=A(t);else H=false;for(;p.length;){var D=p.pop();u=D;if(m.relative[D])u=p.pop();else D="";if(u==null)u=h;m.relative[D](y,u,M)}}else y=[]}y||(y=t);y||o.error(D||g);if(i.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))k.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&
+y[g].nodeType===1&&k.push(t[g]);else k.push.apply(k,y);else A(y,k);if(R){o(R,q,k,l);o.uniqueSort(k)}return k};o.uniqueSort=function(g){if(C){j=n;g.sort(C);if(j)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};o.matches=function(g,h){return o(g,null,null,h)};o.find=function(g,h,k){var l,q;if(!g)return[];for(var p=0,u=m.order.length;p<u;p++){var t=m.order[p];if(q=m.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");l=m.find[t](q,
+h,k);if(l!=null){g=g.replace(m.match[t],"");break}}}}l||(l=h.getElementsByTagName("*"));return{set:l,expr:g}};o.filter=function(g,h,k,l){for(var q=g,p=[],u=h,t,y,R=h&&h[0]&&w(h[0]);g&&h.length;){for(var H in m.filter)if((t=m.leftMatch[H].exec(g))!=null&&t[2]){var M=m.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-1)!=="\\"){if(u===p)p=[];if(m.preFilter[H])if(t=m.preFilter[H](t,u,k,p,l,R)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=u[U])!=null;U++)if(D){I=M(D,t,U,u);var Da=
+l^!!I;if(k&&I!=null)if(Da)y=true;else u[U]=false;else if(Da){p.push(D);y=true}}if(I!==v){k||(u=p);g=g.replace(m.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)o.error(g);else break;q=g}return u};o.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var m=o.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},relative:{"+":function(g,h){var k=typeof h==="string",l=k&&!/\W/.test(h);k=k&&!l;if(l)h=h.toLowerCase();l=0;for(var q=g.length,
+p;l<q;l++)if(p=g[l]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[l]=k||p&&p.nodeName.toLowerCase()===h?p||false:p===h}k&&o.filter(h,g,true)},">":function(g,h){var k=typeof h==="string";if(k&&!/\W/.test(h)){h=h.toLowerCase();for(var l=0,q=g.length;l<q;l++){var p=g[l];if(p){k=p.parentNode;g[l]=k.nodeName.toLowerCase()===h?k:false}}}else{l=0;for(q=g.length;l<q;l++)if(p=g[l])g[l]=k?p.parentNode:p.parentNode===h;k&&o.filter(h,g,true)}},"":function(g,h,k){var l=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=
+h=h.toLowerCase();q=b}q("parentNode",h,l,g,p,k)},"~":function(g,h,k){var l=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,l,g,p,k)}},find:{ID:function(g,h,k){if(typeof h.getElementById!=="undefined"&&!k)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var k=[];h=h.getElementsByName(g[1]);for(var l=0,q=h.length;l<q;l++)h[l].getAttribute("name")===g[1]&&k.push(h[l]);return k.length===0?null:k}},
+TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,k,l,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var u;(u=h[p])!=null;p++)if(u)if(q^(u.className&&(" "+u.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))k||l.push(u);else if(k)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&
+"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,k,l,q,p){h=g[1].replace(/\\/g,"");if(!p&&m.attrMap[h])g[1]=m.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,k,l,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=o(g[3],null,null,h);else{g=o.filter(g[3],h,k,true^q);k||l.push.apply(l,g);return false}else if(m.match.POS.test(g[0])||m.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);
+return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,k){return!!o(k[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===
+g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,h){return h===0},last:function(g,h,k,l){return h===l.length-1},even:function(g,h){return h%2===
+0},odd:function(g,h){return h%2===1},lt:function(g,h,k){return h<k[3]-0},gt:function(g,h,k){return h>k[3]-0},nth:function(g,h,k){return k[3]-0===h},eq:function(g,h,k){return k[3]-0===h}},filter:{PSEUDO:function(g,h,k,l){var q=h[1],p=m.filters[q];if(p)return p(g,k,h,l);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=h[3];k=0;for(l=h.length;k<l;k++)if(h[k]===g)return false;return true}else o.error("Syntax error, unrecognized expression: "+
+q)},CHILD:function(g,h){var k=h[1],l=g;switch(k){case "only":case "first":for(;l=l.previousSibling;)if(l.nodeType===1)return false;if(k==="first")return true;l=g;case "last":for(;l=l.nextSibling;)if(l.nodeType===1)return false;return true;case "nth":k=h[2];var q=h[3];if(k===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var u=0;for(l=p.firstChild;l;l=l.nextSibling)if(l.nodeType===1)l.nodeIndex=++u;p.sizcache=h}g=g.nodeIndex-q;return k===0?g===0:g%k===0&&g/k>=
+0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var k=h[1];g=m.attrHandle[k]?m.attrHandle[k](g):g[k]!=null?g[k]:g.getAttribute(k);k=g+"";var l=h[2];h=h[4];return g==null?l==="!=":l==="="?k===h:l==="*="?k.indexOf(h)>=0:l==="~="?(" "+k+" ").indexOf(h)>=0:!h?k&&g!==false:l==="!="?k!==h:l==="^="?
+k.indexOf(h)===0:l==="$="?k.substr(k.length-h.length)===h:l==="|="?k===h||k.substr(0,h.length+1)===h+"-":false},POS:function(g,h,k,l){var q=m.setFilters[h[2]];if(q)return q(g,k,h,l)}}},s=m.match.POS;for(var x in m.match){m.match[x]=new RegExp(m.match[x].source+/(?![^\[]*\])(?![^\(]*\))/.source);m.leftMatch[x]=new RegExp(/(^(?:.|\r|\n)*?)/.source+m.match[x].source.replace(/\\(\d+)/g,function(g,h){return"\\"+(h-0+1)}))}var A=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};
+try{Array.prototype.slice.call(r.documentElement.childNodes,0)}catch(B){A=function(g,h){h=h||[];if(i.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var k=0,l=g.length;k<l;k++)h.push(g[k]);else for(k=0;g[k];k++)h.push(g[k]);return h}}var C;if(r.documentElement.compareDocumentPosition)C=function(g,h){if(!g.compareDocumentPosition||!h.compareDocumentPosition){if(g==h)j=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===
+h?0:1;if(g===0)j=true;return g};else if("sourceIndex"in r.documentElement)C=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)j=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)j=true;return g};else if(r.createRange)C=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)j=true;return g.ownerDocument?-1:1}var k=g.ownerDocument.createRange(),l=h.ownerDocument.createRange();k.setStart(g,0);k.setEnd(g,0);l.setStart(h,0);l.setEnd(h,0);g=k.compareBoundaryPoints(Range.START_TO_END,
+l);if(g===0)j=true;return g};(function(){var g=r.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var k=r.documentElement;k.insertBefore(g,k.firstChild);if(r.getElementById(h)){m.find.ID=function(l,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(l[1]))?q.id===l[1]||typeof q.getAttributeNode!=="undefined"&&q.getAttributeNode("id").nodeValue===l[1]?[q]:v:[]};m.filter.ID=function(l,q){var p=typeof l.getAttributeNode!=="undefined"&&l.getAttributeNode("id");
+return l.nodeType===1&&p&&p.nodeValue===q}}k.removeChild(g);k=g=null})();(function(){var g=r.createElement("div");g.appendChild(r.createComment(""));if(g.getElementsByTagName("*").length>0)m.find.TAG=function(h,k){k=k.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var l=0;k[l];l++)k[l].nodeType===1&&h.push(k[l]);k=h}return k};g.innerHTML="<a href='#'></a>";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")m.attrHandle.href=function(h){return h.getAttribute("href",
+2)};g=null})();r.querySelectorAll&&function(){var g=o,h=r.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){o=function(l,q,p,u){q=q||r;if(!u&&q.nodeType===9&&!w(q))try{return A(q.querySelectorAll(l),p)}catch(t){}return g(l,q,p,u)};for(var k in g)o[k]=g[k];h=null}}();(function(){var g=r.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===
+0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){m.order.splice(1,0,"CLASS");m.find.CLASS=function(h,k,l){if(typeof k.getElementsByClassName!=="undefined"&&!l)return k.getElementsByClassName(h[1])};g=null}}})();var E=r.compareDocumentPosition?function(g,h){return g.compareDocumentPosition(h)&16}:function(g,h){return g!==h&&(g.contains?g.contains(h):true)},w=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},fa=function(g,h){var k=[],
+l="",q;for(h=h.nodeType?[h]:h;q=m.match.PSEUDO.exec(g);){l+=q[0];g=g.replace(m.match.PSEUDO,"")}g=m.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)o(g,h[q],k);return o.filter(l,k)};c.find=o;c.expr=o.selectors;c.expr[":"]=c.expr.filters;c.unique=o.uniqueSort;c.getText=a;c.isXMLDoc=w;c.contains=E})();var bb=/Until$/,cb=/^(?:parents|prevUntil|prevAll)/,db=/,/;Q=Array.prototype.slice;var Ea=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,i){return!!b.call(e,i,e)===d});else if(b.nodeType)return c.grep(a,
+function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Qa.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;c.find(a,this[f],b);if(f>0)for(var i=d;i<b.length;i++)for(var j=0;j<d;j++)if(b[j]===b[i]){b.splice(i--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=
+0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ea(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ea(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,i={},j;if(f&&a.length){e=0;for(var n=a.length;e<n;e++){j=a[e];i[j]||(i[j]=c.expr.match.POS.test(j)?c(j,b||this.context):j)}for(;f&&f.ownerDocument&&f!==b;){for(j in i){e=i[j];if(e.jquery?e.index(f)>
+-1:c(f).is(e)){d.push({selector:j,elem:f});delete i[j]}}f=f.parentNode}}return d}var o=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(m,s){for(;s&&s.ownerDocument&&s!==b;){if(o?o.index(s)>-1:c(s).is(a))return s;s=s.parentNode}return null})},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),
+a);return this.pushStack(pa(a[0])||pa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},
+nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);bb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):
+e;if((this.length>1||db.test(f))&&cb.test(a))e=e.reverse();return this.pushStack(e,a,Q.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===v||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==
+b&&d.push(a);return d}});var Fa=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ga=/(<([\w:]+)[^>]*?)\/>/g,eb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,Ha=/<([\w:]+)/,fb=/<tbody/i,gb=/<|&\w+;/,sa=/checked\s*(?:[^=]|=\s*.checked.)/i,Ia=function(a,b,d){return eb.test(d)?a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],
+col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==v)return this.empty().append((this[0]&&this[0].ownerDocument||r).createTextNode(a));return c.getText(this)},
+wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?
+d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,
+false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&
+!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Fa,"").replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){qa(this,b);qa(this.find("*"),b.find("*"))}return b},html:function(a){if(a===v)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Fa,""):null;else if(typeof a==="string"&&!/<script/i.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(Ha.exec(a)||
+["",""])[1].toLowerCase()]){a=a.replace(Ga,Ia);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var i=c(this),j=i.html();i.empty().append(function(){return a.call(this,e,j)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,
+b,f))});else a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(s){return c.nodeName(s,"table")?s.getElementsByTagName("tbody")[0]||s.appendChild(s.ownerDocument.createElement("tbody")):s}var e,i,j=a[0],n=[];if(!c.support.checkClone&&arguments.length===3&&typeof j===
+"string"&&sa.test(j))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(j))return this.each(function(s){var x=c(this);a[0]=j.call(this,s,b?x.html():v);x.domManip(a,b,d)});if(this[0]){e=a[0]&&a[0].parentNode&&a[0].parentNode.nodeType===11?{fragment:a[0].parentNode}:ra(a,this,n);if(i=e.fragment.firstChild){b=b&&c.nodeName(i,"tr");for(var o=0,m=this.length;o<m;o++)d.call(b?f(this[o],i):this[o],e.cacheable||this.length>1||o>0?e.fragment.cloneNode(true):e.fragment)}n&&c.each(n,
+Ma)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);for(var e=0,i=d.length;e<i;e++){var j=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),j);f=f.concat(j)}return this.pushStack(f,a,d.selector)}});c.each({remove:function(a,b){if(!a||c.filter(a,[this]).length){if(!b&&this.nodeType===1){c.cleanData(this.getElementsByTagName("*"));c.cleanData([this])}this.parentNode&&
+this.parentNode.removeChild(this)}},empty:function(){for(this.nodeType===1&&c.cleanData(this.getElementsByTagName("*"));this.firstChild;)this.removeChild(this.firstChild)}},function(a,b){c.fn[a]=function(){return this.each(b,arguments)}});c.extend({clean:function(a,b,d,f){b=b||r;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||r;var e=[];c.each(a,function(i,j){if(typeof j==="number")j+="";if(j){if(typeof j==="string"&&!gb.test(j))j=b.createTextNode(j);else if(typeof j===
+"string"){j=j.replace(Ga,Ia);var n=(Ha.exec(j)||["",""])[1].toLowerCase(),o=F[n]||F._default,m=o[0];i=b.createElement("div");for(i.innerHTML=o[1]+j+o[2];m--;)i=i.lastChild;if(!c.support.tbody){m=fb.test(j);n=n==="table"&&!m?i.firstChild&&i.firstChild.childNodes:o[1]==="<table>"&&!m?i.childNodes:[];for(o=n.length-1;o>=0;--o)c.nodeName(n[o],"tbody")&&!n[o].childNodes.length&&n[o].parentNode.removeChild(n[o])}!c.support.leadingWhitespace&&V.test(j)&&i.insertBefore(b.createTextNode(V.exec(j)[0]),i.firstChild);
+j=c.makeArray(i.childNodes)}if(j.nodeType)e.push(j);else e=c.merge(e,j)}});if(d)for(a=0;e[a];a++)if(f&&c.nodeName(e[a],"script")&&(!e[a].type||e[a].type.toLowerCase()==="text/javascript"))f.push(e[a].parentNode?e[a].parentNode.removeChild(e[a]):e[a]);else{e[a].nodeType===1&&e.splice.apply(e,[a+1,0].concat(c.makeArray(e[a].getElementsByTagName("script"))));d.appendChild(e[a])}return e},cleanData:function(a){for(var b=0,d;(d=a[b])!=null;b++){c.event.remove(d);c.removeData(d)}}});var hb=/z-?index|font-?weight|opacity|zoom|line-?height/i,
+Ja=/alpha\([^)]*\)/,Ka=/opacity=([^)]*)/,ga=/float/i,ha=/-([a-z])/ig,ib=/([A-Z])/g,jb=/^-?\d+(?:px)?$/i,kb=/^-?\d/,lb={position:"absolute",visibility:"hidden",display:"block"},mb=["Left","Right"],nb=["Top","Bottom"],ob=r.defaultView&&r.defaultView.getComputedStyle,La=c.support.cssFloat?"cssFloat":"styleFloat",ia=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===v)return c.curCSS(d,f);if(typeof e==="number"&&!hb.test(f))e+="px";c.style(d,f,e)})};
+c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return v;if((b==="width"||b==="height")&&parseFloat(d)<0)d=v;var f=a.style||a,e=d!==v;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=Ja.test(a)?a.replace(Ja,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Ka.exec(f.filter)[1])/100+"":""}if(ga.test(b))b=La;b=b.replace(ha,ia);if(e)f[b]=d;return f[b]},css:function(a,
+b,d,f){if(b==="width"||b==="height"){var e,i=b==="width"?mb:nb;function j(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(i,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,"border"+this+"Width",true))||0})}a.offsetWidth!==0?j():c.swap(a,lb,j);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&
+a.currentStyle){f=Ka.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ga.test(b))b=La;if(!d&&e&&e[b])f=e[b];else if(ob){if(ga.test(b))b="float";b=b.replace(ib,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ha,ia);f=a.currentStyle[b]||a.currentStyle[d];if(!jb.test(f)&&kb.test(f)){b=e.left;var i=a.runtimeStyle.left;a.runtimeStyle.left=
+a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=i}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var pb=
+J(),qb=/<script(.|\s)*?\/script>/gi,rb=/select|textarea/i,sb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ja=/\?/,tb=/(\?|&)_=.*?(&|$)/,ub=/^(\w+:)?\/\/([^\/?#]+)/,vb=/%20/g;c.fn.extend({_load:c.fn.load,load:function(a,b,d){if(typeof a!=="string")return this._load(a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=
+c.param(b,c.ajaxSettings.traditional);f="POST"}var i=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(j,n){if(n==="success"||n==="notmodified")i.html(e?c("<div />").append(j.responseText.replace(qb,"")).find(e):j.responseText);d&&i.each(d,[j.responseText,n,j])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&
+(this.checked||rb.test(this.nodeName)||sb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,
+b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:z.XMLHttpRequest&&(z.location.protocol!=="file:"||!z.ActiveXObject)?function(){return new z.XMLHttpRequest}:
+function(){try{return new z.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&e.success.call(o,n,j,w);e.global&&f("ajaxSuccess",[w,e])}function d(){e.complete&&e.complete.call(o,w,j);e.global&&f("ajaxComplete",[w,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}
+function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),i,j,n,o=a&&a.context||e,m=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(m==="GET")N.test(e.url)||(e.url+=(ja.test(e.url)?"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||
+N.test(e.url))){i=e.jsonpCallback||"jsonp"+pb++;if(e.data)e.data=(e.data+"").replace(N,"="+i+"$1");e.url=e.url.replace(N,"="+i+"$1");e.dataType="script";z[i]=z[i]||function(q){n=q;b();d();z[i]=v;try{delete z[i]}catch(p){}A&&A.removeChild(B)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===false&&m==="GET"){var s=J(),x=e.url.replace(tb,"$1_="+s+"$2");e.url=x+(x===e.url?(ja.test(e.url)?"&":"?")+"_="+s:"")}if(e.data&&m==="GET")e.url+=(ja.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&
+c.event.trigger("ajaxStart");s=(s=ub.exec(e.url))&&(s[1]&&s[1]!==location.protocol||s[2]!==location.host);if(e.dataType==="script"&&m==="GET"&&s){var A=r.getElementsByTagName("head")[0]||r.documentElement,B=r.createElement("script");B.src=e.url;if(e.scriptCharset)B.charset=e.scriptCharset;if(!i){var C=false;B.onload=B.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;b();d();B.onload=B.onreadystatechange=null;A&&B.parentNode&&
+A.removeChild(B)}}}A.insertBefore(B,A.firstChild);return v}var E=false,w=e.xhr();if(w){e.username?w.open(m,e.url,e.async,e.username,e.password):w.open(m,e.url,e.async);try{if(e.data||a&&a.contentType)w.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[e.url]);c.etag[e.url]&&w.setRequestHeader("If-None-Match",c.etag[e.url])}s||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",
+e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(fa){}if(e.beforeSend&&e.beforeSend.call(o,w,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");w.abort();return false}e.global&&f("ajaxSend",[w,e]);var g=w.onreadystatechange=function(q){if(!w||w.readyState===0||q==="abort"){E||d();E=true;if(w)w.onreadystatechange=c.noop}else if(!E&&w&&(w.readyState===4||q==="timeout")){E=true;w.onreadystatechange=c.noop;j=q==="timeout"?"timeout":!c.httpSuccess(w)?
+"error":e.ifModified&&c.httpNotModified(w,e.url)?"notmodified":"success";var p;if(j==="success")try{n=c.httpData(w,e.dataType,e)}catch(u){j="parsererror";p=u}if(j==="success"||j==="notmodified")i||b();else c.handleError(e,w,j,p);d();q==="timeout"&&w.abort();if(e.async)w=null}};try{var h=w.abort;w.abort=function(){w&&h.call(w);g("abort")}}catch(k){}e.async&&e.timeout>0&&setTimeout(function(){w&&!E&&g("timeout")},e.timeout);try{w.send(m==="POST"||m==="PUT"||m==="DELETE"?e.data:null)}catch(l){c.handleError(e,
+w,null,l);d()}e.async||g();return w}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=
+f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(j,n){if(c.isArray(n))c.each(n,
+function(o,m){b?f(j,m):d(j+"["+(typeof m==="object"||c.isArray(m)?o:"")+"]",m)});else!b&&n!=null&&typeof n==="object"?c.each(n,function(o,m){d(j+"["+o+"]",m)}):f(j,n)}function f(j,n){n=c.isFunction(n)?n():n;e[e.length]=encodeURIComponent(j)+"="+encodeURIComponent(n)}var e=[];if(b===v)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var i in a)d(i,a[i]);return e.join("&").replace(vb,"+")}});var ka={},wb=/toggle|show|hide/,xb=/^([+-]=)?([\d+-.]+)(.*)$/,
+W,ta=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(ka[d])f=ka[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();
+ka[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&
+c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var i=c.extend({},e),j,n=this.nodeType===1&&c(this).is(":hidden"),
+o=this;for(j in a){var m=j.replace(ha,ia);if(j!==m){a[m]=a[j];delete a[j];j=m}if(a[j]==="hide"&&n||a[j]==="show"&&!n)return i.complete.call(this);if((j==="height"||j==="width")&&this.style){i.display=c.css(this,"display");i.overflow=this.style.overflow}if(c.isArray(a[j])){(i.specialEasing=i.specialEasing||{})[j]=a[j][1];a[j]=a[j][0]}}if(i.overflow!=null)this.style.overflow="hidden";i.curAnim=c.extend({},a);c.each(a,function(s,x){var A=new c.fx(o,i,s);if(wb.test(x))A[x==="toggle"?n?"show":"hide":x](a);
+else{var B=xb.exec(x),C=A.cur(true)||0;if(B){x=parseFloat(B[2]);var E=B[3]||"px";if(E!=="px"){o.style[s]=(x||1)+E;C=(x||1)/A.cur(true)*C;o.style[s]=C+E}if(B[1])x=(B[1]==="-="?-1:1)*x+C;A.custom(C,x,E)}else A.custom(C,x,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",
+1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration==="number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,
+b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==
+null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(i){return e.step(i)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop===
+"width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=
+this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=
+c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=
+null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in r.documentElement?function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),
+f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(a)return this.each(function(s){c.offset.setOffset(this,a,s)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=
+b,e=b.ownerDocument,i,j=e.documentElement,n=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var o=b.offsetTop,m=b.offsetLeft;(b=b.parentNode)&&b!==n&&b!==j;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;i=e?e.getComputedStyle(b,null):b.currentStyle;o-=b.scrollTop;m-=b.scrollLeft;if(b===d){o+=b.offsetTop;m+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){o+=parseFloat(i.borderTopWidth)||
+0;m+=parseFloat(i.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&i.overflow!=="visible"){o+=parseFloat(i.borderTopWidth)||0;m+=parseFloat(i.borderLeftWidth)||0}f=i}if(f.position==="relative"||f.position==="static"){o+=n.offsetTop;m+=n.offsetLeft}if(c.offset.supportsFixedPosition&&f.position==="fixed"){o+=Math.max(j.scrollTop,n.scrollTop);m+=Math.max(j.scrollLeft,n.scrollLeft)}return{top:o,left:m}};c.offset={initialize:function(){var a=r.body,b=r.createElement("div"),
+d,f,e,i=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);
+d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i;a.removeChild(b);c.offset.initialize=c.noop},
+bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),i=parseInt(c.curCSS(a,"top",true),10)||0,j=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,d,e);d={top:b.top-e.top+i,left:b.left-
+e.left+j};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=
+this.offsetParent||r.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],i;if(!e)return null;if(f!==v)return this.each(function(){if(i=ua(this))i.scrollTo(!a?f:c(i).scrollLeft(),a?f:c(i).scrollTop());else this[d]=f});else return(i=ua(e))?"pageXOffset"in i?i[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&i.document.documentElement[d]||i.document.body[d]:e[d]}});
+c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(i){var j=c(this);j[d](f.call(this,i,j[d]()))});return"scrollTo"in e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||
+e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===v?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});z.jQuery=z.$=c})(window);
diff --git a/doc/config/scripts/narrow.js b/doc/config/scripts/narrow.js
new file mode 100644
index 000000000..a5e8b97d9
--- /dev/null
+++ b/doc/config/scripts/narrow.js
@@ -0,0 +1,133 @@
+/* This function generates menus and search box in narrow/slim fit mode */
+var narrowInit = function() {
+ /* 1: Create search form */
+ var narrowSearch = $('<div id="narrowsearch"></div>');
+ var searchform = $("#qtdocsearch");
+ narrowSearch.append(searchform);
+ $("#qtdocheader .content .qtref").after(narrowSearch);
+
+ /* 2: Create dropdowns */
+ var narrowmenu = $('<ul id="narrowmenu" class="sf-menu"></ul>');
+
+ /* Lookup */
+ var lookuptext = $("#lookup h2").attr("title");
+ $("#lookup ul").removeAttr("id");
+ $("#lookup ul li").removeAttr("class");
+ $("#lookup ul li").removeAttr("style");
+ var lookupul = $("#lookup ul");
+ var lookuplist = $('<li></li>');
+ var lookuplink = $('<a href="#"></a>');
+ lookuplink.append(lookuptext);
+ lookuplist.append(lookuplink);
+ lookuplist.append(lookupul);
+ narrowmenu.append(lookuplist);
+
+ /* Topics */
+ var topicstext = $("#topics h2").attr("title");
+ $("#topics ul").removeAttr("id");
+ $("#topics ul li").removeAttr("class");
+ $("#topics ul li").removeAttr("style");
+ var topicsul = $("#topics ul");
+ var topicslist = $('<li></li>');
+ var topicslink = $('<a href="#"></a>');
+ topicslink.append(topicstext);
+ topicslist.append(topicslink);
+ topicslist.append(topicsul);
+ narrowmenu.append(topicslist);
+
+ /* Examples */
+ var examplestext = $("#examples h2").attr("title");
+ $("#examples ul").removeAttr("id");
+ $("#examples ul li").removeAttr("class");
+ $("#examples ul li").removeAttr("style");
+ var examplesul = $("#examples ul");
+ var exampleslist = $('<li></li>');
+ var exampleslink = $('<a href="#"></a>');
+ exampleslink.append(examplestext);
+ exampleslist.append(exampleslink);
+ exampleslist.append(examplesul);
+ narrowmenu.append(exampleslist);
+
+ $("#shortCut").after(narrowmenu);
+ $('ul#narrowmenu').superfish({
+ delay: 100,
+ autoArrows: false,
+ disableHI: true
+ });
+}
+
+/* Executes on doc ready */
+$(document).ready(function(){
+ /* check if body has the narrow class */
+ if ($('body').hasClass('narrow')) {
+ /* run narrowInit */
+ narrowInit();
+ }
+
+ /* messure window width and add class if it is smaller than 600 px */
+ if($(window).width()<600) {
+ $('body').addClass('narrow');
+ /* if the search box contains */
+ if ($("#narrowsearch").length == 0) {
+ /* run narrowInit */
+ narrowInit();
+ }
+ }
+ else { /* if the window is wider than 600 px, narrow is removed */
+ $('body').removeClass('narrow');
+ if ($("#narrowsearch").length == 0) {
+ }
+ }
+});
+/* binding resize event to this funciton */
+$(window).bind('resize', function () {
+ /* if the window is wider than 600 px, narrow class is added */
+ if($(window).width()<600) {
+ $('body').addClass('narrow');
+ if ($("#narrowsearch").length == 0) {
+ narrowInit();
+ }
+ }
+ else {
+ /* else we remove the narrow class */
+ $('body').removeClass('narrow');
+ }
+});
+
+ $('#narrowsearch').keyup(function () {
+ /* extract the search box content */
+ var searchString = $('#narrowsearch').val();
+ /* if the string is less than three characters */
+ if ((searchString == null) || (searchString.length < 3)) {
+ /* remove classes and elements*/
+ $('#narrowsearch').removeClass('loading');
+ $('.searching').remove();
+ /* run CheckEmptyAndLoadList */
+ CheckEmptyAndLoadList();
+
+ $('.report').remove();
+ return;
+ }
+ /* if timer checks out */
+ if (this.timer) clearTimeout(this.timer);
+ this.timer = setTimeout(function () {
+ /* add loading image by adding loading class */
+ $('#narrowsearch').addClass('loading');
+ $('.searching').remove();
+
+ /* run the actual search */
+ $.ajax({
+ contentType: "application/x-www-form-urlencoded",
+ url: 'http://' + location.host + '/nokiasearch/GetDataServlet',
+ data: 'searchString='+searchString,
+ dataType:'xml',
+ type: 'post',
+ success: function (response, textStatus) {
+ /* on success remove loading img */
+ $('.searching').remove();
+ $('#narrowsearch').removeClass('loading');
+ processNokiaData(response);
+ }
+ });
+ }, 500); /* timer set to 500 ms */
+ }); \ No newline at end of file
diff --git a/doc/config/scripts/superfish.js b/doc/config/scripts/superfish.js
new file mode 100644
index 000000000..c6a9c7de0
--- /dev/null
+++ b/doc/config/scripts/superfish.js
@@ -0,0 +1,121 @@
+
+/*
+ * Superfish v1.4.8 - jQuery menu widget
+ * Copyright (c) 2008 Joel Birch
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt
+ */
+
+;(function($){
+ $.fn.superfish = function(op){
+
+ var sf = $.fn.superfish,
+ c = sf.c,
+ $arrow = $(['<span class="',c.arrowClass,'"> &#187;</span>'].join('')),
+ over = function(){
+ var $$ = $(this), menu = getMenu($$);
+ clearTimeout(menu.sfTimer);
+ $$.showSuperfishUl().siblings().hideSuperfishUl();
+ },
+ out = function(){
+ var $$ = $(this), menu = getMenu($$), o = sf.op;
+ clearTimeout(menu.sfTimer);
+ menu.sfTimer=setTimeout(function(){
+ o.retainPath=($.inArray($$[0],o.$path)>-1);
+ $$.hideSuperfishUl();
+ if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);}
+ },o.delay);
+ },
+ getMenu = function($menu){
+ var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0];
+ sf.op = sf.o[menu.serial];
+ return menu;
+ },
+ addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); };
+
+ return this.each(function() {
+ var s = this.serial = sf.o.length;
+ var o = $.extend({},sf.defaults,op);
+ o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){
+ $(this).addClass([o.hoverClass,c.bcClass].join(' '))
+ .filter('li:has(ul)').removeClass(o.pathClass);
+ });
+ sf.o[s] = sf.op = o;
+
+ $('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() {
+ if (o.autoArrows) addArrow( $('>a:first-child',this) );
+ })
+ .not('.'+c.bcClass)
+ .hideSuperfishUl();
+
+ var $a = $('a',this);
+ $a.each(function(i){
+ var $li = $a.eq(i).parents('li');
+ $a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);});
+ });
+ o.onInit.call(this);
+
+ }).each(function() {
+ var menuClasses = [c.menuClass];
+ if (sf.op.dropShadows && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
+ $(this).addClass(menuClasses.join(' '));
+ });
+ };
+
+ var sf = $.fn.superfish;
+ sf.o = [];
+ sf.op = {};
+ sf.IE7fix = function(){
+ var o = sf.op;
+ if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined)
+ this.toggleClass(sf.c.shadowClass+'-off');
+ };
+ sf.c = {
+ bcClass : 'sf-breadcrumb',
+ menuClass : 'sf-js-enabled',
+ anchorClass : 'sf-with-ul',
+ arrowClass : 'sf-sub-indicator',
+ shadowClass : 'sf-shadow'
+ };
+ sf.defaults = {
+ hoverClass : 'sfHover',
+ pathClass : 'overideThisToUse',
+ pathLevels : 1,
+ delay : 800,
+ animation : {opacity:'show'},
+ speed : 'normal',
+ autoArrows : true,
+ dropShadows : true,
+ disableHI : false, // true disables hoverIntent detection
+ onInit : function(){}, // callback functions
+ onBeforeShow: function(){},
+ onShow : function(){},
+ onHide : function(){}
+ };
+ $.fn.extend({
+ hideSuperfishUl : function(){
+ var o = sf.op,
+ not = (o.retainPath===true) ? o.$path : '';
+ o.retainPath = false;
+ var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass)
+ .find('>ul').hide().css('visibility','hidden');
+ o.onHide.call($ul);
+ return this;
+ },
+ showSuperfishUl : function(){
+ var o = sf.op,
+ sh = sf.c.shadowClass+'-off',
+ $ul = this.addClass(o.hoverClass)
+ .find('>ul:hidden').css('visibility','visible');
+ sf.IE7fix.call($ul);
+ o.onBeforeShow.call($ul);
+ $ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); });
+ return this;
+ }
+ });
+
+})(jQuery);
diff --git a/doc/config/style/narrow.css b/doc/config/style/narrow.css
new file mode 100644
index 000000000..de5b0a09f
--- /dev/null
+++ b/doc/config/style/narrow.css
@@ -0,0 +1,270 @@
+ /* start narrow mode */
+
+ body.narrow
+ {
+ background-image: none;
+ }
+
+ .narrow a {
+ color: #44a51c;
+ }
+
+ .narrow .header, .narrow .header .content, .narrow .footer, .narrow .wrapper {
+ margin: 0 7px;
+ min-width: 300px;
+ }
+
+ .narrow .footer {
+ margin: 0px;
+ }
+
+ .creator .header, .creator .header .content, .creator .footer, .creator .wrapper {
+ margin: 0px;
+ min-width: 300px;
+ }
+ .narrow .header
+ {
+ width: 100%;
+ margin: 0;
+ height: auto;
+ background: #fff url(../images/header_bg.png) repeat-x 0 100%;
+ padding: 10px 0 5px 0;
+ overflow: visible;
+ }
+
+ .narrow .header .content
+ {
+ }
+
+ .narrow .header #nav-logo
+ {
+ display: none;
+ }
+
+ .narrow .header .qtref
+ {
+ width: auto;
+ height: auto;
+ color: #363534;
+ position: static;
+ float: left;
+ margin-left: 25px;
+ font: bold 18px/1 Arial;
+ }
+
+ .narrow .header .qtref a
+ {
+ color: #00732F;
+ }
+
+ .narrow .header .qtref span
+ {
+ background-image: none;
+ text-indent: 0;
+ }
+
+ .narrow .header #nav-topright
+ {
+ display: none;
+ }
+
+ .narrow .header #shortCut
+ {
+ clear: both;
+ font-weight: normal;
+ position: static;
+ float: left;
+ margin: 15px 0 0 25px;
+ overflow: hidden;
+ padding: 0;
+ height: auto;
+ }
+
+ .narrow .header #shortCut ul
+ {
+ float: none;
+ margin: 0;
+ width: auto;
+ font-size: 11px;
+ }
+
+ .narrow .header #shortCut ul li
+ {
+ background-image: none;
+ }
+
+ .narrow .header #shortCut ul .shortCut-topleft-active,
+ .narrow .header #shortCut ul .shortCut-topleft-inactive
+ {
+ background-image: none;
+ height: auto;
+ padding: 0;
+ width: auto;
+ }
+ .narrow .header #shortCut ul li a
+ {
+ color: #00732F;
+ }
+
+ .narrow .wrapper .hd
+ {
+ background: url(../images/bg_ul_blank.png) no-repeat 0 0;
+ }
+
+ .narrow .wrapper .bd
+ {
+ background: url(../images/bg_l_blank.png) repeat-y 0 0;
+ }
+
+ .narrow .wrapper .ft
+ {
+ background: url(../images/bg_ll_blank.png) no-repeat 0 0;
+ }
+
+ .narrow .sidebar
+ {
+ display: none;
+ }
+
+ .narrow .wrap
+ {
+ margin: 0 5px 0 5px;
+ }
+
+ .creator .wrap
+ {
+ margin: 0px;
+ background:#FFFFFF;
+ }
+ .narrow .wrap .toolbar
+ {
+ border-bottom: none;
+ }
+
+ .narrow .wrap .content
+ {
+ padding-top: 15px;
+ }
+ .creator .wrap .content
+ {
+ padding-top: 10px;
+ }
+ .creator .wrap .content .guide
+ {
+ padding-top: 15px;
+ }
+ .narrow .wrap .feedback
+ {
+ display: none;
+ }
+
+ .narrow .wrap .breadcrumb ul li {
+ font-weight: normal;
+ }
+
+ .narrow .wrap .breadcrumb ul li a {
+ color: #44a51c;
+ }
+
+ .narrow .wrap .breadcrumb ul li.last a {
+ color: #363534;
+ }
+
+ #narrowsearch {
+ display: none;
+ }
+
+ .narrow #narrowsearch {
+ display: block;
+ float: right;
+ margin-right: 25px;
+ _position: relative;
+ }
+
+ .narrow #narrowsearch fieldset {
+ _position: absolute;
+ _margin-top: -1px;
+ }
+
+ .narrow #narrowsearch {
+ background: url("http://doc.qt.nokia.com/prototype/html/images/sprites-combined.png") no-repeat scroll -6px -348px transparent;
+ height: 21px;
+ padding: 2px 0 0 5px;
+ width: 167px;
+ }
+
+ .narrow #narrowsearch input {
+ border: none;
+ font: 13px/1.2 Verdana;
+ height: 19px;
+ outline: none;
+ padding: 0;
+ width: 158px;
+ *border: 1px solid #fff;
+ *height: 17px;
+ _height: 18px;
+ /* to be fixed */
+ display: none;
+ /* to be fixed */
+ }
+
+ .narrow .indexbox .indexIcon {
+ display: none;
+ }
+
+ .narrow .indexboxcont .section {
+ width: 64%;
+ padding-left: 0;
+ }
+
+ .narrow .indexboxcont .sectionlist {
+ width: 32.5%;
+ }
+
+ #narrowmenu {
+ display: none;
+ float: right;
+ margin: 15px 40px 0 0;
+ font-size: 11px;
+ }
+
+ .narrow #narrowmenu {
+ display: block;
+ }
+
+ #narrowmenu a {
+ line-height: 1.1;
+ background: url(../images/arrow_down.png) no-repeat 100% 50%;
+ white-space: nowrap;
+ padding: 0 16px 0 5px;
+ }
+
+ #narrowmenu li {
+ margin-left: 20px;
+ }
+
+ #narrowmenu li li {
+ margin: 0 0 5px 0;
+ }
+
+ #narrowmenu li li a {
+ padding: 0;
+ background-image: none;
+ }
+
+ #narrowmenu li,
+ #narrowmenu li ul {
+ background-color: #fff;
+ margin-top:-1px;
+ }
+
+ #narrowmenu li ul {
+ width: auto;
+ padding: 5px;
+ }
+
+ .sf-menu li:hover ul, .sf-menu li.sfHover ul {
+ top: 1.2em;
+ }
+
+ /* end narrow mode */
diff --git a/doc/config/style/offline.css b/doc/config/style/offline.css
new file mode 100644
index 000000000..c3f90c36a
--- /dev/null
+++ b/doc/config/style/offline.css
@@ -0,0 +1,675 @@
+@media screen
+{
+
+/* basic elements */
+ html
+ {
+ color: #000000;
+ background: #FFFFFF;
+ }
+ table
+ {
+ border-collapse: collapse;
+ border-spacing: 0;
+ }
+ fieldset, img
+ {
+ border: 0;
+ max-width:100%;
+ }
+ address, caption, cite, code, dfn, em, strong, th, var, optgroup
+ {
+ font-style: inherit;
+ font-weight: inherit;
+ }
+ del, ins
+ {
+ text-decoration: none;
+ }
+ ol li
+ {
+ list-style: decimal;
+ }
+ ul li
+ {
+ list-style: none;
+ }
+ caption, th
+ {
+ text-align: left;
+ }
+ h1, h2, h3, h4, h5, h6
+ {
+ font-size: 100%;
+ }
+ q:before, q:after
+ {
+ content: '';
+ }
+ abbr, acronym
+ {
+ border: 0;
+ font-variant: normal;
+ }
+ sup, sub
+ {
+ vertical-align: baseline;
+ }
+ tt, .qmlreadonly span, .qmldefault span
+ {
+ word-spacing:0.5em;
+ }
+ legend
+ {
+ color: #000000;
+ }
+ strong
+ {
+ font-weight: bold;
+ }
+ em
+ {
+ font-style: italic;
+ }
+
+ body
+ {
+ margin-left: 0.5em;
+ margin-right: 0.5em;
+ font-family: sans-serif;
+ line-height: normal
+ }
+ a
+ {
+ color: #00732F;
+ text-decoration: none;
+ }
+ hr
+ {
+ background-color: #E6E6E6;
+ border: 1px solid #E6E6E6;
+ height: 1px;
+ width: 100%;
+ text-align: left;
+ margin: 1.5em 0 1.5em 0;
+ }
+
+ pre
+ {
+ border: 1px solid #DDDDDD;
+ -moz-border-radius: 0.7em 0.7em 0.7em 0.7em;
+ -webkit-border-radius: 0.7em 0.7em 0.7em 0.7em;
+ border-radius: 0.7em 0.7em 0.7em 0.7em;
+ margin: 0 1.5em 1em 1em;
+ padding: 1em 1em 1em 1em;
+ overflow-x: auto;
+ }
+ table, pre
+ {
+ -moz-border-radius: 0.7em 0.7em 0.7em 0.7em;
+ -webkit-border-radius: 0.7em 0.7em 0.7em 0.7em;
+ border-radius: 0.7em 0.7em 0.7em 0.7em;
+ background-color: #F6F6F6;
+ border: 1px solid #E6E6E6;
+ border-collapse: separate;
+ margin-bottom: 2.5em;
+ }
+ pre {
+ font-size: 90%;
+ display: block;
+ overflow:hidden;
+ }
+ thead
+ {
+ margin-top: 0.5em;
+ font-weight: bold
+ }
+ th
+ {
+ padding: 0.5em 1.5em 0.5em 1em;
+ background-color: #E1E1E1;
+ border-left: 1px solid #E6E6E6;
+ }
+ td
+ {
+ padding: 0.25em 1.5em 0.25em 1em;
+ }
+
+ td.rightAlign
+ {
+ padding: 0.25em 0.5em 0.25em 1em;
+ }
+ table tr.odd
+ {
+ border-left: 1px solid #E6E6E6;
+ background-color: #F6F6F6;
+ color: #66666E;
+ }
+ table tr.even
+ {
+ border-left: 1px solid #E6E6E6;
+ background-color: #ffffff;
+ color: #66666E;
+ }
+
+ div.float-left
+ {
+ float: left; margin-right: 2em
+ }
+ div.float-right
+ {
+ float: right; margin-left: 2em
+ }
+
+ span.comment
+ {
+ color: #008B00;
+ }
+ span.string, span.char
+ {
+ color: #000084;
+ }
+ span.number
+ {
+ color: #a46200;
+ }
+ span.operator
+ {
+ color: #202020;
+ }
+ span.keyword
+ {
+ color: #840000;
+ }
+ span.name
+ {
+ color: black
+ }
+ span.type
+ {
+ font-weight: bold
+ }
+ span.type a:visited
+ {
+ color: #0F5300;
+ }
+ span.preprocessor
+ {
+ color: #404040
+ }
+/* end basic elements */
+
+/* font style elements */
+ .heading
+ {
+ font-weight: bold;
+ font-size: 125%;
+ }
+ .subtitle
+ {
+ font-size: 110%
+ }
+ .small-subtitle
+ {
+ font-size: 100%
+ }
+ .red
+ {
+ color:red;
+ }
+/* end font style elements */
+
+/* global settings*/
+ .header, .footer
+ {
+ display: block;
+ clear: both;
+ overflow: hidden;
+ }
+/* end global settings*/
+
+/* header elements */
+ .header .qtref
+ {
+ color: #00732F;
+ font-weight: bold;
+ font-size: 130%;
+ }
+
+ .header .content
+ {
+ margin-bottom: 0.5em
+ }
+
+ .header .breadcrumb
+ {
+ font-size: 90%;
+ padding: 0.5em 0 0.5em 1em;
+ margin: 0;
+ background-color: #fafafa;
+ height: 1.35em;
+ border-bottom: 1px solid #d1d1d1;
+ }
+
+ .header .breadcrumb ul
+ {
+ margin: 0;
+ padding: 0;
+ }
+
+ .header .content
+ {
+ word-wrap: break-word;
+ }
+
+ .header .breadcrumb ul li
+ {
+ float: left;
+ background: url(../images/breadcrumb.png) no-repeat 0 3px;
+ padding-left: 1.5em;
+ margin-left: 1.5em;
+ }
+
+ .header .breadcrumb ul li.last
+ {
+ font-weight: normal;
+ }
+
+ .header .breadcrumb ul li a
+ {
+ color: #00732F;
+ }
+
+ .header .breadcrumb ul li.first
+ {
+ background-image: none;
+ padding-left: 0;
+ margin-left: 0;
+ }
+
+ .header .content ol li {
+ background: none;
+ margin-bottom: 1.0em;
+ margin-left: 1.2em;
+ padding-left: 0
+ }
+
+ .header .content li
+ {
+ background: url(../images/bullet_sq.png) no-repeat 0 5px;
+ margin-bottom: 1em;
+ padding-left: 1.2em;
+ }
+
+/* end header elements */
+
+/* content elements */
+ .content h1
+ {
+ font-weight: bold;
+ font-size: 130%
+ }
+
+ .content h2
+ {
+ font-weight: bold;
+ font-size: 120%;
+ width: 100%;
+ }
+ .content h3
+ {
+ font-weight: bold;
+ font-size: 110%;
+ width: 100%;
+ }
+ .content table p
+ {
+ margin: 0
+ }
+ .content ul
+ {
+ padding-left: 2.5em;
+ }
+ .content li
+ {
+ padding-top: 0.25em;
+ padding-bottom: 0.25em;
+ }
+ .content ul img {
+ vertical-align: middle;
+ }
+
+ .content a:visited
+ {
+ color: #4c0033;
+ text-decoration: none;
+ }
+
+ .content a:visited:hover
+ {
+ color: #4c0033;
+ text-decoration: underline;
+ }
+
+ a:hover
+ {
+ color: #4c0033;
+ text-decoration: underline;
+ }
+ descr p a
+ {
+ text-decoration: underline;
+ }
+
+ .descr p a:visited
+ {
+ text-decoration: underline;
+ }
+
+ .alphaChar{
+ width:95%;
+ background-color:#F6F6F6;
+ border:1px solid #E6E6E6;
+ -moz-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ font-size:12pt;
+ padding-left:10px;
+ margin-top:10px;
+ margin-bottom:10px;
+ }
+ .flowList{
+ /*vertical-align:top;*/
+ /*margin:20px auto;*/
+
+ column-count:3;
+ -webkit-column-count:3;
+ -moz-column-count:3;
+/*
+ column-width:100%;
+ -webkit-column-width:200px;
+ -col-column-width:200px;
+*/
+ column-gap:41px;
+ -webkit-column-gap:41px;
+ -moz-column-gap:41px;
+
+ column-rule: 1px dashed #ccc;
+ -webkit-column-rule: 1px dashed #ccc;
+ -moz-column-rule: 1px dashed #ccc;
+ }
+
+ .flowList dl{
+ }
+ .flowList dd{
+ /*display:inline-block;*/
+ margin-left:10px;
+ min-width:250px;
+ line-height: 1.5;
+ min-width:100%;
+ min-height:15px;
+ }
+
+ .flowList dd a{
+ }
+
+ .content .flowList p{
+ padding:0px;
+ }
+
+ .content .alignedsummary
+ {
+ margin: 15px;
+ }
+
+
+ .qmltype
+ {
+ text-align: center;
+ font-size: 120%;
+ }
+ .qmlreadonly
+ {
+ padding-left: 5px;
+ float: right;
+ color: #254117;
+ }
+
+ .qmldefault
+ {
+ padding-left: 5px;
+ float: right;
+ color: red;
+ }
+
+ .qmldoc
+ {
+ }
+
+ .generic .alphaChar{
+ margin-top:5px;
+ }
+
+ .generic .odd .alphaChar{
+ background-color: #F6F6F6;
+ }
+
+ .generic .even .alphaChar{
+ background-color: #FFFFFF;
+ }
+
+ .memItemRight{
+ padding: 0.25em 1.5em 0.25em 0;
+ }
+ .highlightedCode
+ {
+ margin: 1.0em;
+ }
+ .annotated td {
+ padding: 0.25em 0.5em 0.25em 0.5em;
+ }
+
+ .toc
+ {
+ font-size: 80%
+ }
+
+ .header .content .toc ul
+ {
+ padding-left: 0px;
+ }
+
+ .content .toc h3 {
+ border-bottom: 0px;
+ margin-top: 0px;
+ }
+
+ .content .toc h3 a:hover {
+ color: #00732F;
+ text-decoration: none;
+ }
+
+ .content .toc .level2
+ {
+ margin-left: 1.5em;
+ }
+
+ .content .toc .level3
+ {
+ margin-left: 3.0em;
+ }
+
+ .content ul li
+ {
+ background: url(../images/bullet_sq.png) no-repeat 0 0.7em;
+ padding-left: 1em
+ }
+
+ .content .toc li
+ {
+ background: url(../images/bullet_dn.png) no-repeat 0 5px;
+ padding-left: 1em
+ }
+
+ .relpage
+ {
+ -moz-border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ border: 1px solid #DDDDDD;
+ padding: 25px 25px;
+ clear: both;
+ }
+ .relpage ul
+ {
+ float: none;
+ padding: 1.5em;
+ }
+
+ h3.fn, span.fn
+ {
+ -moz-border-radius:7px 7px 7px 7px;
+ -webkit-border-radius:7px 7px 7px 7px;
+ border-radius:7px 7px 7px 7px;
+ background-color: #F6F6F6;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #E6E6E6;
+ font-weight: bold;
+ word-spacing:3px;
+ padding:3px 5px;
+ }
+
+ .functionIndex {
+ font-size:12pt;
+ word-spacing:10px;
+ margin-bottom:10px;
+ background-color: #F6F6F6;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #E6E6E6;
+ -moz-border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ width:100%;
+ }
+
+ .centerAlign
+ {
+ text-align:center;
+ }
+
+ .rightAlign
+ {
+ text-align:right;
+ }
+
+ .leftAlign
+ {
+ text-align:left;
+ }
+
+ .topAlign{
+ vertical-align:top
+ }
+
+ .functionIndex a{
+ display:inline-block;
+ }
+
+/* end content elements */
+/* footer elements */
+
+ .footer
+ {
+ color: #393735;
+ font-size: 0.75em;
+ text-align: center;
+ padding-top: 1.5em;
+ padding-bottom: 1em;
+ background-color: #E6E7E8;
+ margin: 0;
+ }
+ .footer p
+ {
+ margin: 0.25em
+ }
+ .small
+ {
+ font-size: 0.5em;
+ }
+/* end footer elements */
+
+ .item {
+ float: left;
+ position: relative;
+ width: 100%;
+ overflow: hidden;
+ }
+
+
+ .item .primary {
+ margin-right: 220px;
+ position: relative;
+ }
+
+ .item hr {
+ margin-left: -220px;
+ }
+
+ .item .secondary {
+ float: right;
+ width: 200px;
+ position: relative;
+ }
+
+ .item .cols {
+ clear: both;
+ display: block;
+ }
+
+ .item .cols .col {
+ float: left;
+ margin-left: 1.5%;
+ }
+
+ .item .cols .col.first {
+ margin-left: 0;
+ }
+
+ .item .cols.two .col {
+ width: 45%;
+ }
+
+ .item .box {
+ margin: 0 0 10px 0;
+ }
+
+ .item .box h3 {
+ margin: 0 0 10px 0;
+ }
+
+ .cols.unclear {
+ clear:none;
+ }
+}
+
+/* end of screen media */
+
+/* start of print media */
+
+@media print
+{
+ input, textarea, .header, .footer, .toolbar, .feedback, .wrapper .hd, .wrapper .bd .sidebar, .wrapper .ft, #feedbackBox, #blurpage, .toc, .breadcrumb, .toolbar, .floatingResult
+ {
+ display: none;
+ background: none;
+ }
+ .content
+ {
+ background: none;
+ display: block;
+ width: 100%; margin: 0; float: none;
+ }
+}
+/* end of print media */
diff --git a/doc/config/style/style.css b/doc/config/style/style.css
new file mode 100644
index 000000000..128eb27da
--- /dev/null
+++ b/doc/config/style/style.css
@@ -0,0 +1,1627 @@
+@media screen
+{
+
+/* basic elements */
+ html
+ {
+ color: #000000;
+ background: #FFFFFF;
+ }
+ body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, button, textarea, p, blockquote, th, td
+ {
+ margin: 0;
+ padding: 0;
+ }
+ table
+ {
+ border-collapse: collapse;
+ border-spacing: 0;
+ }
+ fieldset, img
+ {
+ border: 0;
+ max-width:100%;
+ }
+ address, caption, cite, code, dfn, em, strong, th, var, optgroup
+ {
+ font-style: inherit;
+ font-weight: inherit;
+ }
+ del, ins
+ {
+ text-decoration: none;
+ }
+ li
+ {
+ list-style: none;
+ }
+ ol li
+ {
+ list-style: decimal;
+ }
+ caption, th
+ {
+ text-align: left;
+ }
+ h1, h2, h3, h4, h5, h6
+ {
+ font-size: 100%;
+ }
+ q:before, q:after
+ {
+ content: '';
+ }
+ abbr, acronym
+ {
+ border: 0;
+ font-variant: normal;
+ }
+ sup, sub
+ {
+ vertical-align: baseline;
+ }
+ tt, .qmlreadonly span, .qmldefault span
+ {
+ word-spacing:5px;
+ }
+ legend
+ {
+ color: #000000;
+ }
+ input, button, textarea, select, optgroup, option
+ {
+ font-family: inherit;
+ font-size: inherit;
+ font-style: inherit;
+ font-weight: inherit;
+ }
+ input, button, textarea, select
+ {
+ font-size: 100%;
+ }
+ strong
+ {
+ font-weight: bold;
+ }
+ em
+ {
+ font-style: italic;
+ }
+
+ /* adding Qt theme */
+ html
+ {
+ /* background-color: #e5e5e5;*/
+ }
+ body
+ {
+ background: #e6e7e8 url(../images/page_bg.png) repeat-x 0 0;
+ font: normal 13px/1.2 Verdana;
+ color: #363534;
+ }
+ a
+ {
+ color: #00732f;
+ text-decoration: none;
+ }
+ hr
+ {
+ background-color: #E6E6E6;
+ border: 1px solid #E6E6E6;
+ height: 1px;
+ width: 100%;
+ text-align: left;
+ margin: 15px 0px 15px 0px;
+ }
+
+ pre
+ {
+ border: 1px solid #DDDDDD;
+ -moz-border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ margin: 0 20px 10px 10px;
+ padding: 20px 15px 20px 20px;
+ overflow-x: auto;
+ }
+ table, pre
+ {
+ -moz-border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ background-color: #F6F6F6;
+ border: 1px solid #E6E6E6;
+ border-collapse: separate;
+ font-size: 11px;
+ margin-bottom: 25px;
+ }
+ pre.highlightedCode {
+ display: block;
+ overflow:hidden;
+ }
+ thead
+ {
+ margin-top: 5px;
+ font:600 12px/1.2 Arial;
+ }
+ th
+ {
+ padding: 5px 15px 5px 15px;
+ background-color: #E1E1E1;
+ border-left: 1px solid #E6E6E6;
+ }
+ td
+ {
+ padding: 3px 15px 3px 15px;
+ }
+ tr.odd td:hover, tr.even td:hover {}
+
+ td.rightAlign
+ {
+ padding: 3px 5px 3px 10px;
+ }
+ table tr.odd
+ {
+ border-left: 1px solid #E6E6E6;
+ background-color: #F6F6F6;
+ color: #66666E;
+ }
+ table tr.even
+ {
+ border-left: 1px solid #E6E6E6;
+ background-color: #ffffff;
+ color: #66666E;
+ }
+ table tr.odd td:hover, table tr.even td:hover
+ {
+ /* background-color: #E6E6E6;*/ /* disabled until further notice */
+ }
+
+ div.float-left
+ {
+ float: left; margin-right: 2em
+ }
+ div.float-right
+ {
+ float: right; margin-left: 2em
+ }
+
+ span.comment
+ {
+ color: #008B00;
+ font-style: italic
+ }
+ span.string, span.char
+ {
+ color: #000084;
+ }
+ span.number
+ {
+ color: #a46200;
+ }
+ span.operator
+ {
+ color: #202020;
+ }
+ span.keyword
+ {
+ color: #840000;
+ }
+ span.name
+ {
+ color: black
+ }
+ span.type
+ {
+ font-weight: bold
+ }
+ span.type a:visited
+ {
+ color: #0F5300;
+ }
+ span.preprocessor
+ {
+ color: #404040
+ }
+/* end basic elements */
+
+/* font style elements */
+ .heading
+ {
+ font: normal bold 16px/1.2 Arial;
+ padding-bottom: 15px;
+ }
+ .subtitle
+ {
+ font-size: 13px;
+ }
+ .small-subtitle
+ {
+ font-size: 13px;
+ }
+/* end font style elements */
+
+/* global settings*/
+ .header, .footer, .wrapper
+ {
+ min-width: 600px;
+ max-width: 1500px;
+ margin: 0 30px;
+ }
+ .header, .footer
+ {
+ display: block;
+ clear: both;
+ overflow: hidden;
+ }
+ .header:after, .footer:after, .breadcrumb:after, .wrap .content:after, .group:after
+ {
+ content: ".";
+ display: block;
+ height: 0;
+ clear: both;
+ visibility: hidden;
+ }
+
+/* end global settings*/
+/* header elements */
+ .header
+ {
+ height: 115px;
+ position: relative;
+ }
+ .header .icon
+ {
+ position: absolute;
+ top: 13px;
+ left: 0;
+ }
+ .header .qtref
+ {
+ position: absolute;
+ top: 28px;
+ left: 88px;
+ width: 302px;
+ height: 22px;
+ }
+ .header .qtref span
+ {
+ display: block;
+ width: 420px;
+ height: 30px;
+ text-indent: -999em;
+ background: url(../images/sprites-combined.png) no-repeat -80px -235px;
+ }
+ .content a:visited
+ {
+ color: #4c0033;
+ text-decoration: none;
+ }
+ .content a:visited:hover
+ {
+ color: #4c0033;
+ text-decoration: underline;
+ }
+
+ #nav-topright
+ {
+ height: 70px;
+ }
+
+ #nav-topright ul
+ {
+ list-style-type: none;
+ float: right;
+ width: 370px;
+ margin-top: 11px;
+ }
+
+ #nav-topright li
+ {
+ display: inline-block;
+ margin-right: 20px;
+ float: left;
+ }
+
+ #nav-topright li.nav-topright-last
+ {
+ margin-right: 0;
+ }
+
+ #nav-topright li a
+ {
+ background: transparent url(../images/sprites-combined.png) no-repeat;
+ height: 18px;
+ display: block;
+ overflow: hidden;
+ text-indent: -9999px;
+ }
+
+ #nav-topright li.nav-topright-home a
+ {
+ width: 65px;
+ background-position: -2px -91px;
+ }
+
+ #nav-topright li.nav-topright-home a:hover
+ {
+ background-position: -2px -117px;
+ }
+
+
+ #nav-topright li.nav-topright-dev a
+ {
+ width: 30px;
+ background-position: -76px -91px;
+ }
+
+ #nav-topright li.nav-topright-dev a:hover
+ {
+ background-position: -76px -117px;
+ }
+
+
+ #nav-topright li.nav-topright-labs a
+ {
+ width: 40px;
+ background-position: -114px -91px;
+ }
+
+ #nav-topright li.nav-topright-labs a:hover
+ {
+ background-position: -114px -117px;
+ }
+
+ #nav-topright li.nav-topright-doc a
+ {
+ width: 32px;
+ background-position: -162px -91px;
+ }
+
+ #nav-topright li.nav-topright-doc a:hover, #nav-topright li.nav-topright-doc-active a
+ {
+ background-position: -162px -117px;
+ }
+
+ #nav-topright li.nav-topright-blog a
+ {
+ width: 40px;
+ background-position: -203px -91px;
+ }
+
+ #nav-topright li.nav-topright-blog a:hover, #nav-topright li.nav-topright-blog-active a
+ {
+ background-position: -203px -117px;
+ }
+
+ #nav-topright li.nav-topright-shop a
+ {
+ width: 40px;
+ background-position: -252px -91px;
+ }
+
+ #nav-topright li.nav-topright-shop a:hover, #nav-topright li.nav-topright-shop-active a
+ {
+ background-position: -252px -117px;
+ }
+
+ #nav-logo
+ {
+ background: transparent url(../images/sprites-combined.png ) no-repeat 0 -225px;
+ left: -3px;
+ position: absolute;
+ width: 75px;
+ height: 75px;
+ top: 13px;
+ }
+ #nav-logo a
+ {
+ width: 75px;
+ height: 75px;
+ display: block;
+ text-indent: -9999px;
+ overflow: hidden;
+ }
+
+
+ .shortCut-topleft-inactive
+ {
+ padding-left: 3px;
+ padding-right: 3px;
+ background: transparent url( ../images/sprites-combined.png) no-repeat 0px -58px;
+ height: 20px;
+ }
+ .shortCut-topleft-inactive span
+ {
+ font-variant: normal;
+ }
+ .shortCut-topleft-inactive span a:hover, .shortCut-topleft-active a:hover
+ {
+ text-decoration:none;
+ }
+ #shortCut
+ {
+ padding-top: 10px;
+ font-weight: bolder;
+ color: #b0adab;
+ }
+ #shortCut ul
+ {
+ list-style-type: none;
+ float: left;
+ width: 347px;
+ margin-left: 100px;
+ }
+ #shortCut li
+ {
+ display: inline-block;
+ margin-right: 25px;
+ float: left;
+ white-space: nowrap;
+ }
+ #shortCut li a
+ {
+ color: #b0adab;
+ }
+ #shortCut li a:hover
+ {
+ color: #44a51c;
+ }
+
+
+
+/* end header elements */
+/* content and sidebar elements */
+ .wrapper
+ {
+ background: url(../images/bg_r.png) repeat-y 100% 0;
+ }
+ .wrapper .hd
+ {
+ padding-left: 216px;
+ height: 15px;
+ background: url(../images/page.png) no-repeat 0 0;
+ overflow: hidden;
+ }
+
+
+
+
+ .wrapper .hd span
+ {
+ height: 15px;
+ display: block;
+ overflow: hidden;
+ background: url(../images/page.png) no-repeat 100% -30px;
+ }
+ .wrapper .bd
+ {
+ background: url(../images/bg_l.png) repeat-y 0 0;
+ position: relative;
+ }
+
+
+
+
+ .wrapper .ft
+ {
+ padding-left: 216px;
+ height: 15px;
+ background: url(../images/page.png) no-repeat 0 -75px;
+ overflow: hidden;
+ }
+
+
+
+
+ .wrapper .ft span
+ {
+ height: 15px;
+ display: block;
+ background: url(../images/page.png) no-repeat 100% -60px;
+ overflow: hidden;
+ }
+ .navTop{
+ float:right;
+ display:block;
+ padding-right:15px;
+
+
+ }
+
+
+
+/* end content and sidebar elements */
+/* sidebar elements */
+ .sidebar
+ {
+ float: left;
+ margin-left: 5px;
+ width: 200px;
+ font-size: 11px;
+ }
+
+
+
+
+
+
+ .sidebar .searchlabel
+ {
+ padding: 0 0 2px 17px;
+ font: normal bold 11px/1.2 Verdana;
+ }
+
+ .sidebar .search
+ {
+ padding: 0 15px 0 16px;
+ }
+
+ .sidebar .search form
+ {
+ background: url(../images/sprites-combined.png) no-repeat -6px -348px;
+ height:21px;
+ padding:2px 0 0 5px;
+ width:167px;
+ }
+
+ .sidebar .search form input#pageType
+ {
+ width: 158px;
+ height: 19px;
+ padding: 0;
+ border: 0px;
+ outline: none;
+ font: 13px/1.2 Verdana;
+ }
+
+ .sidebar .box
+ {
+ padding: 17px 15px 5px 16px;
+ }
+
+ .sidebar .box .first
+ {
+ background-image: none;
+ }
+
+ .sidebar .box h2
+ {
+ font: bold 16px/1.2 Arial;
+ padding: 0;
+ }
+ .sidebar .box h2 span
+ {
+ overflow: hidden;
+ display: inline-block;
+ }
+ .sidebar .box#lookup h2
+ {
+ background-image: none;
+ }
+ .sidebar #lookup.box h2 span
+ {
+ }
+ .sidebar .box#topics h2
+ {
+ background-image: none;
+ }
+ .sidebar #topics.box h2 span
+ {
+ }
+ .sidebar .box#examples h2
+ {
+ background-image: none;
+ }
+ .sidebar #examples.box h2 span
+ {
+ }
+
+ .sidebar .box .list
+ {
+ display: block;
+ max-height:200px;
+ min-height:120px;
+ overflow-y:auto;
+ overflow-x:none;
+ }
+ .list li a:hover
+ {
+ text-decoration: underline;
+ }
+ .sidebar .box ul
+ {
+ padding-bottom:5px;
+ padding-left:10px;
+ padding-top:5px;
+ }
+ .sidebar .box ul li
+ {
+ padding-left: 12px;
+ background: url(../images/bullet_gt.png) no-repeat 0 5px;
+ margin-bottom: 5px;
+ }
+ .sidebar .bottombar
+ {
+ background: url(../images/box_bg.png) repeat-x 0 bottom;
+ }
+ .sidebar .box ul li.noMatch
+ {
+ background: none;
+ color:#FF2A00;
+ font-style:italic;
+ }
+ .sidebar .box ul li.hit
+ {
+ background: none;
+ color:#AAD2F0;
+ font-style:italic;
+ }
+ .sidebar .search form input.loading
+ {
+ background:url("../images/spinner.gif") no-repeat scroll right center transparent;
+ }
+
+.floatingResult{
+ z-index:1;
+ position:relative;
+ padding-top:0px;
+ background-color:white;
+ border:solid 1px black;
+ height:250px;
+ width:600px;
+ overflow-x:hidden;
+ overflow-y:auto;
+}
+
+ .floatingResult:hover{
+ display:block;
+ }
+ .floatingResult:hover{
+ }
+
+/* end sidebar elements */
+/* content elements */
+ .wrap
+ {
+ margin: 0 5px 0 208px;
+ overflow: visible;
+ }
+
+
+
+
+ .wrap .toolbar
+ {
+ background-color: #fafafa;
+ border-bottom: 1px solid #d1d1d1;
+ height: 20px;
+ position: relative;
+ }
+ .wrap .toolbar .toolblock
+ {
+ position: absolute;
+ }
+ .wrap .toolbar .breadcrumb
+ {
+ font-size: 11px;
+ line-height: 1.2;
+ padding: 0 0 10px 21px;
+ height: 10px;
+ }
+ .wrap .toolbar .toolbuttons
+ {
+ padding: 0 0 10px 21px;
+ right: 5px;
+ vertical-align: middle;
+ overflow: hidden;
+ }
+ .wrap .toolbar .toolbuttons .active
+ {
+ color: #00732F;
+ }
+ .wrap .toolbar .toolbuttons ul
+ {
+ float: right;
+ }
+ .wrap .toolbar .toolbuttons li
+ {
+ float: left;
+ text-indent: -10px;
+ margin-top: -5px;
+ margin-right: 15px;
+ font-weight: bold;
+ color: #B0ADAB;
+ }
+
+ .toolbuttons #print
+ {
+ border-left: 1px solid #c5c4c4;
+ margin-top: 0;
+ padding-left: 7px;
+ text-indent: 0;
+ }
+ .toolbuttons #print a
+ {
+ width: 16px;
+ height: 16px;
+ }
+
+ .toolbuttons #print a span
+ {
+ width: 16px;
+ height: 16px;
+ text-indent: -999em;
+ display: block;
+ overflow: hidden;
+ background: url(../images/sprites-combined.png) no-repeat -137px -311px;
+ }
+
+ .toolbuttons #smallA
+ {
+ font-size: 10pt;
+ }
+ .toolbuttons #medA
+ {
+ font-size: 12pt;
+ }
+ .toolbuttons #bigA
+ {
+ font-size: 14pt;
+ margin-right: 7px;
+ }
+
+ #smallA:hover, #medA:hover, #bigA:hover
+ {
+ color: #00732F;
+ }
+
+
+ .wrap .content
+ {
+ padding: 30px;
+ word-wrap:break-word;
+ }
+
+ .wrap .breadcrumb ul
+ {
+ }
+ .wrap .breadcrumb ul li
+ {
+ float: left;
+ background: url(../images/breadcrumb.png) no-repeat 0 3px;
+ padding-left: 15px;
+ margin-left: 15px;
+ font-weight: bold;
+ }
+ .wrap .breadcrumb ul li.last
+ {
+ font-weight: normal;
+ }
+ .wrap .breadcrumb ul li a
+ {
+ color: #363534;
+ }
+ .wrap .breadcrumb ul li.first
+ {
+ background-image: none;
+ padding-left: 0;
+ margin-left: 0;
+ }
+
+
+
+
+ .wrap .content ol li {
+ background:none;
+ font:normal 10pt/1.2 Verdana;
+
+ margin-bottom:10px;
+ margin-left:12px;
+ /*list-style-type:disc;*/
+ }
+
+ .wrap .content ol li
+ {
+ background:none;
+ margin-bottom: 10px;
+ padding-left:0px;
+ margin-left:52px;
+ }
+
+ .wrap .content li
+ {
+ background: url(../images/bullet_sq.png) no-repeat 0 5px;
+ font: normal 400 10pt/1.2 Verdana;
+ margin-bottom: 10px;
+ padding-left:12px;
+ }
+
+ .content li:hover {}
+
+ .wrap .content h1
+ {
+ font: bold 18px/1.2 Arial;
+ }
+ .wrap .content h2
+ {
+ border-bottom:1px solid #DDDDDD;
+ font:600 16px/1.2 Arial;
+ margin-top:15px;
+ width:100%;
+ }
+ .wrap .content h3
+ {
+ font: bold 14px/1.2 Arial;
+ font:600 16px/1.2 Arial;
+ margin-top:15px;
+ width:100%;
+ }
+ .wrap .content p
+ {
+ line-height: 20px;
+ padding: 5px;
+ }
+ .wrap .content table p
+ {
+ line-height: 20px;
+ /* padding: 0px;*/
+ }
+ .wrap .content ul
+ {
+ padding-left: 25px;
+ padding-top: 10px;
+ }
+ .wrap .content ul img {
+ vertical-align:middle;
+ }
+ a:hover
+ {
+ color: #4c0033;
+ text-decoration: underline;
+ }
+ .feedback
+ {
+ float: none;
+ position: absolute;
+ right: 15px;
+ bottom: 10px;
+ font: normal 8px/1 Verdana;
+ color: #B0ADAB;
+ }
+ .feedback:hover
+ {
+ float: right;
+ font: normal 8px/1 Verdana;
+ color: #00732F;
+ text-decoration: underline;
+ }
+ .alphaChar{
+ width:95%;
+ background-color:#F6F6F6;
+ border:1px solid #E6E6E6;
+ -moz-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ font-size:12pt;
+ padding-left:10px;
+ margin-top:10px;
+ margin-bottom:10px;
+ }
+ .flowList{
+ /*vertical-align:top;*/
+ /*margin:20px auto;*/
+
+ column-count:3;
+ -webkit-column-count:3;
+ -moz-column-count:3;
+/*
+ column-width:100%;
+ -webkit-column-width:200px;
+ -col-column-width:200px;
+*/
+ column-gap:41px;
+ -webkit-column-gap:41px;
+ -moz-column-gap:41px;
+
+ column-rule: 1px dashed #ccc;
+ -webkit-column-rule: 1px dashed #ccc;
+ -moz-column-rule: 1px dashed #ccc;
+ }
+
+ .flowList dl{
+ }
+ .flowList dd{
+ /*display:inline-block;*/
+ margin-left:10px;
+ min-width:250px;
+ line-height: 1.2;
+ min-width:100%;
+
+ }
+
+ .flowList dd a{
+ }
+
+ .wrap .content .flowList p{
+ padding:0px;
+ }
+
+ .content .alignedsummary
+ {
+ margin: 15px;
+ }
+
+
+ .qmltype
+ {
+ text-align: center;
+ font-size: 160%;
+ }
+ .qmlreadonly
+ {
+ padding-left: 5px;
+ float: right;
+ color: #254117;
+ }
+
+ .qmldefault
+ {
+ padding-left: 5px;
+ float: right;
+ color: red;
+ }
+
+ .qmldoc
+ {
+ }
+
+ *.qmlitem p
+ {
+ }
+ #feedbackBox
+ {
+ display: none;
+ -moz-border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ border: 1px solid #DDDDDD;
+ position: fixed;
+ top: 100px;
+ left: 33%;
+ height: 230px;
+ width: 400px;
+ padding: 5px;
+ background-color: #e6e7e8;
+ z-index: 4;
+ }
+ #feedcloseX
+ {
+ display: inline;
+ padding: 5px 5px 0 0;
+ margin-bottom: 3px;
+ color: #363534;
+ font-weight: bold;
+ float: right;
+ text-decoration: none;
+ }
+
+ #feedbox
+ {
+ display: inline;
+ width: 370px;
+ height: 120px;
+ margin: 0px 25px 10px 15px;
+ }
+ #noteHead
+ {
+ font-weight:bold;
+ padding:10px 10px 10px 20px;
+ }
+ #feedsubmit
+ {
+ display: inline;
+ float: right;
+ margin: 4px 32px 0 0;
+ }
+
+ .note
+ {
+ font-size:7pt;
+ padding-bottom:3px;
+ padding-left:20px;
+ }
+
+ #blurpage
+ {
+ display: none;
+ position: fixed;
+ float: none;
+ top: 0px;
+ left: 0px;
+ right: 0px;
+ bottom: 0px;
+ background: transparent url(../images/feedbackground.png) 0 0;
+ z-index: 3;
+ }
+ .toc
+ {
+ float: right;
+ -moz-border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ background-color: #F6F6F6;
+ border: 1px solid #DDDDDD;
+ margin: 0 20px 10px 10px;
+ padding: 20px 15px 20px 20px;
+ height: auto;
+ width: 200px;
+ }
+
+ .toc h3, .generic a
+ {
+ font: bold 12px/1.2 Arial;
+ }
+
+ .generic{
+ }
+ .generic td{
+ /* padding:5px;*/
+ }
+ .generic .alphaChar{
+ margin-top:5px;
+ }
+
+ .generic .odd .alphaChar{
+ background-color: #F6F6F6;
+ }
+
+ .generic .even .alphaChar{
+ background-color: #FFFFFF;
+ }
+
+ .alignedsummary{}
+ .propsummary{}
+ .memItemLeft{}
+ .memItemRight{
+ padding:3px 15px 3px 0;
+ }
+ .bottomAlign{}
+ .highlightedCode
+ {
+ margin:10px;
+ }
+ .LegaleseLeft{}
+ .valuelist{}
+ .annotated td{
+ padding: 3px 5px 3px 5px;
+ }
+ .obsolete{}
+ .compat{}
+ .flags{}
+ .qmlsummary{}
+ .qmlitem{}
+ .qmlproto{}
+ .qmlname{}
+ .qmlreadonly{}
+ .qmldefault{}
+ .qmldoc{}
+ .qt-style{}
+ .redFont{}
+ code{}
+
+ .wrap .content .toc ul
+ {
+ padding-left: 0px;
+ }
+
+ .wrap .content .toc h3{
+ border-bottom:0px;
+ margin-top:0px;
+ }
+
+ .wrap .content .toc h3 a:hover{
+ color:#00732F;
+ text-decoration:none;
+ }
+
+
+ .wrap .content .toc .level2
+ {
+ margin-left: 15px;
+ }
+
+ .wrap .content .toc .level3
+ {
+ margin-left: 30px;
+ }
+
+ .content .toc li
+ {
+ font: normal 10px/1.2 Verdana;
+ background: url(../images/bullet_dn.png) no-repeat 0 5px;
+ }
+ .relpage
+ {
+ -moz-border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ border: 1px solid #DDDDDD;
+ padding: 25px 25px;
+ clear: both;
+ }
+ .relpage ul
+ {
+ float: none;
+ padding: 15px;
+ }
+ .content .relpage li
+ {
+ font: normal 11px/1.2 Verdana;
+ }
+ h3.fn, span.fn
+ {
+ -moz-border-radius:7px 7px 7px 7px;
+ -webkit-border-radius:7px 7px 7px 7px;
+ border-radius:7px 7px 7px 7px;
+ background-color: #F6F6F6;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #E6E6E6;
+ font-weight: bold;
+ word-spacing:3px;
+ padding:3px 5px;
+ }
+
+ .functionIndex {
+ font-size:12pt;
+ word-spacing:10px;
+ margin-bottom:10px;
+ background-color: #F6F6F6;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #E6E6E6;
+ -moz-border-radius: 7px 7px 7px 7px;
+ -webkit-border-radius: 7px 7px 7px 7px;
+ border-radius: 7px 7px 7px 7px;
+ width:100%;
+ }
+
+ .centerAlign
+ {
+ text-align:center;
+ }
+
+ .rightAlign
+ {
+ text-align:right;
+ }
+
+
+ .leftAlign
+ {
+ text-align:left;
+ }
+
+ .topAlign{
+ vertical-align:top
+ }
+
+ .functionIndex a{
+ display:inline-block;
+ }
+
+/* end content elements */
+/* footer elements */
+
+ .footer
+ {
+ min-height: 100px;
+ color: #797775;
+ font: normal 9px/1 Verdana;
+ text-align: center;
+ padding-top: 40px;
+ background-color: #E6E7E8;
+ margin: 0;
+ }
+/* end footer elements */
+
+
+
+
+ /* start index box */
+ .indexbox
+ {
+ width: 100%;
+ display:inline-block;
+ }
+
+ .indexboxcont
+ {
+ display: block;
+
+ }
+
+ .indexboxbar
+ {
+ background: transparent url(../images/horBar.png ) repeat-x left bottom;
+ margin-bottom: 25px;
+
+
+ }
+
+ .indexboxcont .section
+ {
+ display: inline-block;
+ width: 49%;
+ *width:42%;
+ _width:42%;
+ padding:0 2% 0 1%;
+ vertical-align:top;
+
+}
+
+ .indexboxcont .indexIcon
+ {
+ width: 11%;
+ *width:18%;
+ _width:18%;
+ overflow:hidden;
+
+}
+
+.indexboxcont .section {
+ float: left;
+}
+
+ .indexboxcont .section p
+ {
+ padding-top: 20px;
+ padding-bottom: 20px;
+ }
+ .indexboxcont .sectionlist
+ {
+ display: inline-block;
+ vertical-align:top;
+ width: 32.5%;
+ padding: 0;
+ }
+ .indexboxcont .sectionlist ul
+ {
+ margin-bottom: 20px;
+ }
+
+ .indexboxcont .sectionlist ul li
+ {
+ line-height: 12px;
+ }
+
+ .content .indexboxcont li
+ {
+ font: normal bold 13px/1 Verdana;
+ }
+
+ .indexbox a:hover, .indexbox a:visited:hover
+ {
+ color: #4c0033;
+ text-decoration: underline;
+ }
+
+ .indexbox a:visited
+ {
+ color: #00732f;
+ text-decoration: none;
+ }
+
+ .indexbox .indexIcon {
+ width: 11%;
+ }
+
+
+ .indexbox .indexIcon span
+ {
+ display: block;
+ }
+
+ .indexbox.guide .indexIcon span
+ {
+ width: 96px;
+ height: 137px;
+ background: url(../images/sprites-combined.png) no-repeat -5px -376px;
+ padding: 0;
+ }
+
+ .indexbox.tools .indexIcon span
+ {
+ width: 115px;
+ height: 137px;
+ background: url(../images/sprites-combined.png) no-repeat -111px -376px;
+ padding: 0;
+ }
+ .indexboxcont:after
+ {
+ content: ".";
+ display: block;
+ height: 0;
+ clear: both;
+ visibility: hidden;
+ }
+
+
+
+/* start of creator spec*/
+ .creator
+ {
+ margin-left:0px;
+ margin-right:0px;
+ padding-left:0px;
+ padding-right:0px;
+ }
+ .creator .wrap .content ol li {
+ list-style-type:decimal;
+
+ }
+ .creator .header .icon,
+ .creator .feedback,
+ .creator .t_button,
+ .creator .feedback,
+ .creator #feedbackBox,
+ .creator #feedback,
+ .creator #blurpage,
+ /*.creator .indexbox .indexIcon span,*/
+ .creator .wrapper .hd,
+/* .creator .indexbox .indexIcon,*/
+ .creator .header #nav-logo,
+ .creator #offlinemenu,
+ .creator #offlinesearch,
+ .creator .header #nav-topright,
+ .creator .header #shortCut ,
+ .creator .wrapper .hd,
+ .creator .wrapper .ft,
+ .creator .sidebar,
+ .creator .wrap .feedback
+ {
+ display:none;
+ }
+
+ body.creator
+ {
+ background: none;
+
+ font: normal 13px/1.2 Verdana;
+ color: #363534;
+ background-color: #FAFAFA;
+ }
+
+ .wrap .content ol li {
+
+ }
+
+
+ .creator .header, .footer, .wrapper
+ {
+ max-width: 1500px;
+ margin: 0px;
+ }
+
+ .creator .wrapper
+ {
+ position:relative;
+ top:5px;
+ }
+ .creator .wrapper .bd
+ {
+
+ background:#FFFFFF;
+ }
+
+
+ .creator .header, .footer
+ {
+ display: block;
+ clear: both;
+ overflow: hidden;
+ }
+ .creator .wrap .content p
+
+ {
+ line-height: 20px;
+ padding: 5px;
+ }
+
+ .creator .header .qtref span
+ {
+ background:none;
+ }
+
+
+
+ .creator .footer
+ {
+ border-top:1px solid #E5E5E5;
+ height: 50px;
+ margin:0px;
+ padding:10px;
+ }
+
+ .creator .footer p
+ {
+ text-align:justify;
+ max-width:900px;
+ }
+
+ .creator .wrap
+ {
+
+ padding:0 5px 0 5px;
+ margin: 0px;
+ }
+ .creator .wrap .toolbar
+ {
+
+
+ border-bottom:1px solid #E5E5E5;
+ /*width:100%;*/
+ margin-left:-5px;
+ margin-right:-5px;
+ }
+ .creator .wrap .breadcrumb ul li a
+ {
+ /* color: #363534;*/
+ color: #00732F;
+ }
+
+ .creator .wrap .content
+ {
+ padding: 0px;
+ word-wrap:break-word;
+ }
+
+ .creator .wrap .content ol li {
+ background:none;
+ font: inherit;
+ padding-left: 0px;
+ }
+
+ .creator .wrap .content .descr ol li {
+ margin-left: 45px;
+
+ }
+ .creator .content .alignedsummary
+ {
+ margin: 5px;
+ width:100%;
+ }
+ .creator .generic{
+ max-width:75%;
+ }
+ .creator .generic td{
+ /* padding:0;*/
+ }
+ .creator .indexboxbar
+ {
+ border-bottom:1px solid #E5E5E5;
+ margin-bottom: 25px;
+ background: none;
+ }
+
+
+
+ .creator .header
+ {
+ width: 100%;
+ margin: 0;
+ height: auto;
+ background-color: #ffffff;
+ padding: 10px 0 5px 0;
+ overflow: visible;
+ border-bottom: solid #E5E5E5 1px;
+ z-index:1;
+
+
+
+
+
+
+
+
+ /* position:fixed;*/
+ }
+
+
+ .creator .header .content
+ {
+ }
+ .creator .header .qtref
+ {
+ color: #00732F;
+ position: static;
+ float: left;
+ margin-left: 5px;
+ font: bold 18px/1 Arial;
+ }
+
+ .creator .header .qtref:visited
+ {
+ color: #00732F;
+ }
+ .creator .header .qtref:hover
+ {
+ color: #00732F;
+ text-decoration:none;
+ }
+ .creator .header .qtref span
+ {
+ background-image: none;
+ text-indent: 0;
+ text-decoration:none;
+ }
+
+
+
+
+
+
+ .creator .wrap .toolbar
+ {
+ display:block;
+ padding-top:0px;
+ }
+
+
+
+ .creator .wrap .breadcrumb ul li {
+ font-weight: normal;
+ }
+
+ .creator .wrap .breadcrumb ul li a {
+ /*color: #44a51c;*/
+ }
+
+ .creator .wrap .breadcrumb ul li.last a {
+ /*color: #363534;*/
+ }
+
+ .creator #narrowmenu ul
+ {
+ border-bottom:solid 1px #E5E5E5;
+ border-left:solid 1px #E5E5E5;
+ border-right:solid 1px #E5E5E5;
+ }
+
+ .creator #narrowmenu li ul {
+ margin-top:-15px;
+ }
+
+
+ .creator .toc {
+ margin:10px 20px 10px 10px;
+ }
+
+ .creator #narrowsearch, .creator #narrowmenu{
+ display:none;
+ }
+/* end of creator spec*/
+
+}
+
+/* end of screen media */
+
+/* start of print media */
+
+@media print
+{
+ input, textarea, .header, .footer, .toolbar, .feedback, .wrapper .hd, .wrapper .bd .sidebar, .wrapper .ft, #feedbackBox, #blurpage, .toc, .breadcrumb, .toolbar, .floatingResult
+ {
+ display: none;
+ background: none;
+ }
+ .content
+ {
+ background: none;
+ display: block;
+ width: 100%; margin: 0; float: none;
+
+ }
+}
+/* end of print media */
diff --git a/doc/config/style/style_ie6.css b/doc/config/style/style_ie6.css
new file mode 100644
index 000000000..16fb8505d
--- /dev/null
+++ b/doc/config/style/style_ie6.css
@@ -0,0 +1,54 @@
+.indexbox, .indexboxcont, .group {
+ zoom: 1;
+ height: 1%;
+}
+
+.sidebar {
+ margin-left: 3px;
+ width: 199px;
+ overflow: hidden;
+}
+
+.sidebar .search form {
+ position: relative;
+}
+
+.sidebar .search form fieldset {
+ position: absolute;
+ margin-top: -1px;
+}
+
+.sidebar .search form input#searchstring {
+ border: 1px solid #fff;
+ height: 18px;
+}
+
+.wrap {
+ zoom: 1;
+}
+
+.content,
+.toolbar {
+ zoom: 1;
+ margin-left: -3px;
+ position: relative;
+}
+
+.indexbox {
+ clear: both;
+}
+
+.indexboxcont .section {
+ zoom: 1;
+ float: left;
+}
+
+.indexboxcont .sectionlist {
+ zoom: 1;
+ float: left;
+}
+
+.wrap .toolbar .toolbuttons li {
+ text-indent: 0;
+ margin-right: 8px;
+} \ No newline at end of file
diff --git a/doc/config/style/style_ie7.css b/doc/config/style/style_ie7.css
new file mode 100644
index 000000000..afbff5f88
--- /dev/null
+++ b/doc/config/style/style_ie7.css
@@ -0,0 +1,19 @@
+.indexbox, .indexboxcont, .group {
+ min-height: 1px;
+}
+
+.sidebar .search form input#searchstring {
+ border: 1px solid #fff;
+ height: 17px;
+}
+
+
+.indexboxcont .section {
+ zoom: 1;
+ float: left;
+}
+
+.indexboxcont .sectionlist {
+ zoom: 1;
+ float: left;
+}
diff --git a/doc/config/style/style_ie8.css b/doc/config/style/style_ie8.css
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/doc/config/style/style_ie8.css
diff --git a/doc/config/style/superfish.css b/doc/config/style/superfish.css
new file mode 100644
index 000000000..2bdaef4d9
--- /dev/null
+++ b/doc/config/style/superfish.css
@@ -0,0 +1,51 @@
+.sf-menu, .sf-menu * {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+.sf-menu {
+ line-height: 1.0;
+}
+.sf-menu ul {
+ position: absolute;
+ top: -999em;
+ width: 10em; /* left offset of submenus need to match (see below) */
+}
+.sf-menu ul li {
+ width: 100%;
+}
+.sf-menu li:hover {
+ visibility: inherit; /* fixes IE7 'sticky bug' */
+}
+.sf-menu li {
+ float: left;
+ position: relative;
+}
+.sf-menu a {
+ display: block;
+ position: relative;
+}
+.sf-menu li:hover ul,
+.sf-menu li.sfHover ul {
+ left: 0;
+ top: 2.5em; /* match top ul list item height */
+ z-index: 99;
+}
+ul.sf-menu li:hover li ul,
+ul.sf-menu li.sfHover li ul {
+ top: -999em;
+}
+ul.sf-menu li li:hover ul,
+ul.sf-menu li li.sfHover ul {
+ left: 10em; /* match ul width */
+ top: 0;
+}
+ul.sf-menu li li:hover li ul,
+ul.sf-menu li li.sfHover li ul {
+ top: -999em;
+}
+ul.sf-menu li li li:hover ul,
+ul.sf-menu li li li.sfHover ul {
+ left: 10em; /* match ul width */
+ top: 0;
+}
diff --git a/doc/doc.pri b/doc/doc.pri
new file mode 100644
index 000000000..285a8870e
--- /dev/null
+++ b/doc/doc.pri
@@ -0,0 +1,31 @@
+
+win32:!win32-g++ {
+ unixstyle = false
+} else:win32-g++:isEmpty(QMAKE_SH) {
+ unixstyle = false
+} else {
+ unixstyle = true
+}
+
+LINE_SEP=$$escape_expand(\\n\\t)
+GENERATOR = $$[QT_INSTALL_BINS]/qhelpgenerator
+QDOC = $$[QT_INSTALL_BINS]/qdoc3
+MOBILITY_DOCUMENTATION = $$QDOC $${QT_MOBILITY_SOURCE_TREE}/doc/config/qtmobility.qdocconf $$LINE_SEP \
+ cd $${QT_MOBILITY_SOURCE_TREE} && \
+ $$GENERATOR doc/html/qtmobility.qhp -o doc/qch/qtmobility.qch
+
+ONLINE_MOBILITY_DOCUMENTATION = $$QDOC $${QT_MOBILITY_SOURCE_TREE}/doc/config/qtmobility-online.qdocconf $$LINE_SEP \
+ cd $${QT_MOBILITY_SOURCE_TREE} && \
+ $$GENERATOR doc/html/qtmobility.qhp -o doc/qch/qtmobility.qch
+
+contains(unixstyle, false):MOBILITY_DOCUMENTATION = $$replace(MOBILITY_DOCUMENTATION, "/", "\\")
+
+# Build rules
+qch_docs.commands = $$MOBILITY_DOCUMENTATION
+qch_onlinedocs.commands = $$ONLINE_MOBILITY_DOCUMENTATION
+
+docs.depends = qch_docs
+onlinedocs.depends = qch_onlinedocs
+
+
+QMAKE_EXTRA_TARGETS += qch_docs qch_onlinedocs docs onlinedocs
diff --git a/doc/doc.pro b/doc/doc.pro
new file mode 100644
index 000000000..d0e0ed409
--- /dev/null
+++ b/doc/doc.pro
@@ -0,0 +1,8 @@
+######################################################################
+#
+# Mobility API project
+#
+######################################################################
+
+TEMPLATE = subdirs
+SUBDIRS += src/snippets
diff --git a/doc/src/camera.qdoc b/doc/src/camera.qdoc
new file mode 100644
index 000000000..d3379f35f
--- /dev/null
+++ b/doc/src/camera.qdoc
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// XXX OMG its so bad
+// namespace warning
+// why mention control?
+// bad brief
+// control list
+// links?
+
+/*!
+
+\page camera.html
+
+\title Camera
+\brief An API to control camera devices.
+
+The Camera API provides control of system camera devices. Providing support
+for still or video image capture with sound support.
+
+\tableofcontents
+
+
+\section1 Namespace
+
+The QtMobility APIs are placed into the \i{QtMobility} namespace. This is done
+to facilitate the future migration of QtMobility APIs into Qt. See the
+\l {Quickstart guide} for an example on how the
+namespace impacts on application development.
+
+
+\section1 Overview
+
+The Camera API allows high level control of various aspects of still images
+and video. Camera is a part of the Multimedia API and this relationship is
+apparent when you notice that certain core classes are subclassed from some
+Multimedia base classes including \l QMediaObject and \l QMediaControl.
+
+
+
+\section1 Still Images
+
+In order to capture an image we need to create a \l QCamera object and use
+it to initialize a \l QVideoWidget, so we can see where the camera is
+pointing - a viewfinder. The camera object is also used to initialize a new
+QCameraImageCapture object, imageCapture. All that is then needed is to start
+the camera, lock it so that the settings are not changed while the image
+capture occurs, capture the image, and finally unlock the camera ready for
+the next photo.
+
+ \code
+ camera = new QCamera;
+ viewFinder = new QCameraViewfinder;
+ camera->setViewfinder(viewFinder);
+ viewFinder->show();
+
+ imageCapture = new QCameraImageCapture(camera);
+
+ camera->setCaptureMode(QCamera::CaptureStillImage);
+ camera->start();
+
+ //on half pressed shutter button
+ camera->searchA{QCameraFocus::FocusMode}{ndLock();
+
+ //on shutter button pressed
+ imageCapture->capture();
+
+ //on shutter button released
+ camera->unlock();
+ \endcode
+
+Alternatively, we could have used a QGraphicsVideoItem as a viewfinder.
+
+
+\section1 Video Clips
+
+Previously we saw code that allowed the capture of a still image. Recording
+video requires the use of a \l QMediaRecorder object and a \l
+QAudioCaptureSource for sound.
+
+To record video we need to create a camera object as before but this time as
+well as creating a viewfinder, we will also initialize a media recorder object.
+
+ \code
+ camera = new QCamera;
+ mediaRecorder = new QMediaRecorder(camera);
+
+ camera->setCaptureMode(QCamera::CaptureVideo);
+ camera->start();
+
+ //on shutter button pressed
+ mediaRecorder->record();
+ \endcode
+
+Signals from the \i mediaRecorder can be connected to slots to react to
+changes in the state of the recorder or error events. Recording itself
+starts with the \l {QMediaRecorder::record()}{record()} function of
+mediaRecorder being called, this causes the signal \l
+{QMediaRecorder::stateChanged()}{stateChanged()} to be emitted. The
+recording process can be changed with the \l {QMediaRecorder::record()}{record()},
+\l {QMediaRecorder::pause()}{pause()}, \l {QMediaRecorder::stop()}{stop()} and
+\l {QMediaRecorder::setMuted()}{setMuted()} slots in \l QMediaRecorder.
+
+When the camera is in video mode, as decided by the application, then as the
+shutter button is pressed the camera is locked as before but instead the
+\l {QMediaRecorder::record()}{record()} function in \l QMediaRecorder is used.
+
+
+
+\section1 Focus
+
+Focusing is managed by the classes \l QCameraFocus and \l QCameraFocusControl.
+QCameraFocus allows the developer to set the general policy by means of the
+enums for the \l {QCameraFocus::FocusMode}{FocusMode} and the
+\l {QCameraFocus::FocusPointMode}{FocusPointMode}. \l {QCameraFocus::FocusMode}{FocusMode}
+deals with settings such as \l {QCameraFocus::FocusMode}{AutoFocus},
+\l {QCameraFocus::FocusMode}{ContinuousFocus} and \l {QCameraFocus::FocusMode}{InfinityFocus}, whereas \l {QCameraFocus::FocusMode}{FocusPointMode} deals with the various focus zones within the view. \l {QCameraFocus::FocusMode}{FocusPointMode} has support for face recognition, center focus and a custom
+focus where the focus point can be specified.
+
+
+
+\section1 Cancelling Asynchronous Operations
+
+Various operations such as image capture and auto focusing occur
+asynchrously. These operations can often be cancelled by the start of a new
+operation as long as this is supported by the backend. For image capture,
+the operation can be cancelled by calling
+\l {QCameraImageCapture::cancelCapture()}{cancelCapture()}. For AutoFocus,
+autoexposure or white balance cancellation can be done by calling
+\i {QCamera::unlock(QCamera::LockFocus)}.
+
+
+
+\section1 Camera Controls
+
+ \table
+ \header
+ \o Control Name
+ \o Description
+ \row
+ \o camera
+ \o the interface for system camera devices
+ \row
+ \o exposure
+ \o Includes: flash mode; flash power; metering mode; aperture; shutter speed, iso setting
+ \row
+ \o focus
+ \o Includes: optical zoom; digital zoom; focus point; focus zones
+ \row
+ \o image processing
+ \o white balance; contrast; saturation; sharpen; denoise
+ \row
+ \o locks
+ \o handles the locking and unlocking of camera devices
+ \endtable
+
+
+\section1 Classes
+\annotatedlist camera
+
+
+*/
+
+
diff --git a/doc/src/classic.css b/doc/src/classic.css
new file mode 100644
index 000000000..b8cae8e1e
--- /dev/null
+++ b/doc/src/classic.css
@@ -0,0 +1,284 @@
+BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+ font-family: Arial, Geneva, Helvetica, sans-serif;
+}
+H1 {
+ text-align: center;
+ font-size: 160%;
+}
+H2 {
+ font-size: 120%;
+}
+H3 {
+ font-size: 100%;
+}
+
+h3.fn,span.fn
+{
+ background-color: #eee;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #ddd;
+ font-weight: bold;
+ padding: 6px 0px 6px 10px;
+ margin: 42px 0px 0px 0px;
+}
+
+hr {
+ border: 0;
+ color: #a0a0a0;
+ background-color: #ccc;
+ height: 1px;
+ width: 100%;
+ text-align: left;
+ margin: 34px 0px 34px 0px;
+}
+
+table.valuelist {
+ border-width: 1px 1px 1px 1px;
+ border-style: solid;
+ border-color: #dddddd;
+ border-collapse: collapse;
+ background-color: #f0f0f0;
+}
+
+table.indextable {
+ border-width: 1px 1px 1px 1px;
+ border-style: solid;
+ border-collapse: collapse;
+ background-color: #f0f0f0;
+ border-color:#555;
+ font-size: 100%;
+}
+
+table td.largeindex {
+ border-width: 1px 1px 1px 1px;
+ border-collapse: collapse;
+ background-color: #f0f0f0;
+ border-color:#555;
+ font-size: 120%;
+}
+
+table.valuelist th {
+ border-width: 1px 1px 1px 2px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #666;
+ color:white;
+ background-color:#666;
+}
+
+th.titleheader {
+ border-width: 1px 0px 1px 0px;
+ padding: 2px;
+ border-style: solid;
+ border-color: #666;
+ color:white;
+ background-color:#555;
+ background-image:url('images/gradient.png')};
+ background-repeat: repeat-x;
+ font-size: 100%;
+}
+
+
+th.largeheader {
+ border-width: 1px 0px 1px 0px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #444;
+ color:white;
+ background-color:#555555;
+ font-size: 120%;
+}
+
+p {
+
+ margin-left: 4px;
+ margin-top: 8px;
+ margin-bottom: 8px;
+}
+
+a:link
+{
+ color: #0046ad;
+ text-decoration: none
+}
+
+a:visited
+{
+ color: #672967;
+ text-decoration: none
+}
+
+a.obsolete
+{
+ color: #661100;
+ text-decoration: none
+}
+
+a.compat
+{
+ color: #661100;
+ text-decoration: none
+}
+
+a.obsolete:visited
+{
+ color: #995500;
+ text-decoration: none
+}
+
+a.compat:visited
+{
+ color: #995500;
+ text-decoration: none
+}
+
+body
+{
+ background: #ffffff;
+ color: black
+}
+
+table.generic, table.annotated
+{
+ border-width: 1px;
+ border-color:#bbb;
+ border-style:solid;
+ border-collapse:collapse;
+}
+
+table td.memItemLeft {
+ width: 180px;
+ padding: 2px 0px 0px 8px;
+ margin: 4px;
+ border-width: 1px;
+ border-color: #E0E0E0;
+ border-style: none;
+ font-size: 100%;
+ white-space: nowrap
+}
+
+table td.memItemRight {
+ padding: 2px 8px 0px 8px;
+ margin: 4px;
+ border-width: 1px;
+ border-color: #E0E0E0;
+ border-style: none;
+ font-size: 100%;
+}
+
+table tr.odd {
+ background: #f0f0f0;
+ color: black;
+}
+
+table tr.even {
+ background: #e4e4e4;
+ color: black;
+}
+
+table.annotated th {
+ padding: 3px;
+ text-align: left
+}
+
+table.annotated td {
+ padding: 3px;
+}
+
+table tr pre
+{
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 0px;
+ padding-right: 0px;
+ border: none;
+ background: none
+}
+
+tr.qt-style
+{
+ background: #96E066;
+ color: black
+}
+
+body pre
+{
+ padding: 0.2em;
+ border: #e7e7e7 1px solid;
+ background: #f1f1f1;
+ color: black
+}
+
+table tr.qt-code pre
+{
+ padding: 0.2em;
+ border: #e7e7e7 1px solid;
+ background: #f1f1f1;
+ color: black
+}
+
+span.preprocessor, span.preprocessor a
+{
+ color: darkblue;
+}
+
+span.comment
+{
+ color: darkred;
+ font-style: italic
+}
+
+span.string,span.char
+{
+ color: darkgreen;
+}
+
+.title
+{
+ text-align: center
+}
+
+.subtitle
+{
+ font-size: 0.8em
+}
+
+.small-subtitle
+{
+ font-size: 0.65em
+}
+
+.qmlitem {
+ padding: 0;
+}
+
+.qmlname {
+ white-space: nowrap;
+}
+
+.qmltype {
+ text-align: center;
+ font-size: 160%;
+}
+
+.qmlproto {
+ background-color: #eee;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #ddd;
+ font-weight: bold;
+ padding: 6px 10px 6px 10px;
+ margin: 42px 0px 0px 0px;
+}
+
+.qmlreadonly {
+ float: right;
+ color: red
+}
+
+.qmldoc {
+}
+
+*.qmlitem p {
+}
diff --git a/doc/src/examples/audiodevices.qdoc b/doc/src/examples/audiodevices.qdoc
new file mode 100644
index 000000000..e629c5bd1
--- /dev/null
+++ b/doc/src/examples/audiodevices.qdoc
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example audiodevices
+ \title Audio Devices Example
+
+
+
+ This example shows how to create a simple application to list and test
+ the configuration for the various audio devices available on the device
+ or machine. This is done using the QtMobility Multimedia API.
+
+ \image audiodevices.png
+
+*/
+
+
diff --git a/doc/src/examples/audiorecorder.qdoc b/doc/src/examples/audiorecorder.qdoc
new file mode 100644
index 000000000..cc518c927
--- /dev/null
+++ b/doc/src/examples/audiorecorder.qdoc
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example audiorecorder
+ \title Audio Recorder Example
+
+
+
+ This example shows how to create a simple audio recorder using the QtMobility
+ Multimedia API.
+
+ We can easily setup the capture when we create the objects using a
+ QMediaRecorder initialized with a QAudioCaptureSource object.
+
+ \snippet snippets/multimedia-snippets/audiorecorder.cpp create-objs-1
+
+ Then we set up the display of a list of available sources to use
+
+ \snippet snippets/multimedia-snippets/audiorecorder.cpp device-list
+
+ And available codecs
+
+ \snippet snippets/multimedia-snippets/audiorecorder.cpp codec-list
+
+ We display a dialog for the user to select the appropriate codec and the
+ input device to capture. Once selected we can use user interface objects
+ like buttons to start and stop the recording and display elapsed time.
+
+ \snippet snippets/multimedia-snippets/audiorecorder.cpp get-device
+
+ Then use signals to indicate a change to the output filename, the codec
+ and the audio source.
+
+ When the button to record is pushed the toggleRecord() slot will start
+ or stop the recording process using the \l{QMediaRecorder::record()}
+ and \l{QMediaRecorder::stop()} functions of the QMediaRecorder object.
+
+ \snippet snippets/multimedia-snippets/audiorecorder.cpp toggle-record
+
+
+*/
+
+
diff --git a/doc/src/examples/camera.qdoc b/doc/src/examples/camera.qdoc
new file mode 100644
index 000000000..dcf4dadfc
--- /dev/null
+++ b/doc/src/examples/camera.qdoc
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+
+/*!
+
+\example camera
+\title Camera Example
+\brief The Camera Example shows how to use the API to capture a still image
+or video.
+
+
+
+The Camera Example demonstrates how you can use the QtMultimediaKit to implement
+some basic Camera functionality to take still images and record video clips
+with audio.
+
+A Camera class is created that will act as our Camera. It has a user interface,
+control functions, setting values and a means of defining the location where
+the image or video clip is to be saved. It will also store the image and video
+settings.
+
+The Camera class contains an instance of \l {QCamera}, the API class interface to
+the hardware. It also has an instance of \l {QCameraImageCapture} to take still images
+and an instance of \l {QMediaRecorder} to record video. It also contains the user
+interface object.
+
+The Camera constructor does some basic initialization. The camera object is
+set to '0', the user interface is initialized and UI signal are connected to
+slots that react to the triggering event. However, most of the work is done when
+the \i {setCamera()} function is called, passing in a \l {QByteArray}.
+
+\i {setCamera()} sets up various connections between the user interface and the functionality
+of the Camera class using signals and slots. It also instantiates and initializes the \l {QCamera},
+\l {QCameraImageCapture} and \l {QMediaRecorder} objects mentioned above. The still
+and video recording visual tabs are enabled and finally the
+\l {QCamera::start()}{start()} function of the \l{QCamera} object is called.
+
+Now that the camera is ready for user commands it waits for a suitable event.
+Such an event will be the key press of either the \l {Qt::Key_CameraFocus} or
+\l {Qt::Key_Camera} buttons on the application window. Camera focus will
+simply display the viewfinder and lock the camera settings. Key_Camera will
+either call \i {takeImage()} if the \l {QCamera::captureMode()}{captureMode()}
+is QCamera::CaptureStillImage, or if the capture mode is for video then one
+of two actions will occur. If the recording state shows that we are currently
+recording then the \i {stop()} function is called resulting in a call to
+\l {QCamera::stop()}, whereas if we are not recording then a video recording
+is started with a call to \l {QMediaRecorder::record()}.
+
+\image camera-example.png
+
+*/
+
+
diff --git a/doc/src/examples/declarative-camera.qdoc b/doc/src/examples/declarative-camera.qdoc
new file mode 100644
index 000000000..b37e656f3
--- /dev/null
+++ b/doc/src/examples/declarative-camera.qdoc
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\example declarative-camera
+\title QML Camera Example
+
+\brief The Camera Example shows how to use the API to capture a still image
+or video.
+
+\image qml-camera.png
+
+This example demonstrates the basic use of the Camera QML Plugin elements. The
+plugin provides access to the API functionality for camera settings and
+capturing an image.
+
+Most of the QML code supports the user interface for this application with the
+Camera elements being mostly found in \i {declarative-camera.qml} and
+\i {CaptureControls.qml}.
+
+In \i {declarative-camera.qml} the Camera element is initialized with an id
+of \i {camera }, a photo preview is setup, states are implemented for image
+preview or capture and a CaptureControls element is initialized. The initial
+\i state is \i PhotoCapture. The camera element includes a handler, \i onImageCaptured,
+for the \l {imageCaptured} signal. The handler sets up the application to process
+the preview including a change in the user interface state. The PhotoPreview
+element now becomes visible with any key press being picked up by the handler
+in PhotoPreview and returning the state to \i PhotoCapture.
+
+The \i CaptureControls element, which is implemented in \i {CaptureControls.qml},
+generates a column on the right hand side of the screen which includes control
+buttons for \i focus (not initially visible), \i {capture}, \i {flash modes},
+\i {white balance}, \i {exposure compensation}, and if a preview is
+available a \i {preview} button. The last button exits from the application.
+
+When the Capture button is pressed the \i onClicked handler calls
+\l {Camera::captureImage()}{captureImage()}
+
+
+
+
+
+
+
+*/
diff --git a/doc/src/examples/hapticsplayer.qdoc b/doc/src/examples/hapticsplayer.qdoc
new file mode 100644
index 000000000..e3743ba6f
--- /dev/null
+++ b/doc/src/examples/hapticsplayer.qdoc
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example hapticsplayer
+ \title Haptics Player
+
+ \tableofcontents
+
+ \section1 Overview
+
+ This example shows how to use various haptic effects in an application via
+ the \l{Feedback}{QtMobility Feedback API}.
+
+ It provides an example of how to use the QtMobility libraries to:
+ \list
+ \o play "system theme" haptic effects corresponding to certain predefined events
+ \o play a dynamic custom effect, single or repeating
+ \o play a custom effect which is stored in a file
+ \endlist
+
+ \section2 Use Case
+
+ This example is more feature complete than the \l{hapticsquare}{Haptic Square} example,
+ but is intended more as a way to test the haptics provider plugins which
+ are available on a system, than as an example for application developers.
+
+ It is useful for people who wish to learn how to use the API to create and
+ play custom effects dynamically, or to allow users of an application to
+ select which haptic effect to play when a particular event occurs. It is also useful
+ to test how effects are implemented on specific devices.
+
+ It is a more complex example than the \l{hapticsquare}{Haptic Square} example, so it is
+ suggested that developers look at that example first.
+
+ \section2 Interface
+ The application is designed to work on desktop and mobile platforms with
+ minimal differences in code between the platforms. The interface consists
+ of three tabs which allow the user to select and play different custom,
+ system theme, and file effects, respectively. The custom effect tab also
+ allows the user to modify the custom effect dynamically, and see the effect
+ of attack and fade, intensity and duration, and periodicity, on the user
+ experience.
+
+ \section2 Known Issues
+ The example will not work correctly on platforms which do not have a
+ QFeedbackHapticInterface (haptic effect provider) plugin loaded. On such
+ platforms, the example will do nothing.
+*/
diff --git a/doc/src/examples/player.qdoc b/doc/src/examples/player.qdoc
new file mode 100644
index 000000000..8aad56f25
--- /dev/null
+++ b/doc/src/examples/player.qdoc
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example player
+ \title Media Player Example
+
+
+ This example creates a simple multimedia player. We can play audio and
+ or video files using various codecs.
+
+ The example uses a QMediaPlayer object passed into a QVideoWidget to
+ control the video output. To give the application playlist capability
+ we also use a QPlayList object.
+
+ To activate the various functions such as play and stop on the dialog
+ we connect clicked() signals to slots that emit the play() and stop()
+ signals and in turn which we connect to the play() and stop() slots in
+ QMediaPlayer.
+
+ \code
+ connect(controls, SIGNAL(play()), player, SLOT(play()));
+ connect(controls, SIGNAL(pause()), player, SLOT(pause()));
+ connect(controls, SIGNAL(stop()), player, SLOT(stop()));
+ \endcode
+
+ We can get the volume (and set our user interface representation)
+
+ \code
+ controls->setVolume(player->volume());
+ \endcode
+
+ and we can make widget 'volume' changes change the volume
+
+ \code
+ connect(controls, SIGNAL(changeVolume(int)), player, SLOT(setVolume(int)));
+ \endcode
+
+ The example also allows us to change various video properties by means
+ of the QVideoWidget object. We can go to Full Screen mode with a single
+ button click, and back again. Or if we press the "Color Options" dialog
+ button we can have access to more subtle influences. The dialog has a
+ set of sliders so that we can change the brightness, contrast, hue and
+ saturation of the video being watched. The connect() statements are in
+ pairs so that changes to either the user interface widget (the relevant
+ slider) or the QVideoWidget object will update the other object.
+
+ \code
+ connect(brightnessSlider, SIGNAL(sliderMoved(int)), videoWidget,
+ SLOT(setBrightness(int)));
+ connect(videoWidget, SIGNAL(brightnessChanged(int)),
+ brightnessSlider, SLOT(setValue(int)));
+
+ connect(contrastSlider, SIGNAL(sliderMoved(int)), videoWidget,
+ SLOT(setContrast(int)));
+ connect(videoWidget, SIGNAL(contrastChanged(int)), contrastSlider,
+ SLOT(setValue(int)));
+
+ connect(hueSlider, SIGNAL(sliderMoved(int)), videoWidget,
+ SLOT(setHue(int)));
+ connect(videoWidget, SIGNAL(hueChanged(int)), hueSlider,
+ SLOT(setValue(int)));
+
+ connect(saturationSlider, SIGNAL(sliderMoved(int)), videoWidget,
+ SLOT(setSaturation(int)));
+ connect(videoWidget, SIGNAL(saturationChanged(int)),
+ saturationSlider, SLOT(setValue(int)));
+ \endcode
+
+*/
+
diff --git a/doc/src/examples/slideshow.qdoc b/doc/src/examples/slideshow.qdoc
new file mode 100644
index 000000000..6537e59e0
--- /dev/null
+++ b/doc/src/examples/slideshow.qdoc
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example slideshow
+ \title SlideShow Example
+
+
+ \image slideshow-img1.png
+
+
+ Slideshow displays a series of time delayed images after you select a
+ source image directory to use. The folder button presents a list of three
+ options: browse for a directory, load a playlist or enter a location.
+
+ This implementation uses a QMediaImageViewer object for the image with
+ a QVideoWidget used to do the display. Whether the the source is a
+ browsed directory, a playlist file or a URL to a local or remote
+ location the playlist object in Slideshow is updated with the file or
+ multiple file locations.
+
+ \code
+ connect(imageViewer, SIGNAL(stateChanged(QMediaImageViewer::State)),
+ this, SLOT(stateChanged(QMediaImageViewer::State)));
+
+ playlist = new QMediaPlaylist;
+ playlist->setMediaObject(imageViewer);
+ \endcode
+
+ We create a QVideoWidget to display the viewer and add it to the dialog.
+
+ \code
+ QVideoWidget *videoWidget = new QVideoWidget;
+ videoWidget->setMediaObject(imageViewer);
+ \endcode
+
+
+ \code
+ layout->addWidget(videoWidget, Qt::AlignCenter);
+ \endcode
+
+
+ The timeout between images is set by changing the timeout property in
+ QMediaImageViewer which is in milliseconds. So to change the timeout
+ to five seconds
+ \code
+ imageViewer->setTimeout( 5000 );
+ \endcode
+
+
+*/
diff --git a/doc/src/images/annotatedurl.png b/doc/src/images/annotatedurl.png
new file mode 100644
index 000000000..38d86fb49
--- /dev/null
+++ b/doc/src/images/annotatedurl.png
Binary files differ
diff --git a/doc/src/images/audiodevices.png b/doc/src/images/audiodevices.png
new file mode 100644
index 000000000..419b40f48
--- /dev/null
+++ b/doc/src/images/audiodevices.png
Binary files differ
diff --git a/doc/src/images/camera-example.png b/doc/src/images/camera-example.png
new file mode 100644
index 000000000..12e1b5728
--- /dev/null
+++ b/doc/src/images/camera-example.png
Binary files differ
diff --git a/doc/src/images/codeless.png b/doc/src/images/codeless.png
new file mode 100644
index 000000000..390102264
--- /dev/null
+++ b/doc/src/images/codeless.png
Binary files differ
diff --git a/doc/src/images/qml-camera.png b/doc/src/images/qml-camera.png
new file mode 100644
index 000000000..0cd61f0a0
--- /dev/null
+++ b/doc/src/images/qml-camera.png
Binary files differ
diff --git a/doc/src/images/slideshow-img1.png b/doc/src/images/slideshow-img1.png
new file mode 100644
index 000000000..72255d643
--- /dev/null
+++ b/doc/src/images/slideshow-img1.png
Binary files differ
diff --git a/doc/src/legal/3rdparty.qdoc b/doc/src/legal/3rdparty.qdoc
new file mode 100644
index 000000000..bf161d71a
--- /dev/null
+++ b/doc/src/legal/3rdparty.qdoc
@@ -0,0 +1,300 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE: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$
+**
+****************************************************************************/
+
+/*!
+ \page 3rdparty.html
+
+ \title Third-Party Licenses Used in Qt
+ \ingroup licensing
+ \brief License information for third-party libraries supplied with Qt.
+
+ Qt includes a number of third-party libraries that are used to provide
+ certain features. Unlike the code described in the
+ \l{Other Licenses Used in Qt}{code used in Qt} document, these
+ libraries are supplied alongside the Qt modules.
+
+ Third Party Software may impose additional restrictions and it is the
+ user's responsibility to ensure that they have met the licensing
+ requirements of the GPL, LGPL, or Qt Commercial license and the relevant
+ license of the Third Party Software they are using.
+
+ Run \c{configure -help} to see any options that may be available for
+ controlling the use of these libraries.
+
+ \tableofcontents
+
+ \section1 DES (\c des.cpp)
+
+ \i{Implementation of DES encryption for NTLM\br
+ Copyright 1997-2005 Simon Tatham.\br
+ This software is released under the MIT license.}
+
+ See \c src/3rdparty/des/des.cpp for more information about the terms and
+ conditions under which the code is supplied.
+
+ \section1 FreeType 2 (\c freetype) version 2.3.6
+
+ \i{The FreeType project is a team of volunteers who develop free, portable
+ and high-quality software solutions for digital typography. We specifically
+ target embedded systems and focus on bringing small, efficient and
+ ubiquitous products.} -- quoted from \c 3rdparty/freetype/docs/freetype2.html.
+
+ See \c src/3rdparty/freetype/docs/FTL.txt and \c
+ src/3rdparty/freetype/docs/GPL.txt for license details.
+
+ See also the files in \c src/3rdparty/harfbuzz, which are used by
+ FreeType.
+
+ Parts of the FreeType projects have been modified and put into Qt
+ for use in the painting subsystem. These files are ftraster.h,
+ ftraster.c, ftgrays.h and ftgrays.c. The following modifications
+ has been made to these files:
+
+ \list
+ \o Renamed FT_ and ft_ symbols to QT_FT_ and qt_ft_ to avoid name
+ conflicts.
+ \o Removed parts of code not relevant when compiled with
+ _STANDALONE_ defined.
+ \o Changed behavior in ftraster.c to follow X polygon filling
+ rules.
+ \o Implemented support in ftraster.c for winding / odd even
+ polygon fill rules.
+ \o Replaced bitmap generation with span generation in ftraster.c
+ \o Renamed: ftraster.h to qblackraster_p.h
+ \o Renamed: ftraster.c to qblackraster.c
+ \o Renamed: ftgrays.h to qgrayraster_p.h
+ \o Renamed: ftgrays.c to qgrayraster.c
+ \endlist
+
+ \section1 HarfBuzz (\c harfbuzz)
+
+ \i{This is HarfBuzz, an OpenType Layout engine.}
+
+ \i{It was derived originally from the OpenType code in FreeType-1.x, ported to
+ FreeType2. (This code has been abandoned for FreeType2, but until something
+ better comes along, should serve our purposes.) In addition to porting to
+ FreeType-2, it has been modified in various other ways.} -- quoted from
+ \c src/3rdparty/harfbuzz/README.
+
+ See \c src/3rdparty/harfbuzz/COPYING.FTL and src/3rdparty/harfbuzz/COPYING.GPL
+ for license details.
+
+ \section1 The Independent JPEG Group's JPEG Software (\c libjpeg) version 6b
+
+ \i{This package contains C software to implement JPEG image compression and
+ decompression. JPEG (pronounced "jay-peg") is a standardized compression
+ method for full-color and gray-scale images. JPEG is intended for compressing
+ "real-world" scenes; line drawings, cartoons and other non-realistic images
+ are not its strong suit. JPEG is lossy, meaning that the output image is not
+ exactly identical to the input image.} -- quoted from \c
+ src/3rdparty/libjpeg/README.
+
+ See \c src/3rdparty/libjpeg/README for license details.
+
+ \section1 MD4 (\c md4.cpp and \c md4.h)
+
+ \i{MD4 (RFC-1320) message digest.\br
+ Modified from MD5 code by Andrey Panin <pazke@donpac.ru>\br\br
+ Written by Solar Designer <solar@openwall.com> in 2001, and placed in\br
+ the public domain. There's absolutely no warranty.}
+
+ See \c src/3rdparty/md4/md4.cpp and \c src/3rdparty/md4/md4.h for more
+ information about the terms and conditions under which the code is
+ supplied.
+
+ \section1 MD5 (\c md5.cpp and \c md5.h)
+
+ \i{This code implements the MD5 message-digest algorithm.
+ The algorithm is due to Ron Rivest. This code was
+ written by Colin Plumb in 1993, no copyright is claimed.
+ This code is in the public domain; do with it what you wish.} -- quoted from
+ \c src/3rdparty/md5/md5.h
+
+ See \c src/3rdparty/md5/md5.cpp and \c src/3rdparty/md5/md5.h for more
+ information about the terms and conditions under which the code is
+ supplied.
+
+ \section1 MNG Library (\c libmng) version 1.0.10
+
+ \i{The libmng library supports decoding, displaying, encoding, and various
+ other manipulations of the Multiple-image Network Graphics (MNG) format
+ image files. It uses the zlib compression library, and optionally the
+ JPEG library by the Independant JPEG Group (IJG) and/or
+ lcms (little cms), a color-management library by Marti Maria Saguer.}
+ -- quoted from \c src/3rdparty/libmng/doc/libmng.txt
+
+ See \c src/3rdparty/libmng/LICENSE for license details.
+
+ \section1 PNG Reference Library (\c libpng) version 1.2.29
+
+ \i{Libpng was written as a companion to the PNG specification, as a way
+ of reducing the amount of time and effort it takes to support the PNG
+ file format in application programs.} -- quoted from \c
+ src/3rdparty/libpng/libpng.txt.
+
+ See \c src/3rdparty/libpng/LICENSE for license details.
+
+ \section1 The ptmalloc memory allocator (\c ptmalloc3) version 1.8
+
+ \i ptmcalloc3 is a scalable concurrent memory allocator suitable
+ for use in multi-threaded programs.
+
+ \hr
+
+ Copyright (c) 2001-2006 Wolfram Gloger
+
+ Permission to use, copy, modify, distribute, and sell this software
+ and its documentation for any purpose is hereby granted without fee,
+ provided that (i) the above copyright notices and this permission
+ notice appear in all copies of the software and related documentation,
+ and (ii) the name of Wolfram Gloger may not be used in any advertising
+ or publicity relating to the software.
+
+ THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+ IN NO EVENT SHALL WOLFRAM GLOGER BE LIABLE FOR ANY SPECIAL,
+ INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
+ DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY
+ OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ PERFORMANCE OF THIS SOFTWARE.
+
+ \hr
+
+ See \c src/3rdparty/ptmalloc/COPYRIGHT for license details.
+
+ \section1 SHA-1 (\c sha1.cpp)
+
+ \i{Based on the public domain implementation of the SHA-1 algorithm\br
+ Copyright (C) Dominik Reichl <dominik.reichl@t-online.de>}
+
+ See \c src/3rdparty/sha1/sha1.cpp for more information about the terms and
+ conditions under which the code is supplied.
+
+ \section1 SQLite (\c sqlite) version 3.5.9
+
+ \i{SQLite is a small C library that implements a
+ self-contained, embeddable, zero-configuration SQL database engine.}
+ -- quoted from \l{http://www.sqlite.org/}{www.sqlite.org}.
+
+ According to the comments in the source files, the code is in the public
+ domain. See the
+ \l{http://www.sqlite.org/copyright.html}{SQLite Copyright} page on the
+ SQLite web site for further information.
+
+ \section1 TIFF Software Distribution (\c libtiff) version 3.8.2
+
+ \i {libtiff is a set of C functions (a library) that support the
+ manipulation of TIFF image files.} -- quoted from \c
+ src/libtiff/html/libtiff.html
+
+ \hr
+
+ Copyright (c) 1988-1997 Sam Leffler\br
+ Copyright (c) 1991-1997 Silicon Graphics, Inc.\br
+ Copyright (C) 2004, Andrey Kiselev <dron@ak4719.spb.edu>\br
+ Copyright (c) 1997 Greg Ward Larson
+
+ Permission to use, copy, modify, distribute, and sell this software and
+ its documentation for any purpose is hereby granted without fee, provided
+ that (i) the above copyright notices and this permission notice appear in
+ all copies of the software and related documentation, and (ii) the names of
+ Sam Leffler and Silicon Graphics may not be used in any advertising or
+ publicity relating to the software without the specific, prior written
+ permission of Sam Leffler and Silicon Graphics.
+
+ THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+ IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ OF THIS SOFTWARE.
+
+ \hr
+
+ Copyright (c) 1996-1997 Sam Leffler\br
+ Copyright (c) 1996 Pixar
+
+ Permission to use, copy, modify, distribute, and sell this software and
+ its documentation for any purpose is hereby granted without fee, provided
+ that (i) the above copyright notices and this permission notice appear in
+ all copies of the software and related documentation, and (ii) the names of
+ Pixar, Sam Leffler and Silicon Graphics may not be used in any advertising or
+ publicity relating to the software without the specific, prior written
+ permission of Pixar, Sam Leffler and Silicon Graphics.
+
+ THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+ IN NO EVENT SHALL PIXAR, SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ OF THIS SOFTWARE.
+
+ \hr
+
+ See \c src/3rdparty/libtiff/COPYRIGHT for license details.
+
+ \section1 Wintab API (\c wintab)
+
+ Wintab is a de facto API for pointing devices on Windows. The
+ wintab code is from \l{http://www.pointing.com/WINTAB.HTM}.
+
+ See \c src/3rdparty/wintab/wintab.h for license details.
+
+ \section1 Data Compression Library (\c zlib) version 1.2.3
+
+ \i{zlib is a general purpose data compression library. All the code
+ is thread safe. The data format used by the zlib library is described
+ by RFCs (Request for Comments) 1950 to 1952} -- quoted from \c
+ src/3rdparty/zlib/README.
+
+ See \c src/3rdparty/zlib/README for license details.
+*/
diff --git a/doc/src/legal/editions.qdoc b/doc/src/legal/editions.qdoc
new file mode 100644
index 000000000..9fe3a6c02
--- /dev/null
+++ b/doc/src/legal/editions.qdoc
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE: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$
+**
+****************************************************************************/
+
+/*!
+ \page editions.html
+ \title Qt Editions
+ \ingroup licensing
+ \brief Information about the different editions of Qt.
+
+ Qt can be used to create both commercial and non-commercial
+ software for a wide range of different deployment environments,
+ and is supplied in a number of different forms to suit the needs
+ of different kinds of developers.
+
+ In terms of license conditions, there are two main forms of Qt:
+
+ \list
+ \o The \l{Qt Commercial Edition} are the commercial
+ versions of \l{About Qt}{Qt}.
+ \o The \l{Open Source Versions of Qt} are freely available for download.
+ \endlist
+
+ On the Qt web site, you can find a
+ \l{Qt Licensing Overview} and information on \l{Qt License Pricing}
+ for commercial editions of Qt and other Qt-related products.
+*/
diff --git a/doc/src/legal/gpl.qdoc b/doc/src/legal/gpl.qdoc
new file mode 100644
index 000000000..58967b778
--- /dev/null
+++ b/doc/src/legal/gpl.qdoc
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE: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$
+**
+****************************************************************************/
+
+/*! \page lgpl.html
+\title GNU Lesser General Public License (LGPL)
+\ingroup licensing
+\brief About the LGPL license used for Qt.
+
+The Qt GUI Toolkit is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).\br
+Contact: Nokia Corporation (qt-info@nokia.com)
+
+Qt is available under the LGPL.
+
+\section1 The GNU Lesser General Public License (Version 2.1)
+
+Reference: \l{GNU Lesser General Public License, version 2.1}
+
+\snippet doc/src/snippets/code/doc_src_lgpl.qdoc LGPL v2.1
+
+\section1 Nokia Qt LGPL Exception version 1.0
+
+As a special exception to the GNU Lesser General Public License version 2.1,
+the object code form of a "work that uses the Library" may incorporate material
+from a header file that is part of the Library. You may distribute such object
+code under terms of your choice, provided that the incorporated material
+(i) does not exceed more than 5% of the total size of the Library; and
+(ii) is limited to numerical parameters, data structure layouts, accessors,
+macros, inline functions and templates.
+*/
diff --git a/doc/src/legal/opensourceedition.qdoc b/doc/src/legal/opensourceedition.qdoc
new file mode 100644
index 000000000..c199e34ce
--- /dev/null
+++ b/doc/src/legal/opensourceedition.qdoc
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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$
+**
+****************************************************************************/
+
+/*!
+ \page opensourceedition.html
+
+ \title Open Source Versions of Qt
+ \ingroup licensing
+ \brief Information about the license and features of the Open Source Edition.
+
+ Free (or open source) software is software that comes with a license
+ that gives users certain rights. In particular the right to use the
+ software, to modify it, to obtain its source, and to pass it on (under
+ the same terms). Notice that the term "free" is about rights, not
+ money. The Free Software Foundation (creators of the GNU GPL) speaks
+ of free in this context as in "free speech", not as in "no cost".
+
+ Nokia supports the free software concept by providing the Qt Open Source
+ Edition, which is licensed under the \l{GNU General Public License (GPL)}
+ (version 3) and the \l{GNU Lesser General Public License (LGPL)} (version 2.1).
+ You can use this edition of Qt to create and distribute software with licenses
+ that are compatible to these free software licenses.
+
+ The support of open source with the Open Source Versions of Qt has enabled large
+ successful software projects like KDE to thrive, with thousands of developers
+ around the world using open source versions of Qt at no cost to themselves. With
+ the release of Qt 4, open source versions of Qt became available for Unix/X11,
+ Mac OS X, and Windows platforms.
+
+ The Open Source Edition can be downloaded from the \l{Downloads}{Qt website}.
+
+ Please refer to the online \l{License FAQ} for answers to frequently asked
+ questions on open source licensing and its implications.
+
+ More information on Free and Open Source software is available online:
+
+ \list
+ \o GNU GPL: \l http://www.gnu.org/.
+ \o Open Source licensing: \l http://www.opensource.org/.
+ \endlist
+
+ See \l{Licensing Information} for a collection of documents about licenses
+ used in Qt.
+
+ Information about Qt Commercial License Agreements is available
+ in the \l{Qt Licensing Overview} on the Qt website or by contacting
+ the sales department at http://qt.nokia.com/contact.
+
+ If you are in doubt what edition of Qt is right for your project,
+ please contact
+ \l{mailto:qt-info@nokia.com}{qt-info@nokia.com}.
+
+*/
diff --git a/doc/src/legal/trademarks.qdoc b/doc/src/legal/trademarks.qdoc
new file mode 100644
index 000000000..f1a6cdaca
--- /dev/null
+++ b/doc/src/legal/trademarks.qdoc
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE: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$
+**
+****************************************************************************/
+
+/*!
+ \page trademarks.html
+
+ \title Trademarks
+ \ingroup licensing
+ \brief Information about trademarks owned by Nokia and other organisations.
+
+ Nokia, the Nokia logo, Qt, and the Qt logo are trademarks of Nokia \reg
+ Corporation and/or its subsidiaries in Finland and other countries.
+
+ \list
+ \o Intel, Intel Inside (logos), MMX and Pentium are \reg trademarks of
+ Intel Corporation in the United States, other countries, or both.
+ \o Java and all Java-based trademarks are trademarks of Sun Microsystems,
+ Inc. in the United States, other countries, or both.
+ \o Linux is a \reg trademark of Linus Torvalds in the United States, other
+ countries or both.
+ \o Mac, Mac OS and Macintosh are \reg trademarks of Apple Computer, Inc.,
+ registered in the U.S. and other countries.
+ \o Microsoft, Windows, Windows NT, XP, Visual Studio and the Windows logo
+ are \reg trademarks of Microsoft Corporation in the United States, other
+ countries, or both.
+ \o Motif is a registered trademark of The Open Group in the United States,
+ other countries, or both.
+ \o OpenGL is a \reg trademark of Silicon Graphics, Inc. in the United States
+ and other countries.
+ \o UNIX is a registered trademark of The Open Group in the United States
+ and other countries.
+ \o Versit is a \reg trademark of the Internet Mail Consortium in the United States
+ and other countries.
+ \o All other company, product, or service names may be trademarks or
+ service marks of others and are the property of their respective owners.
+ The use of the word partner does not imply a partnership relationship
+ between Nokia and any other company.
+ \endlist
+*/
diff --git a/doc/src/multimedia.qdoc b/doc/src/multimedia.qdoc
new file mode 100644
index 000000000..25c42f5fe
--- /dev/null
+++ b/doc/src/multimedia.qdoc
@@ -0,0 +1,470 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+/*!
+ \group multimedia
+ \title QtMobility Multimedia
+ APIs to play and record media, and manage a collection of media content.
+*/
+
+// XXX title sucks
+// XXX move backend stuff away
+// XXX move QML stuff up
+// XXX more introductory material
+// XXX terminology
+// XXX separate pages for audio, video, camera, radio, metadata
+// control, mediaobject etc stuff
+// symbian/harmattan specific pages
+
+/*!
+
+\page multimedia.html
+\title Multimedia
+\brief Provides a set of APIs to play and record media, and manage a
+collection of media content.
+\ingroup mobility
+
+Multimedia provides a set of APIs that allow the developer to play, record
+and manage a collection of media content. It is dependent on the
+QtMultimediaKit module. QtMultimediaKit is the recommended API to build multimedia
+applications using Qt. The Phonon API is no longer recommended.
+
+\tableofcontents
+
+\section1 No Special Namespace
+
+Unlike the other APIs in QtMobility, the Multimedia API is \i not in the
+\i QtMobility namespace.
+
+\section1 Overview
+
+This API delivers an easy to use interface to multimedia functions. The
+developer can use the API to display an image, or a video, record sound or play a
+multimedia stream.
+
+There are several benefits this API brings to Qt. Firstly, the
+developer can now implement fundamental multimedia functions with minimal
+code, mostly because they are already implemented. Also there is a great
+deal of flexibility with the media source or the generated multimedia. The
+source file does not need to be local to the device, it could be streamed
+from a remote location and identified by a URL. Finally, many different
+codecs are supported 'out
+of the box'.
+
+The supplied \l {qtmultimediakit examples}{examples} give a good idea at the ease of use of the API. When
+the supporting user interface code is ignored we can see that functionality
+is immediately available with minimal effort.
+
+\section2 Audio
+
+The Audio Recorder example is a good introduction to the basic use of the API. We will use snippets from this example to illustrate how to use the
+API to quickly build functionality.
+
+The first step is to demonstrate recording audio to a file. When recording from an audio source there are a number of things we may want to control beyond the essential user interface. We may want a particular encoding of the file, MP3 or Ogg Vorbis for instance, or select a different input source. The user may modify the bitrate, number of channels, quality and sample rate. Here the example will only modify the codec and the source device, since they are essential.
+
+To begin, the developer sets up a source and a recorder object. A
+\l{QAudioCaptureSource} object is created and used to initialize a \l{QMediaRecorder} object. The output file name is then set for the \l{QMediaRecorder} object.
+
+\code
+ audiosource = new QAudioCaptureSource;
+ capture = new QMediaRecorder(audiosource);
+
+ capture->setOutputLocation(QUrl("test.raw"));
+\endcode
+
+A list of devices is needed so that an input can be selected in the user interface
+
+\code
+ for(int i = 0; i < audiosource->deviceCount(); i++)
+ deviceBox->addItem(audiosource->name(i));
+\endcode
+
+and a list of the supported codecs for the user to select a codec,
+
+\code
+ QStringList codecs = capture->supportedAudioCodecs();
+ for(int i = 0; i < codecs.count(); i++)
+ codecsBox->addItem(codecs.at(i));
+\endcode
+
+To set the selected device or codec just use the index of the device or codec by calling the setter in \i {audiosource} or \i {capture} as appropriate, for example,
+
+\code
+ audiosource->setSelectedDevice(i);
+ ...
+ capture->setAudioCodec(codecIdx);
+\endcode
+
+Now start recording by using the \l {QMediaRecorder}{record()} function from the new \l{QMediaRecorder} object
+
+\code
+ capture->record();
+\endcode
+
+And stop recording by calling the matching function \l {QMediaRecorder::stop()}{stop()} in \l{QMediaRecorder}.
+
+\code
+ capture->stop();
+\endcode
+
+How then would this audio file be played? The \l {QMediaPlayer} class will be
+used as a generic player. Since the player can play both video and audio files the interface will be more complex, but for now the example will concentrate on the audio aspect.
+
+Playing the file is simple: create a player object, pass in the filename, set
+the volume or other parameters, then play. Not forgetting that the code will
+need to be hooked up to the user interface.
+
+\code
+ QMediaPlayer *player = new QMediaPlayer;
+ ...
+ player->setMedia(QUrl::fromLocalFile("test.raw"));
+ player->setVolume(50);
+ player->play();
+\endcode
+
+The filename does not have to be a local file. It could be a URL to a
+remote resource. Also by using the \l{QMediaPlaylist} class from this API
+we can play a list of local or remote files. The \l{QMediaPlaylist}
+class supports constructing, managing and playing playlists.
+
+\code
+ player = new QMediaPlayer;
+
+ playlist = new QMediaPlaylist(player);
+ playlist->addMedia(QUrl("http://example.com/myfile1.mp3"));
+ playlist->addMedia(QUrl("http://example.com/myfile2.mp3"));
+ ...
+ playlist->setCurrentPosition(1);
+ player->play();
+\endcode
+
+To manipulate the playlist there are the usual management functions (which are in fact slots): previous, next, setCurrentPosition and shuffle. Playlists can be built, saved and loaded using the API.
+
+
+
+\section2 Video
+
+Continuing with the example discussed for an Audio recorder/player, we can use this to show how to play video files with little change to the code.
+
+Moving from audio to video requires few changes in the sample code. To play a
+video playlist the code can be changed to include another new QtMobility
+Project class: \l{QVideoWidget}. This class enables control of a video
+resource with signals and slots for the control of brightness, contrast,
+hue, saturation and full screen mode.
+
+\code
+ player = new QMediaPlayer;
+
+ playlist = new QMediaPlaylist(player);
+ playlist->addMedia(QUrl("http://example.com/myclip1.mp4"));
+ playlist->addMedia(QUrl("http://example.com/myclip2.mp4"));
+ ...
+ widget = new QVideoWidget(player);
+ widget->show();
+
+ playlist->setCurrentPosition(1);
+ player->play();
+\endcode
+
+The \l {player}{Player} example does things a bit differently to our sample
+code. Instead of using a QVideoWidget object directly, the Player example
+has a \i {VideoWidget} class that inherits from QVideoWidget. This means
+that functions can be added to provide functions such as full screen display,
+either on a double click or on a particular keypress.
+
+\snippet ../../demos/player/player.cpp 2
+
+
+\section2 Radio
+
+QRadioTunerControl is a pure virtual base class that will be the basis for
+any platform specific radio device control. When the functions are
+implemented the developer will be able to quickly produce an application
+that supports the typical uses of an FM radio including tuning, volume,
+start, stop and various other controls.
+
+\section1 Extending the API for Symbian and Maemo
+
+
+For the developer who wishes to extend the functionality of the Multimedia
+classes there are several classes of particular importance. The default
+classes are QMediaService, QMediaServiceProvider and QMediaControl.
+
+Basically, the idea is that to use the Multimedia API you would use these
+three classes or classes derived from them as follows
+
+ \list
+ \o \l QMediaServiceProvider is used by the top level client class to request a service. The top level class knowing what kind of service it needs.
+
+ \o \l QMediaService provides a service and when asked by the top level object, say a component, will return a QMediaControl object.
+
+ \o \l QMediaControl allows the control of the service using a known interface.
+ \endlist
+
+Consider a developer creating, for example, a media player class called MyPlayer.
+It may have special requirements beyond ordinary media players and so may
+need a custom service and a custom control. We can subclass \l QMediaServiceProvider
+to create our MyServiceProvider class. Also we will create a
+MyMediaService, and the MyMediaControl to manipulate the media service.
+
+The MyPlayer object calls MyServiceProvider::requestService() to get an
+instance of MyMediaService. Then the MyPlayer object calls this service
+object it has just received and calling \l {QMediaService::requestControl()}{requestControl()}
+it will receive the control object derived from QMediaControl. Now we have
+all the parts necessary for our media application. We have the service
+provider, the service it provides and the control used to manipulate the
+service. Since our MyPlayer object has instances of the service and its
+control then it would be possible for these to be used by associated classes
+that could do additional actions, perhaps with their own control since the
+parameter to requestControl() is a c-type string, \i {const char *}, for the
+interface.
+
+
+\section2 Adding a Media Service Provider
+
+The base class for creating new service providers is \l{QMediaServiceProvider}.
+The user must implement the \l{QMediaServiceProvider::requestService()}{requestService()}
+function
+
+\code
+ QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &hint);
+\endcode
+
+The details of implementation will depend on the provider. Looking at the
+class \l QMediaServiceProvider for the default implementation. Notice that
+\l {QMediaServiceProvider::requestService()}{requestService()} uses the
+\l QMediaServiceProviderHint to look for the appropriate plugin and then to
+insert it into the plugin map. However, for a specific service provider there
+is probably no need for this approach, it will simply depend on what the
+developer wants to implement.
+
+Other methods that may be overloaded
+\code
+ void releaseService(QMediaService *service);
+
+ QtMediaServices::SupportEstimate hasSupport(const QByteArray &serviceType,
+ const QString &mimeType,
+ const QStringList& codecs,
+ int flags) const;
+
+ QStringList supportedMimeTypes(const QByteArray &serviceType, int flags) const;
+
+ QList<QByteArray> devices(const QByteArray &serviceType) const;
+
+ QString deviceDescription(const QByteArray &serviceType, const QByteArray &device);
+\endcode
+
+The choice of what needs to be done depends on what the developer wishes to do with the service.
+
+
+\section1 Camera Support
+
+Creating still images and video.
+
+\section2 Still Images
+
+In order to capture an image we need to create a \l QCamera object and use
+it to initialize a \l QVideoWidget, so we can see where the camera is
+pointing - a viewfinder. The camera object is also used to initialize a new
+QCameraImageCapture object, \i imageCapture. All that is then needed is to start
+the camera, lock it so that the settings are not changed while the image
+capture occurs, capture the image, and finally unlock the camera ready for
+the next photo.
+
+ \code
+ camera = new QCamera;
+ viewFinder = new QCameraViewfinder();
+ viewFinder->show();
+
+ camera->setViewfinder(viewFinder);
+
+ imageCapture = new QCameraImageCapture(camera);
+
+ camera->setCaptureMode(QCamera::CaptureStillImage);
+ camera->start();
+
+ //on half pressed shutter button
+ camera->searchAndLock();
+
+ ...
+
+ //on shutter button pressed
+ imageCapture->capture();
+
+ //on shutter button released
+ camera->unlock();
+ \endcode
+
+\note Alternatively, we could have used a QGraphicsVideoItem as a viewfinder.
+
+
+\section2 Video Clips
+
+Previously we saw code that allowed the capture of a still image. Recording
+video requires the use of a \l QMediaRecorder object and a \l
+QAudioCaptureSource for sound.
+
+To record video we need a camera object, as before, a media recorder and a
+viewfinder object. The media recorder object will need to be initialized.
+
+ \code
+ camera = new QCamera;
+ mediaRecorder = new QMediaRecorder(camera);
+
+ camera->setCaptureMode(QCamera::CaptureVideo);
+ camera->start();
+
+ //on shutter button pressed
+ mediaRecorder->record();
+ \endcode
+
+Signals from the \i mediaRecorder can be connected to slots to react to
+changes in the state of the recorder or error events. Recording itself
+starts with the \l {QMediaRecorder::record()}{record()} function of
+mediaRecorder being called, this causes the signal \l
+{QMediaRecorder::stateChanged()}{stateChanged()} to be emitted. The
+recording process can be changed with the \l {QMediaRecorder::record()}{record()},
+\l {QMediaRecorder::pause()}{pause()}, \l {QMediaRecorder::stop()}{stop()} and
+\l {QMediaRecorder::setMuted()}{setMuted()} slots in \l QMediaRecorder.
+
+When the camera is in video mode, as decided by the application, then as the
+shutter button is pressed the camera is locked as before but instead the
+\l {QMediaRecorder::record()}{record()} function in \l QMediaRecorder is used.
+
+
+
+\section2 Focus
+
+Focusing is managed by the classes \l QCameraFocus and \l QCameraFocusControl.
+QCameraFocus allows the developer to set the general policy by means of the
+enums for the \l {QCameraFocus::FocusMode}{FocusMode} and the
+\l {QCameraFocus::FocusPointMode}{FocusPointMode}.
+\l {QCameraFocus::FocusMode}{FocusMode} deals with
+settings such as \l {QCameraFocus::FocusMode}{AutoFocus},
+\l {QCameraFocus::FocusMode}{ContinuousFocus} and
+\l {QCameraFocus::FocusMode}{InfinityFocus}, whereas
+\l {QCameraFocus::FocusPointMode}{FocusPointMode} deals with the various focus zones within the view.
+\l {QCameraFocus::FocusPointMode}{FocusPointMode} has support for face
+recognition, center focus and a custom focus where the focus point can be specified.
+
+
+
+\section2 Canceling Asynchronous Operations
+
+Various operations such as image capture and auto focusing occur
+asynchrously. These operations can often be cancelled by the start of a new
+operation as long as this is supported by the backend. For image capture,
+the operation can be cancelled by calling
+\l {QCameraImageCapture::cancelCapture()}{cancelCapture()}. For \l {QCameraFocus::FocusMode}{auto-focus},
+\l {QCameraExposure::ExposureMode}{auto-exposure} or \l {QCameraImageProcessing::WhiteBalanceMode}{white balance}
+cancellation can be done by calling \l {QCamera::unlock()}{unlock}(QCamera::LockFocus).
+
+
+
+\section2 Camera Controls
+
+ \table
+ \header
+ \o Control Name
+ \o Description
+ \row
+ \o camera
+ \o The interface for system camera devices
+ \row
+ \o exposure
+ \o Includes: flash mode; flash power; metering mode; aperture; shutter speed, iso setting
+ \row
+ \o focus
+ \o Includes: optical zoom; digital zoom; focus point; focus zones
+ \row
+ \o image processing
+ \o White balance; contrast; saturation; sharpen; denoise
+ \row
+ \o locks
+ \o Handles the locking and unlocking of camera devices
+ \endtable
+
+
+\section2 Classes
+\annotatedlist camera
+
+
+
+
+\target qtmultimediakit examples
+\section1 Examples
+
+\section2 Record a Sound Source
+
+\l{audiorecorder}{AudioRecorder} is a demonstration of the discovery of
+the supported devices and codecs and the use of recording functions in the
+QMediaRecorder class.
+
+\section2 Play a Media File
+
+The \l{player}{Player} example is a simple multimedia player. Select a
+video file to play, stop, pause, show in fullscreen or manipulate various
+image attributes using the Color Options button.
+
+\section2 Slide Show
+
+The \l{slideshow}{Slide Show} shows the use of the QMediaImageViewer and
+QVideoWidget classes.
+
+\section2 Camera Example
+
+The \l{Camera Example} shows how use the QtMultimediaKit API to quickly
+write a camera application in C++.
+
+\section2 QML Camera Example
+
+The \l {QML Camera Example} demonstrates still image capture and controls
+using the QML plugin. Video recording is not currently available.
+
+
+\section1 Reference documentation
+
+\section2 Main classes
+
+\annotatedlist multimedia
+
+
+\section2 Classes for service implementers.
+
+\annotatedlist multimedia-serv
+
+\section2 QML Elements
+\list
+\o \l {SoundEffect}{SoundEffect: Low Latency Sound Effects}
+\o \l {Audio}{Audio: Music playback}
+\o \l {Video}{Video: Video playback}
+\endlist
+*/
+
+
+
diff --git a/doc/src/plugins/qml-multimedia.qdoc b/doc/src/plugins/qml-multimedia.qdoc
new file mode 100644
index 000000000..facae3c92
--- /dev/null
+++ b/doc/src/plugins/qml-multimedia.qdoc
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \group qml-multimedia
+ \title QML Multimedia Plugin
+ QML Support for the QtMobility Project Multimedia API.
+*/
+
+/*!
+ \page qml-multimedia.html
+
+ \title Multimedia QML Plugin
+
+ \brief A QML plugin for the QtMobility Project Multimedia API.
+
+
+ \section1 Overview
+
+ The Multimedia API in the QtMobility Project gives developers a simplified way to use audio and video playback, and access camera functionality. The Multimedia QML Plugin provides a QML friendly interface to these features.
+
+ \section1 Elements
+
+ \section2 Audio
+
+ The \l Audio element is an easy way to add audio playback to a Qt Quick
+ scene. QtMobility provides properties for control, methods (functions) and signals.
+
+ The code extract below shows the creation and use of an audio element.
+
+ \qml
+
+ import Qt 4.7
+ import QtMultimediaKit 1.1
+ // ...
+
+ Audio {
+ id: playMusic
+ source: "music.wav"
+ }
+
+ MouseArea {
+ id: playArea
+ anchors.fill: parent
+ onPressed: { playMusic.play() }
+ }
+
+ \endqml
+
+ The snippet above shows how the inclusion of \i playMusic enables audio features on the element that contains it. So that when the parent's MouseArea is clicked the \l {Audio::play()}{play()} method of the audio element is run. Other typical audio control methods are available such as \l {Audio::pause}{pause()} and \l {Audio::stop()}{stop()}.
+
+ Much of the getting / setting of \l Audio parameters is done through properties. These include
+ \table 70%
+ \header
+ \o Property
+ \o Description
+ \row
+ \o \l {Audio::source}{source}
+ \o The source URL of the media.
+ \row
+ \o \l {Audio::autoLoad}{autoLoad}
+ \o Indicates if loading of media should begin immediately.
+ \row
+ \o \l{Audio::playing}{playing}
+ \o Indicates that the media is playing.
+ \row
+ \o \l {Audio::paused}{paused}
+ \o The media is paused.
+ \row
+ \o \l{Audio::status}{status}
+ \o The status of media loading.
+ \row
+ \o \l{Audio::duration}{duration}
+ \o Amount of time in milliseconds the media will play.
+ \row
+ \o \l{Audio::position}{position}
+ \o Current position in the media in milliseconds of play.
+ \row
+ \o \l{Audio::volume}{volume}
+ \o Audio output volume: from 0.0 (silent) to 1.0 (maximum)
+ \row
+ \o \l{Audio::muted}{muted}
+ \o Indicates audio is muted.
+ \row
+ \o \l{Audio::bufferProgress}{bufferProgress}
+ \o Indicates how full the data buffer is: 0.0 (empty) to 1.0 (full).
+ \row
+ \o \l{Audio::seekable}{seekable}
+ \o Indicates whether the audio position can be changed.
+ \row
+ \o \l{Audio::playbackRate}{playbackRate}
+ \o The rate at which audio is played at as a multiple of the normal rate.
+ \row
+ \o \l{Audio::error}{error}
+ \o An error code for the error state including NoError
+ \row
+ \o \l{Audio::errorString}{errorString}
+ \o A description of the current error condition.
+ \endtable
+
+ The set of signals available allow the developer to create custom behavior when the following events occur,
+
+ \table 70%
+ \header
+ \o Signal
+ \o Description
+ \row
+ \o \l{Audio::onStarted}{onStarted}
+ \o Called when playback has been started.
+ \row
+ \o \l{Audio::onResumed}{onResumed}
+ \o Called when playback is resumed from the paused state.
+ \row
+ \o \l{Audio::onPaused}{onPaused}
+ \o Called when playback is paused.
+ \row
+ \o \l{Audio::onStopped}{onStopped}
+ \o Called when playback is stopped.
+ \row
+ \o \l{Audio::onError}{onError}
+ \o Called when the specified error occurs.
+ \endtable
+
+ \section2 Camera
+
+ The \l Camera element in the plugin enables still image capture using
+ QML. The element has methods for starting and stopping the camera, capturing
+ the image, camera settings and many signals indicating critical events.
+
+ The follow code is taken from the \l {QML Camera Example}. This snippet
+ shows the setting up of the \l Camera element
+
+ \qml
+
+ Camera {
+ id: camera
+ x : 0
+ y : 0
+ width : 640
+ height : 480
+ focus : visible //to receive focus and capture key events
+ //captureResolution : "640x480"
+
+ flashMode: stillControls.flashMode
+ whiteBalanceMode: stillControls.whiteBalance
+ exposureCompensation: stillControls.exposureCompensation
+
+ onImageCaptured : {
+ photoPreview.source = preview
+ stillControls.previewAvailable = true
+ cameraUI.state = "PhotoPreview"
+ }
+ }
+
+ \endqml
+
+ Notice that the slot for the \l {Camera::imageCaptured()}{imageCaptured()}
+ signal is implemented in \i onImageCaptured. However, this code only
+ changes some state information to allow previewing.
+
+ The capture call itself is part of the implementation of the button
+ that the user presses to take the image. It uses a call to
+ \l {Camera::captureImage()}{captureImage()}:
+
+ \qml
+
+ CameraButton {
+ text: "Capture"
+ onClicked: camera.captureImage()
+ }
+
+ \endqml
+
+
+ \section2 Video
+
+ Adding video playback, with sound, to a Qt Quick scene is also easy. The process is very similar to that of Audio above, in fact \l {Video} shares many of the property names, methods and signals. Here is the equivalent sample code to implement a video playback element in a scene
+
+ \qml
+
+ 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
+
+ There are similar features like \l {Video::play()}{play()} with new
+ features specific to video.
+
+ In the above sample when the parent of MouseArea is clicked, an area of 800x600 pixels with an id of 'video', the source "video.avi" will play in that area. Notice also that signals for the Keys element have been defined so that a spacebar will toggle the pause button; the left arrow will move the current position in the video to 5 seconds previously; and the right arrow will advance the current position in the video by 5 seconds.
+
+ Most of the differences will obviously be about video control and information. There are many properties associated with the \l {Video} element, most of them deal with meta-data, control of the video media and aspects of presentation.
+
+ \section2 SoundEffect
+
+ The \l SoundEffect element provides a way to play short sound effects, like in video games. Multiple sound effect instances can be played simultaneously.
+ You should use the \l Audio element for music playback.
+
+ \qml
+
+ import Qt 4.7
+ import QtMultimediaKit 1.1
+
+
+ SoundEffect {
+ id: effect
+ source: "test.wav"
+ }
+ MouseArea {
+ id: playArea
+ anchors.fill: parent
+ onPressed: { effect.play() }
+ }
+
+ \endqml
+
+
+ In the above sample the sound effect will be played when the MouseArea is clicked.
+
+ For a complete description of this element, see \l SoundEffect
+
+ \section2 Camera
+
+ Adding access to the camera viewfinder, and capturing images is possible by using the \l Camera element. You can adjust capture settings
+ including white balance, exposure compensation and flash mode, and control zoom.
+
+ \qml
+ import Qt 4.7
+ import QtMultimediaKit 1.1
+
+ Camera {
+ focus : visible // to receive focus and capture key events when visible
+
+ flashMode: Camera.FlashRedEyeReduction
+ whiteBalanceMode: Camera.WhiteBalanceFlash
+ exposureCompensation: -1.0
+
+ onImageCaptured : {
+ photoPreview.source = preview // Show the preview in an Image element
+ }
+
+ }
+ \endqml
+
+ For a complete description of this element, see \l Camera, and look at the \l {declarative-camera}{QML Camera Example}.
+
+ \section1 Multimedia QML Elements
+
+ \annotatedlist qml-multimedia
+*/
+
+
diff --git a/doc/src/snippets/multimedia-snippets/audio.cpp b/doc/src/snippets/multimedia-snippets/audio.cpp
new file mode 100644
index 000000000..d58bc5f53
--- /dev/null
+++ b/doc/src/snippets/multimedia-snippets/audio.cpp
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** 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$
+** 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$
+**
+****************************************************************************/
+
+/* Audio related snippets */
+#include <QFile>
+#include <QTimer>
+#include <QDebug>
+
+#include "qaudiodeviceinfo.h"
+#include "qaudioinput.h"
+#include "qaudiooutput.h"
+
+class AudioInputExample : public QObject {
+ Q_OBJECT
+public:
+ void setup();
+
+
+public Q_SLOTS:
+ void stopRecording();
+ void stateChanged(QAudio::State newState);
+
+private:
+ //! [Audio input class members]
+ QFile destinationFile; // class member.
+ QAudioInput* audio; // class member.
+ //! [Audio input class members]
+};
+
+
+void AudioInputExample::setup()
+//! [Audio input setup]
+{
+ destinationFile.setFileName("/tmp/test.raw");
+ destinationFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
+
+ QAudioFormat format;
+ // set up the format you want, eg.
+ format.setFrequency(8000);
+ format.setChannels(1);
+ format.setSampleSize(8);
+ format.setCodec("audio/pcm");
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::UnSignedInt);
+
+ QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
+ if (!info.isFormatSupported(format)) {
+ qWarning()<<"default format not supported try to use nearest";
+ format = info.nearestFormat(format);
+ }
+
+ audio = new QAudioInput(format, this);
+ connect(audio, SIGNAL(stateChanged(QAudio::State)), this, SLOT(stateChanged(QAudio::State)));
+
+ QTimer::singleShot(3000, this, SLOT(stopRecording()));
+ audio->start(&destinationFile);
+ // Records audio for 3000ms
+}
+//! [Audio input setup]
+
+//! [Audio input stop recording]
+void AudioInputExample::stopRecording()
+{
+ audio->stop();
+ destinationFile.close();
+ delete audio;
+}
+//! [Audio input stop recording]
+
+//! [Audio input state changed]
+void AudioInputExample::stateChanged(QAudio::State newState)
+{
+ switch (newState) {
+ case QAudio::StoppedState:
+ if (audio->error() != QAudio::NoError) {
+ // Error handling
+ } else {
+ // Finished recording
+ }
+ break;
+
+ // ...
+ }
+}
+//! [Audio input state changed]
+
+
+class AudioOutputExample : public QObject {
+ Q_OBJECT
+public:
+ void setup();
+
+public Q_SLOTS:
+ void stateChanged(QAudio::State newState);
+
+private:
+ //! [Audio output class members]
+ QFile sourceFile; // class member.
+ QAudioOutput* audio; // class member.
+ //! [Audio output class members]
+};
+
+
+void AudioOutputExample::setup()
+//! [Audio output setup]
+{
+ sourceFile.setFileName("/tmp/test.raw");
+ sourceFile.open(QIODevice::ReadOnly);
+
+ QAudioFormat format;
+ // Set up the format, eg.
+ format.setFrequency(8000);
+ format.setChannels(1);
+ format.setSampleSize(8);
+ format.setCodec("audio/pcm");
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::UnSignedInt);
+
+ QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
+ if (!info.isFormatSupported(format)) {
+ qWarning() << "raw audio format not supported by backend, cannot play audio.";
+ return;
+ }
+
+ audio = new QAudioOutput(format, this);
+ connect(audio, SIGNAL(stateChanged(QAudio::State)), this, SLOT(stateChanged(QAudio::State)));
+ audio->start(&sourceFile);
+}
+//! [Audio output setup]
+
+//! [Audio output state changed]
+void AudioOutputExample::stateChanged(QAudio::State newState)
+{
+ switch (newState) {
+ case QAudio::IdleState:
+ // Finished playing (no more data)
+ audio->stop();
+ sourceFile.close();
+ delete audio;
+ break;
+
+ case QAudio::StoppedState:
+ // Stopped for other reasons
+ if (audio->error() != QAudio::NoError) {
+ // Error handling
+ }
+ break;
+
+ // ...
+ }
+}
+//! [Audio output state changed]
+
+void AudioDeviceInfo()
+{
+ //! [Setting audio format]
+ QAudioFormat format;
+ format.setFrequency(44100);
+ // ... other format parameters
+ format.setSampleType(QAudioFormat::SignedInt);
+
+ QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
+
+ if (!info.isFormatSupported(format))
+ format = info.nearestFormat(format);
+ //! [Setting audio format]
+
+ //! [Dumping audio formats]
+ foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput))
+ qDebug() << "Device name: " << deviceInfo.deviceName();
+ //! [Dumping audio formats]
+}
diff --git a/doc/src/snippets/multimedia-snippets/audiorecorder.cpp b/doc/src/snippets/multimedia-snippets/audiorecorder.cpp
new file mode 100644
index 000000000..fd92026c6
--- /dev/null
+++ b/doc/src/snippets/multimedia-snippets/audiorecorder.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtGui>
+
+#include <qaudiocapturesource.h>
+#include <qmediarecorder.h>
+#include <qmediaservice.h>
+
+#include <QtMultimediaKit/qaudioformat.h>
+
+#include "audiorecorder.h"
+
+AudioRecorder::AudioRecorder()
+{
+//! [create-objs-1]
+ audiosource = new QAudioCaptureSource;
+ capture = new QMediaRecorder(audiosource);
+//! [create-objs-1]
+
+ // set a default file
+ capture->setOutputLocation(QUrl("test.raw"));
+
+ QWidget *window = new QWidget;
+ QGridLayout* layout = new QGridLayout;
+
+ QLabel* deviceLabel = new QLabel;
+ deviceLabel->setText("Devices");
+ deviceBox = new QComboBox(this);
+ deviceBox->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
+
+ QLabel* codecLabel = new QLabel;
+ codecLabel->setText("Codecs");
+ codecsBox = new QComboBox(this);
+ codecsBox->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
+
+ QLabel* qualityLabel = new QLabel;
+ qualityLabel->setText("Quality");
+ qualityBox = new QComboBox(this);
+ qualityBox->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
+
+//! [device-list]
+ for(int i = 0; i < audiosource->deviceCount(); i++)
+ deviceBox->addItem(audiosource->name(i));
+//! [device-list]
+
+//! [codec-list]
+ QStringList codecs = capture->supportedAudioCodecs();
+ for(int i = 0; i < codecs.count(); i++)
+ codecsBox->addItem(codecs.at(i));
+//! [codec-list]
+
+ qualityBox->addItem("Low");
+ qualityBox->addItem("Medium");
+ qualityBox->addItem("High");
+
+ connect(capture, SIGNAL(durationChanged(qint64)), this, SLOT(updateProgress(qint64)));
+ connect(capture, SIGNAL(stateChanged(QMediaRecorder::State)), this, SLOT(stateChanged(QMediaRecorder::State)));
+
+ layout->addWidget(deviceLabel,0,0,Qt::AlignHCenter);
+ connect(deviceBox,SIGNAL(activated(int)),SLOT(deviceChanged(int)));
+ layout->addWidget(deviceBox,0,1,1,3,Qt::AlignLeft);
+
+ layout->addWidget(codecLabel,1,0,Qt::AlignHCenter);
+ connect(codecsBox,SIGNAL(activated(int)),SLOT(codecChanged(int)));
+ layout->addWidget(codecsBox,1,1,Qt::AlignLeft);
+
+ layout->addWidget(qualityLabel,1,2,Qt::AlignHCenter);
+ connect(qualityBox,SIGNAL(activated(int)),SLOT(qualityChanged(int)));
+ layout->addWidget(qualityBox,1,3,Qt::AlignLeft);
+
+ fileButton = new QPushButton(this);
+ fileButton->setText(tr("Output File"));
+ connect(fileButton,SIGNAL(clicked()),SLOT(selectOutputFile()));
+ layout->addWidget(fileButton,3,0,Qt::AlignHCenter);
+
+ button = new QPushButton(this);
+ button->setText(tr("Record"));
+ connect(button,SIGNAL(clicked()),SLOT(toggleRecord()));
+ layout->addWidget(button,3,3,Qt::AlignHCenter);
+
+ recTime = new QLabel;
+ recTime->setText("0 sec");
+ layout->addWidget(recTime,4,0,Qt::AlignHCenter);
+
+ window->setLayout(layout);
+ setCentralWidget(window);
+ window->show();
+
+ active = false;
+}
+
+AudioRecorder::~AudioRecorder()
+{
+ delete capture;
+ delete audiosource;
+}
+
+void AudioRecorder::updateProgress(qint64 pos)
+{
+ currentTime = pos;
+ if(currentTime == 0) currentTime = 1;
+ QString text = QString("%1 secs").arg(currentTime/1000);
+ recTime->setText(text);
+}
+
+void AudioRecorder::stateChanged(QMediaRecorder::State state)
+{
+ qWarning()<<"stateChanged() "<<state;
+}
+
+void AudioRecorder::deviceChanged(int idx)
+{
+//! [get-device]
+ for(int i = 0; i < audiosource->deviceCount(); i++) {
+ if(deviceBox->itemText(idx).compare(audiosource->name(i)) == 0)
+ audiosource->setSelectedDevice(i);
+ }
+//! [get-device]
+}
+
+void AudioRecorder::codecChanged(int idx)
+{
+ Q_UNUSED(idx);
+ //capture->setAudioCodec(codecsBox->itemText(idx));
+}
+
+void AudioRecorder::qualityChanged(int idx)
+{
+ Q_UNUSED(idx);
+ /*
+ if(capture->audioCodec().compare("audio/pcm") == 0) {
+ if(qualityBox->itemText(idx).compare("Low") == 0) {
+ // 8000Hz mono is 8kbps
+ capture->setAudioBitrate(8);
+ } else if(qualityBox->itemText(idx).compare("Medium") == 0) {
+ // 22050Hz mono is 44.1kbps
+ capture->setAudioBitrate(44);
+ } else if(qualityBox->itemText(idx).compare("High") == 0) {
+ // 44100Hz mono is 88.2kbps
+ capture->setAudioBitrate(88);
+ }
+ }
+ */
+}
+
+//! [toggle-record]
+void AudioRecorder::toggleRecord()
+{
+ if(!active) {
+ recTime->setText("0 sec");
+ currentTime = 0;
+ capture->record();
+
+ button->setText(tr("Stop"));
+ active = true;
+ } else {
+ capture->stop();
+ button->setText(tr("Record"));
+ active = false;
+ }
+}
+//! [toggle-record]
+
+void AudioRecorder::selectOutputFile()
+{
+ QStringList fileNames;
+
+ QFileDialog dialog(this);
+
+ dialog.setFileMode(QFileDialog::AnyFile);
+ if (dialog.exec())
+ fileNames = dialog.selectedFiles();
+
+ if(fileNames.size() > 0)
+ capture->setOutputLocation(QUrl(fileNames.first()));
+}
diff --git a/doc/src/snippets/multimedia-snippets/camera.cpp b/doc/src/snippets/multimedia-snippets/camera.cpp
new file mode 100644
index 000000000..453b44fce
--- /dev/null
+++ b/doc/src/snippets/multimedia-snippets/camera.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** 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$
+** 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$
+**
+****************************************************************************/
+
+/* Camera snippets */
+
+#include "qcamera.h"
+#include "qcameraviewfinder.h"
+#include "qmediarecorder.h"
+#include "qcameraimagecapture.h"
+
+void camera()
+{
+ QCamera *camera = 0;
+ QCameraViewfinder *viewfinder = 0;
+ QMediaRecorder *recorder = 0;
+ QCameraImageCapture *imageCapture = 0;
+
+ //! [Camera]
+ camera = new QCamera;
+
+ viewfinder = new QCameraViewfinder();
+ viewfinder->show();
+
+ camera->setViewfinder(viewfinder);
+
+ recorder = new QMediaRecorder(camera);
+ imageCapture = new QCameraImageCapture(camera);
+
+ camera->setCaptureMode(QCamera::CaptureStillImage);
+ camera->start();
+ //! [Camera]
+
+ //! [Camera keys]
+ //on half pressed shutter button
+ camera->searchAndLock();
+
+ //on shutter button pressed
+ imageCapture->capture();
+
+ //on shutter button released
+ camera->unlock();
+ //! [Camera keys]
+
+}
diff --git a/doc/src/snippets/multimedia-snippets/media.cpp b/doc/src/snippets/multimedia-snippets/media.cpp
new file mode 100644
index 000000000..6ef60f7e7
--- /dev/null
+++ b/doc/src/snippets/multimedia-snippets/media.cpp
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** 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$
+** 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$
+**
+****************************************************************************/
+
+/* Media related snippets */
+#include <QFile>
+#include <QTimer>
+
+#include "qaudiocapturesource.h"
+#include "qmediaplaylist.h"
+#include "qmediarecorder.h"
+#include "qmediaservice.h"
+#include "qmediaimageviewer.h"
+#include "qmediaimageviewer.h"
+#include "qmediaplayercontrol.h"
+#include "qmediaplayer.h"
+#include "qradiotuner.h"
+#include "qvideowidget.h"
+#include "qcameraimagecapture.h"
+
+class MediaExample : public QObject {
+ Q_OBJECT
+
+ void AudioCaptureSource();
+ void MediaControl();
+ void MediaImageViewer();
+ void MediaPlayer();
+ void RadioTuna();
+ void MediaRecorder();
+ void EncoderSettings();
+ void ImageEncoderSettings();
+
+private:
+ // Common naming
+ QMediaService *mediaService;
+ QVideoWidget *videoWidget;
+ QWidget *widget;
+ QMediaPlayer *player;
+ QMediaPlaylist *playlist;
+ QMediaContent video;
+ QMediaRecorder *recorder;
+ QMediaImageViewer *viewer;
+ QCameraImageCapture *imageCapture;
+ QAudioCaptureSource *audioSource;
+ QString fileName;
+ QRadioTuner *radio;
+ QMediaContent image1;
+ QMediaContent image2;
+ QMediaContent image3;
+
+ static const int yourRadioStationFrequency = 11;
+};
+
+void MediaExample::AudioCaptureSource()
+{
+ //! [Audio capture source]
+ QAudioCaptureSource* audioSource = new QAudioCaptureSource;
+ QMediaRecorder* recorder = new QMediaRecorder(audioSource);
+
+ recorder->setOutputLocation(QUrl("test.raw"));
+ //! [Audio capture source]
+
+ Q_UNUSED(audioSource);
+}
+
+
+void MediaExample::MediaControl()
+{
+ {
+ //! [Request control]
+ QMediaPlayerControl *control = qobject_cast<QMediaPlayerControl *>(
+ mediaService->requestControl("com.nokia.Qt.QMediaPlayerControl/1.0"));
+ //! [Request control]
+ Q_UNUSED(control);
+ }
+
+ {
+ //! [Request control templated]
+ QMediaPlayerControl *control = mediaService->requestControl<QMediaPlayerControl *>();
+ //! [Request control templated]
+ Q_UNUSED(control);
+ }
+}
+
+
+void MediaExample::EncoderSettings()
+{
+ //! [Audio encoder settings]
+ QAudioEncoderSettings audioSettings;
+ audioSettings.setCodec("audio/mpeg");
+ audioSettings.setChannelCount(2);
+
+ recorder->setEncodingSettings(audioSettings);
+ //! [Audio encoder settings]
+
+ //! [Video encoder settings]
+ QVideoEncoderSettings videoSettings;
+ videoSettings.setCodec("video/mpeg2");
+ videoSettings.setResolution(640, 480);
+
+ recorder->setEncodingSettings(audioSettings, videoSettings);
+ //! [Video encoder settings]
+}
+
+void MediaExample::ImageEncoderSettings()
+{
+ //! [Image encoder settings]
+ QImageEncoderSettings imageSettings;
+ imageSettings.setCodec("image/jpeg");
+ imageSettings.setResolution(1600, 1200);
+
+ imageCapture->setEncodingSettings(imageSettings);
+ //! [Image encoder settings]
+}
+
+void MediaExample::MediaImageViewer()
+{
+ //! [Binding]
+ viewer = new QMediaImageViewer(this);
+
+ videoWidget = new QVideoWidget;
+ viewer->bind(videoWidget);
+ videoWidget->show();
+ //! [Binding]
+
+ //! [Playlist]
+ playlist = new QMediaPlaylist(this);
+ playlist->setPlaybackMode(QMediaPlaylist::Loop);
+ playlist->addMedia(image1);
+ playlist->addMedia(image2);
+ playlist->addMedia(image3);
+
+ viewer->setPlaylist(playlist);
+ viewer->setTimeout(5000);
+ viewer->play();
+ //! [Playlist]
+}
+
+void MediaExample::MediaPlayer()
+{
+ //! [Player]
+ player = new QMediaPlayer;
+ connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64)));
+ player->setMedia(QUrl::fromLocalFile("/Users/me/Music/coolsong.mp3"));
+ player->setVolume(50);
+ player->play();
+ //! [Player]
+
+ //! [Movie playlist]
+ playlist = new QMediaPlaylist;
+ playlist->addMedia(QUrl("http://example.com/movie1.mp4"));
+ playlist->addMedia(QUrl("http://example.com/movie2.mp4"));
+ playlist->addMedia(QUrl("http://example.com/movie3.mp4"));
+ playlist->setCurrentIndex(1);
+
+ player = new QMediaPlayer;
+ player->setPlaylist(playlist);
+
+ videoWidget = new QVideoWidget;
+ player->setVideoOutput(videoWidget);
+ videoWidget->show();
+
+ player->play();
+ //! [Movie playlist]
+}
+
+void MediaExample::MediaRecorder()
+{
+ //! [Media recorder]
+ // Audio only recording
+ audioSource = new QAudioCaptureSource;
+ recorder = new QMediaRecorder(audioSource);
+
+ QAudioEncoderSettings audioSettings;
+ audioSettings.setCodec("audio/vorbis");
+ audioSettings.setQuality(QtMultimediaKit::HighQuality);
+
+ recorder->setEncodingSettings(audioSettings);
+
+ recorder->setOutputLocation(QUrl::fromLocalFile(fileName));
+ recorder->record();
+ //! [Media recorder]
+}
+
+void MediaExample::RadioTuna()
+{
+ //! [Radio tuner]
+ radio = new QRadioTuner;
+ connect(radio, SIGNAL(frequencyChanged(int)), this, SLOT(freqChanged(int)));
+ if (radio->isBandSupported(QRadioTuner::FM)) {
+ radio->setBand(QRadioTuner::FM);
+ radio->setFrequency(yourRadioStationFrequency);
+ radio->setVolume(100);
+ radio->start();
+ }
+ //! [Radio tuner]
+}
+
+
diff --git a/doc/src/snippets/multimedia-snippets/multimedia-snippets.pro b/doc/src/snippets/multimedia-snippets/multimedia-snippets.pro
new file mode 100644
index 000000000..c85631c58
--- /dev/null
+++ b/doc/src/snippets/multimedia-snippets/multimedia-snippets.pro
@@ -0,0 +1,21 @@
+# Doc snippets - compiled for truthiness
+
+TEMPLATE = lib
+TARGET = qtmmksnippets
+include(../../../../features/basic_examples_setup.pri)
+
+INCLUDEPATH += ../../../../src/global \
+ ../../../../src/multimediakit \
+ ../../../../src/multimediakit/audio \
+ ../../../../src/multimediakit/video \
+ ../../../../src/multimediakit/effects
+
+CONFIG += console
+
+qtAddLibrary(QtMultimediaKit)
+
+SOURCES += \
+ audio.cpp \
+ video.cpp \
+ camera.cpp \
+ media.cpp
diff --git a/doc/src/snippets/multimedia-snippets/player.cpp b/doc/src/snippets/multimedia-snippets/player.cpp
new file mode 100644
index 000000000..db9373437
--- /dev/null
+++ b/doc/src/snippets/multimedia-snippets/player.cpp
@@ -0,0 +1,317 @@
+/****************************************************************************
+**
+** 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$
+** 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 "player.h"
+
+#include "playercontrols.h"
+#include "playlistmodel.h"
+#include "videowidget.h"
+
+#include <qmediaservice.h>
+#include <qmediaplaylist.h>
+
+#include <QtGui>
+
+Player::Player(QWidget *parent)
+ : QWidget(parent)
+ , videoWidget(0)
+ , coverLabel(0)
+ , slider(0)
+ , colorDialog(0)
+{
+//! [create-objs]
+ player = new QMediaPlayer;
+ playlist = new QMediaPlaylist(player);
+//! [create-objs]
+
+ connect(player, SIGNAL(durationChanged(qint64)), SLOT(durationChanged(qint64)));
+ connect(player, SIGNAL(positionChanged(qint64)), SLOT(positionChanged(qint64)));
+ connect(player, SIGNAL(metaDataChanged()), SLOT(metaDataChanged()));
+ connect(playlist, SIGNAL(playlistPositionChanged(int)), SLOT(playlistPositionChanged(int)));
+ connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
+ this, SLOT(statusChanged(QMediaPlayer::MediaStatus)));
+ connect(player, SIGNAL(bufferStatusChanged(int)), this, SLOT(bufferingProgress(int)));
+
+ videoWidget = new VideoWidget(player);
+
+ playlistModel = new PlaylistModel(this);
+ playlistModel->setPlaylist(playlist);
+
+ playlistView = new QListView;
+ playlistView->setModel(playlistModel);
+ playlistView->setCurrentIndex(playlistModel->index(playlist->currentPosition(), 0));
+
+ connect(playlistView, SIGNAL(activated(QModelIndex)), this, SLOT(jump(QModelIndex)));
+
+ slider = new QSlider(Qt::Horizontal);
+ slider->setRange(0, player->duration() / 1000);
+
+ connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(seek(int)));
+
+ QPushButton *openButton = new QPushButton(tr("Open"));
+
+ connect(openButton, SIGNAL(clicked()), this, SLOT(open()));
+
+ PlayerControls *controls = new PlayerControls;
+ controls->setState(player->state());
+ controls->setVolume(player->volume());
+ controls->setMuted(controls->isMuted());
+
+ connect(controls, SIGNAL(play()), player, SLOT(play()));
+ connect(controls, SIGNAL(pause()), player, SLOT(pause()));
+ connect(controls, SIGNAL(stop()), player, SLOT(stop()));
+ connect(controls, SIGNAL(next()), playlist, SLOT(next()));
+ connect(controls, SIGNAL(previous()), playlist, SLOT(previous()));
+ connect(controls, SIGNAL(changeVolume(int)), player, SLOT(setVolume(int)));
+ connect(controls, SIGNAL(changeMuting(bool)), player, SLOT(setMuted(bool)));
+ connect(controls, SIGNAL(changeRate(qreal)), player, SLOT(setPlaybackRate(qreal)));
+
+ connect(player, SIGNAL(stateChanged(QMediaPlayer::State)),
+ controls, SLOT(setState(QMediaPlayer::State)));
+ connect(player, SIGNAL(volumeChanged(int)), controls, SLOT(setVolume(int)));
+ connect(player, SIGNAL(mutingChanged(bool)), controls, SLOT(setMuted(bool)));
+
+ QPushButton *fullScreenButton = new QPushButton(tr("FullScreen"));
+ fullScreenButton->setCheckable(true);
+
+ if (videoWidget != 0) {
+ connect(fullScreenButton, SIGNAL(clicked(bool)), videoWidget, SLOT(setFullScreen(bool)));
+ connect(videoWidget, SIGNAL(fullScreenChanged(bool)),
+ fullScreenButton, SLOT(setChecked(bool)));
+ } else {
+ fullScreenButton->setEnabled(false);
+ }
+
+ QPushButton *colorButton = new QPushButton(tr("Color Options..."));
+ if (videoWidget)
+ connect(colorButton, SIGNAL(clicked()), this, SLOT(showColorDialog()));
+ else
+ colorButton->setEnabled(false);
+
+ QBoxLayout *displayLayout = new QHBoxLayout;
+ if (videoWidget)
+ displayLayout->addWidget(videoWidget, 2);
+ else
+ displayLayout->addWidget(coverLabel, 2);
+ displayLayout->addWidget(playlistView);
+
+ QBoxLayout *controlLayout = new QHBoxLayout;
+ controlLayout->setMargin(0);
+ controlLayout->addWidget(openButton);
+ controlLayout->addStretch(1);
+ controlLayout->addWidget(controls);
+ controlLayout->addStretch(1);
+ controlLayout->addWidget(fullScreenButton);
+ controlLayout->addWidget(colorButton);
+
+ QBoxLayout *layout = new QVBoxLayout;
+ layout->addLayout(displayLayout);
+ layout->addWidget(slider);
+ layout->addLayout(controlLayout);
+
+ setLayout(layout);
+
+ metaDataChanged();
+}
+
+Player::~Player()
+{
+ delete playlist;
+ delete player;
+}
+
+void Player::open()
+{
+ QStringList fileNames = QFileDialog::getOpenFileNames();
+ foreach (QString const &fileName, fileNames)
+ playlist->appendItem(QUrl::fromLocalFile(fileName));
+}
+
+void Player::durationChanged(qint64 duration)
+{
+ slider->setMaximum(duration / 1000);
+}
+
+void Player::positionChanged(qint64 progress)
+{
+ slider->setValue(progress / 1000);
+}
+
+void Player::metaDataChanged()
+{
+ //qDebug() << "update metadata" << player->metaData(QtMultimediaKit::Title).toString();
+ if (player->isMetaDataAvailable()) {
+ setTrackInfo(QString("%1 - %2")
+ .arg(player->metaData(QtMultimediaKit::AlbumArtist).toString())
+ .arg(player->metaData(QtMultimediaKit::Title).toString()));
+
+ if (coverLabel) {
+ QUrl url = player->metaData(QtMultimediaKit::CoverArtUrlLarge).value<QUrl>();
+
+ coverLabel->setPixmap(!url.isEmpty()
+ ? QPixmap(url.toString())
+ : QPixmap());
+ }
+ }
+}
+
+void Player::jump(const QModelIndex &index)
+{
+ if (index.isValid()) {
+ playlist->setCurrentPosition(index.row());
+ }
+}
+
+void Player::playlistPositionChanged(int currentItem)
+{
+ playlistView->setCurrentIndex(playlistModel->index(currentItem, 0));
+}
+
+void Player::seek(int seconds)
+{
+ player->setPosition(seconds * 1000);
+}
+
+void Player::statusChanged(QMediaPlayer::MediaStatus status)
+{
+ switch (status) {
+ case QMediaPlayer::UnknownMediaStatus:
+ case QMediaPlayer::NoMedia:
+ case QMediaPlayer::LoadedMedia:
+ case QMediaPlayer::BufferingMedia:
+ case QMediaPlayer::BufferedMedia:
+#ifndef QT_NO_CURSOR
+ unsetCursor();
+#endif
+ setStatusInfo(QString());
+ break;
+ case QMediaPlayer::LoadingMedia:
+#ifndef QT_NO_CURSOR
+ setCursor(QCursor(Qt::BusyCursor));
+#endif
+ setStatusInfo(tr("Loading..."));
+ break;
+ case QMediaPlayer::StalledMedia:
+#ifndef QT_NO_CURSOR
+ setCursor(QCursor(Qt::BusyCursor));
+#endif
+ break;
+ case QMediaPlayer::EndOfMedia:
+#ifndef QT_NO_CURSOR
+ unsetCursor();
+#endif
+ setStatusInfo(QString());
+ QApplication::alert(this);
+ break;
+ case QMediaPlayer::InvalidMedia:
+#ifndef QT_NO_CURSOR
+ unsetCursor();
+#endif
+ setStatusInfo(player->errorString());
+ break;
+ }
+}
+
+void Player::bufferingProgress(int progress)
+{
+ setStatusInfo(tr("Buffering %4%%").arg(progress));
+}
+
+void Player::setTrackInfo(const QString &info)
+{
+ trackInfo = info;
+
+ if (!statusInfo.isEmpty())
+ setWindowTitle(QString("%1 | %2").arg(trackInfo).arg(statusInfo));
+ else
+ setWindowTitle(trackInfo);
+
+}
+
+void Player::setStatusInfo(const QString &info)
+{
+ statusInfo = info;
+
+ if (!statusInfo.isEmpty())
+ setWindowTitle(QString("%1 | %2").arg(trackInfo).arg(statusInfo));
+ else
+ setWindowTitle(trackInfo);
+}
+
+void Player::showColorDialog()
+{
+ if (!colorDialog) {
+ QSlider *brightnessSlider = new QSlider(Qt::Horizontal);
+ brightnessSlider->setRange(-100, 100);
+ brightnessSlider->setValue(videoWidget->brightness());
+ connect(brightnessSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setBrightness(int)));
+ connect(videoWidget, SIGNAL(brightnessChanged(int)), brightnessSlider, SLOT(setValue(int)));
+
+ QSlider *contrastSlider = new QSlider(Qt::Horizontal);
+ contrastSlider->setRange(-100, 100);
+ contrastSlider->setValue(videoWidget->contrast());
+ connect(contrastSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setContrast(int)));
+ connect(videoWidget, SIGNAL(contrastChanged(int)), contrastSlider, SLOT(setValue(int)));
+
+ QSlider *hueSlider = new QSlider(Qt::Horizontal);
+ hueSlider->setRange(-100, 100);
+ hueSlider->setValue(videoWidget->hue());
+ connect(hueSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setHue(int)));
+ connect(videoWidget, SIGNAL(hueChanged(int)), hueSlider, SLOT(setValue(int)));
+
+ QSlider *saturationSlider = new QSlider(Qt::Horizontal);
+ saturationSlider->setRange(-100, 100);
+ saturationSlider->setValue(videoWidget->saturation());
+ connect(saturationSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setSaturation(int)));
+ connect(videoWidget, SIGNAL(saturationChanged(int)), saturationSlider, SLOT(setValue(int)));
+
+ QFormLayout *layout = new QFormLayout;
+ layout->addRow(tr("Brightness"), brightnessSlider);
+ layout->addRow(tr("Contrast"), contrastSlider);
+ layout->addRow(tr("Hue"), hueSlider);
+ layout->addRow(tr("Saturation"), saturationSlider);
+
+ colorDialog = new QDialog(this);
+ colorDialog->setWindowTitle(tr("Color Options"));
+ colorDialog->setLayout(layout);
+ }
+ colorDialog->show();
+}
diff --git a/doc/src/snippets/multimedia-snippets/soundeffect.qml b/doc/src/snippets/multimedia-snippets/soundeffect.qml
new file mode 100644
index 000000000..080e378ec
--- /dev/null
+++ b/doc/src/snippets/multimedia-snippets/soundeffect.qml
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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$
+** 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$
+**
+****************************************************************************/
+
+//! [complete snippet]
+import Qt 4.7
+import QtMultimediaKit 1.1
+
+Text {
+ text: "Click Me!";
+ font.pointSize: 24;
+ width: 150; height: 50;
+
+ //! [play sound on click]
+ SoundEffect {
+ id: playSound
+ source: "soundeffect.wav"
+ }
+ MouseArea {
+ id: playArea
+ anchors.fill: parent
+ onPressed: { playSound.play() }
+ }
+ //! [play sound on click]
+}
+//! [complete snippet]
diff --git a/doc/src/snippets/multimedia-snippets/video.cpp b/doc/src/snippets/multimedia-snippets/video.cpp
new file mode 100644
index 000000000..d300f32a6
--- /dev/null
+++ b/doc/src/snippets/multimedia-snippets/video.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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$
+**
+****************************************************************************/
+
+/* Video related snippets */
+#include "qvideorenderercontrol.h"
+#include "qmediaservice.h"
+#include "qmediaplayer.h"
+#include "qabstractvideosurface.h"
+#include "qvideowidgetcontrol.h"
+#include "qvideowindowcontrol.h"
+#include "qgraphicsvideoitem.h"
+
+#include <QFormLayout>
+#include <QGraphicsView>
+
+class VideoExample : public QObject {
+ Q_OBJECT
+public:
+ void VideoGraphicsItem();
+ void VideoRendererControl();
+ void VideoWidget();
+ void VideoWindowControl();
+ void VideoWidgetControl();
+
+private:
+ // Common naming
+ QMediaService *mediaService;
+ QVideoWidget *videoWidget;
+ QWidget *widget;
+ QFormLayout *layout;
+ QAbstractVideoSurface *myVideoSurface;
+ QMediaPlayer *player;
+ QMediaContent video;
+ QGraphicsView *graphicsView;
+};
+
+void VideoExample::VideoRendererControl()
+{
+ //! [Video renderer control]
+ QVideoRendererControl *rendererControl = mediaService->requestControl<QVideoRendererControl *>();
+ rendererControl->setSurface(myVideoSurface);
+ //! [Video renderer control]
+}
+
+void VideoExample::VideoWidget()
+{
+ //! [Video widget]
+ player = new QMediaPlayer;
+
+ videoWidget = new QVideoWidget;
+
+ player->setVideoOutput(videoWidget);
+ player->setMedia(QUrl("http://example.com/movie.mp4"));
+
+ videoWidget->show();
+ player->play();
+ //! [Video widget]
+}
+
+void VideoExample::VideoWidgetControl()
+{
+ //! [Video widget control]
+ QVideoWidgetControl *widgetControl = mediaService->requestControl<QVideoWidgetControl *>();
+ layout->addWidget(widgetControl->videoWidget());
+ //! [Video widget control]
+}
+
+void VideoExample::VideoWindowControl()
+{
+ //! [Video window control]
+ QVideoWindowControl *windowControl = mediaService->requestControl<QVideoWindowControl *>();
+ windowControl->setWinId(widget->winId());
+ windowControl->setDisplayRect(widget->rect());
+ windowControl->setAspectRatioMode(Qt::KeepAspectRatio);
+ //! [Video window control]
+}
+
+void VideoExample::VideoGraphicsItem()
+{
+ //! [Video graphics item]
+ player = new QMediaPlayer(this);
+
+ QGraphicsVideoItem *item = new QGraphicsVideoItem;
+ player->setVideoOutput(item);
+ graphicsView->scene()->addItem(item);
+ graphicsView->show();
+
+ player->setMedia(video);
+ player->play();
+ //! [Video graphics item]
+}
diff --git a/doc/src/snippets/snippets.pro b/doc/src/snippets/snippets.pro
new file mode 100644
index 000000000..72459c249
--- /dev/null
+++ b/doc/src/snippets/snippets.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+
+!symbian: SUBDIRS += multimedia-snippets
diff --git a/examples/audiodevices/audiodevices.cpp b/examples/audiodevices/audiodevices.cpp
new file mode 100644
index 000000000..d020c9b60
--- /dev/null
+++ b/examples/audiodevices/audiodevices.cpp
@@ -0,0 +1,312 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <qaudiodeviceinfo.h>
+
+#include "audiodevices.h"
+
+// Utility functions for converting QAudioFormat fields into text
+
+QString toString(QAudioFormat::SampleType sampleType)
+{
+ QString result("Unknown");
+ switch (sampleType) {
+ case QAudioFormat::SignedInt:
+ result = "SignedInt";
+ break;
+ case QAudioFormat::UnSignedInt:
+ result = "UnSignedInt";
+ break;
+ case QAudioFormat::Float:
+ result = "Float";
+ break;
+ }
+ return result;
+}
+
+QString toString(QAudioFormat::Endian endian)
+{
+ QString result("Unknown");
+ switch (endian) {
+ case QAudioFormat::LittleEndian:
+ result = "LittleEndian";
+ break;
+ case QAudioFormat::BigEndian:
+ result = "BigEndian";
+ break;
+ }
+ return result;
+}
+
+
+AudioDevicesBase::AudioDevicesBase(QWidget *parent, Qt::WFlags f)
+ : QMainWindow(parent, f)
+{
+ setupUi(this);
+}
+
+AudioDevicesBase::~AudioDevicesBase() {}
+
+
+AudioTest::AudioTest(QWidget *parent, Qt::WFlags f)
+ : AudioDevicesBase(parent, f)
+{
+ mode = QAudio::AudioOutput;
+
+ connect(testButton, SIGNAL(clicked()), SLOT(test()));
+ connect(modeBox, SIGNAL(activated(int)), SLOT(modeChanged(int)));
+ connect(deviceBox, SIGNAL(activated(int)), SLOT(deviceChanged(int)));
+ connect(frequencyBox, SIGNAL(activated(int)), SLOT(freqChanged(int)));
+ connect(channelsBox, SIGNAL(activated(int)), SLOT(channelChanged(int)));
+ connect(codecsBox, SIGNAL(activated(int)), SLOT(codecChanged(int)));
+ connect(sampleSizesBox, SIGNAL(activated(int)), SLOT(sampleSizeChanged(int)));
+ connect(sampleTypesBox, SIGNAL(activated(int)), SLOT(sampleTypeChanged(int)));
+ connect(endianBox, SIGNAL(activated(int)), SLOT(endianChanged(int)));
+ connect(populateTableButton, SIGNAL(clicked()), SLOT(populateTable()));
+
+ modeBox->setCurrentIndex(0);
+ modeChanged(0);
+ deviceBox->setCurrentIndex(0);
+ deviceChanged(0);
+}
+
+AudioTest::~AudioTest()
+{
+}
+
+void AudioTest::test()
+{
+ // tries to set all the settings picked.
+ testResult->clear();
+
+ if (!deviceInfo.isNull()) {
+ if (deviceInfo.isFormatSupported(settings)) {
+ testResult->setText(tr("Success"));
+ nearestFreq->setText("");
+ nearestChannel->setText("");
+ nearestCodec->setText("");
+ nearestSampleSize->setText("");
+ nearestSampleType->setText("");
+ nearestEndian->setText("");
+ } else {
+ QAudioFormat nearest = deviceInfo.nearestFormat(settings);
+ testResult->setText(tr("Failed"));
+ nearestFreq->setText(QString("%1").arg(nearest.frequency()));
+ nearestChannel->setText(QString("%1").arg(nearest.channels()));
+ nearestCodec->setText(nearest.codec());
+ nearestSampleSize->setText(QString("%1").arg(nearest.sampleSize()));
+ nearestSampleType->setText(toString(nearest.sampleType()));
+ nearestEndian->setText(toString(nearest.byteOrder()));
+ }
+ }
+ else
+ testResult->setText(tr("No Device"));
+}
+
+void AudioTest::modeChanged(int idx)
+{
+ testResult->clear();
+
+ // mode has changed
+ if (idx == 0)
+ mode = QAudio::AudioInput;
+ else
+ mode = QAudio::AudioOutput;
+
+ deviceBox->clear();
+ foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(mode))
+ deviceBox->addItem(deviceInfo.deviceName(), qVariantFromValue(deviceInfo));
+
+ deviceBox->setCurrentIndex(0);
+ deviceChanged(0);
+}
+
+void AudioTest::deviceChanged(int idx)
+{
+ testResult->clear();
+
+ if (deviceBox->count() == 0)
+ return;
+
+ // device has changed
+ deviceInfo = deviceBox->itemData(idx).value<QAudioDeviceInfo>();
+
+ frequencyBox->clear();
+ QList<int> freqz = deviceInfo.supportedFrequencies();
+ for(int i = 0; i < freqz.size(); ++i)
+ frequencyBox->addItem(QString("%1").arg(freqz.at(i)));
+ if(freqz.size())
+ settings.setFrequency(freqz.at(0));
+
+ channelsBox->clear();
+ QList<int> chz = deviceInfo.supportedChannels();
+ for(int i = 0; i < chz.size(); ++i)
+ channelsBox->addItem(QString("%1").arg(chz.at(i)));
+ if(chz.size())
+ settings.setChannels(chz.at(0));
+
+ codecsBox->clear();
+ QStringList codecz = deviceInfo.supportedCodecs();
+ for (int i = 0; i < codecz.size(); ++i)
+ codecsBox->addItem(QString("%1").arg(codecz.at(i)));
+ if (codecz.size())
+ settings.setCodec(codecz.at(0));
+ // Add false to create failed condition!
+ codecsBox->addItem("audio/test");
+
+ sampleSizesBox->clear();
+ QList<int> sampleSizez = deviceInfo.supportedSampleSizes();
+ for (int i = 0; i < sampleSizez.size(); ++i)
+ sampleSizesBox->addItem(QString("%1").arg(sampleSizez.at(i)));
+ if (sampleSizez.size())
+ settings.setSampleSize(sampleSizez.at(0));
+
+ sampleTypesBox->clear();
+ QList<QAudioFormat::SampleType> sampleTypez = deviceInfo.supportedSampleTypes();
+
+ for (int i = 0; i < sampleTypez.size(); ++i)
+ sampleTypesBox->addItem(toString(sampleTypez.at(i)));
+ if (sampleTypez.size())
+ settings.setSampleType(sampleTypez.at(0));
+
+ endianBox->clear();
+ QList<QAudioFormat::Endian> endianz = deviceInfo.supportedByteOrders();
+ for (int i = 0; i < endianz.size(); ++i)
+ endianBox->addItem(toString(endianz.at(i)));
+ if (endianz.size())
+ settings.setByteOrder(endianz.at(0));
+
+ allFormatsTable->clearContents();
+}
+
+void AudioTest::populateTable()
+{
+ int row = 0;
+
+ QAudioFormat format;
+ foreach (QString codec, deviceInfo.supportedCodecs()) {
+ format.setCodec(codec);
+ foreach (int frequency, deviceInfo.supportedFrequencies()) {
+ format.setFrequency(frequency);
+ foreach (int channels, deviceInfo.supportedChannels()) {
+ format.setChannels(channels);
+ foreach (QAudioFormat::SampleType sampleType, deviceInfo.supportedSampleTypes()) {
+ format.setSampleType(sampleType);
+ foreach (int sampleSize, deviceInfo.supportedSampleSizes()) {
+ format.setSampleSize(sampleSize);
+ foreach (QAudioFormat::Endian endian, deviceInfo.supportedByteOrders()) {
+ format.setByteOrder(endian);
+ if (deviceInfo.isFormatSupported(format)) {
+ allFormatsTable->setRowCount(row + 1);
+
+ QTableWidgetItem *codecItem = new QTableWidgetItem(format.codec());
+ allFormatsTable->setItem(row, 0, codecItem);
+
+ QTableWidgetItem *frequencyItem = new QTableWidgetItem(QString("%1").arg(format.frequency()));
+ allFormatsTable->setItem(row, 1, frequencyItem);
+
+ QTableWidgetItem *channelsItem = new QTableWidgetItem(QString("%1").arg(format.channels()));
+ allFormatsTable->setItem(row, 2, channelsItem);
+
+ QTableWidgetItem *sampleTypeItem = new QTableWidgetItem(toString(format.sampleType()));
+ allFormatsTable->setItem(row, 3, sampleTypeItem);
+
+ QTableWidgetItem *sampleSizeItem = new QTableWidgetItem(QString("%1").arg(format.sampleSize()));
+ allFormatsTable->setItem(row, 4, sampleSizeItem);
+
+ QTableWidgetItem *byteOrderItem = new QTableWidgetItem(toString(format.byteOrder()));
+ allFormatsTable->setItem(row, 5, byteOrderItem);
+
+ ++row;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void AudioTest::freqChanged(int idx)
+{
+ // freq has changed
+ settings.setFrequency(frequencyBox->itemText(idx).toInt());
+}
+
+void AudioTest::channelChanged(int idx)
+{
+ settings.setChannels(channelsBox->itemText(idx).toInt());
+}
+
+void AudioTest::codecChanged(int idx)
+{
+ settings.setCodec(codecsBox->itemText(idx));
+}
+
+void AudioTest::sampleSizeChanged(int idx)
+{
+ settings.setSampleSize(sampleSizesBox->itemText(idx).toInt());
+}
+
+void AudioTest::sampleTypeChanged(int idx)
+{
+ switch (sampleTypesBox->itemText(idx).toInt()) {
+ case QAudioFormat::SignedInt:
+ settings.setSampleType(QAudioFormat::SignedInt);
+ break;
+ case QAudioFormat::UnSignedInt:
+ settings.setSampleType(QAudioFormat::UnSignedInt);
+ break;
+ case QAudioFormat::Float:
+ settings.setSampleType(QAudioFormat::Float);
+ }
+}
+
+void AudioTest::endianChanged(int idx)
+{
+ switch (endianBox->itemText(idx).toInt()) {
+ case QAudioFormat::LittleEndian:
+ settings.setByteOrder(QAudioFormat::LittleEndian);
+ break;
+ case QAudioFormat::BigEndian:
+ settings.setByteOrder(QAudioFormat::BigEndian);
+ }
+}
diff --git a/examples/audiodevices/audiodevices.h b/examples/audiodevices/audiodevices.h
new file mode 100644
index 000000000..2938bfced
--- /dev/null
+++ b/examples/audiodevices/audiodevices.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AUDIODEVICES_H
+#define AUDIODEVICES_H
+
+#include <QObject>
+#include <QMainWindow>
+#include <qaudiodeviceinfo.h>
+
+#include "ui_audiodevicesbase.h"
+
+class AudioDevicesBase : public QMainWindow, public Ui::AudioDevicesBase
+{
+public:
+ AudioDevicesBase(QWidget *parent = 0, Qt::WFlags f = 0);
+ virtual ~AudioDevicesBase();
+};
+
+class AudioTest : public AudioDevicesBase
+{
+ Q_OBJECT
+public:
+ AudioTest(QWidget *parent = 0, Qt::WFlags f = 0);
+ virtual ~AudioTest();
+
+ QAudioDeviceInfo deviceInfo;
+ QAudioFormat settings;
+ QAudio::Mode mode;
+
+private slots:
+ void modeChanged(int idx);
+ void deviceChanged(int idx);
+ void freqChanged(int idx);
+ void channelChanged(int idx);
+ void codecChanged(int idx);
+ void sampleSizeChanged(int idx);
+ void sampleTypeChanged(int idx);
+ void endianChanged(int idx);
+ void test();
+ void populateTable();
+
+};
+
+#endif
+
diff --git a/examples/audiodevices/audiodevices.pro b/examples/audiodevices/audiodevices.pro
new file mode 100644
index 000000000..2af690b8c
--- /dev/null
+++ b/examples/audiodevices/audiodevices.pro
@@ -0,0 +1,21 @@
+TEMPLATE = app
+CONFIG += example
+
+INCLUDEPATH += ../../src/multimedia ../../src/multimedia/audio
+include(../mobility_examples.pri)
+
+CONFIG += mobility
+MOBILITY = multimedia
+
+QMAKE_RPATHDIR += $$DESTDIR
+
+HEADERS = audiodevices.h
+
+SOURCES = audiodevices.cpp \
+ main.cpp
+
+FORMS += audiodevicesbase.ui
+
+symbian {
+ TARGET.CAPABILITY = UserEnvironment WriteDeviceData ReadDeviceData
+}
diff --git a/examples/audiodevices/audiodevicesbase.ui b/examples/audiodevices/audiodevicesbase.ui
new file mode 100644
index 000000000..23b45d736
--- /dev/null
+++ b/examples/audiodevices/audiodevicesbase.ui
@@ -0,0 +1,399 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AudioDevicesBase</class>
+ <widget class="QMainWindow" name="AudioDevicesBase">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>679</width>
+ <height>598</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Audio Devices</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QScrollArea" name="scrollArea">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="scrollAreaWidgetContents">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>659</width>
+ <height>558</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="modeLabel">
+ <property name="text">
+ <string>Mode</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="deviceLabel">
+ <property name="text">
+ <string>Device</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QComboBox" name="modeBox">
+ <item>
+ <property name="text">
+ <string>Input</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Output</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="deviceBox"/>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="testFormatTab">
+ <attribute name="title">
+ <string>Test format</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="1">
+ <widget class="QLabel" name="actualLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="text">
+ <string>&lt;i&gt;Actual Settings&lt;/i&gt;</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="nearestLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="text">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Nearest Settings&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="frequencyBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QLineEdit" name="nearestFreq">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QComboBox" name="channelsBox"/>
+ </item>
+ <item row="5" column="2">
+ <widget class="QLineEdit" name="nearestChannel">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="1">
+ <widget class="QComboBox" name="sampleSizesBox"/>
+ </item>
+ <item row="9" column="2">
+ <widget class="QLineEdit" name="nearestSampleSize">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="14" column="1">
+ <widget class="QComboBox" name="endianBox"/>
+ </item>
+ <item row="14" column="2">
+ <widget class="QLineEdit" name="nearestEndian">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="15" column="1">
+ <widget class="QPushButton" name="testButton">
+ <property name="text">
+ <string>Test</string>
+ </property>
+ </widget>
+ </item>
+ <item row="15" column="2">
+ <widget class="QLabel" name="testResult">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="actualFreqLabel">
+ <property name="text">
+ <string>Frequency (Hz)</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="actualChannelLabel">
+ <property name="text">
+ <string>Channels</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="0">
+ <widget class="QLabel" name="actualSampleSizeLabel">
+ <property name="text">
+ <string>Sample size (bits)</string>
+ </property>
+ </widget>
+ </item>
+ <item row="14" column="0">
+ <widget class="QLabel" name="actualEndianLabel">
+ <property name="text">
+ <string>Endianess</string>
+ </property>
+ </widget>
+ </item>
+ <item row="16" column="0" colspan="3">
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Note: an invalid codec 'audio/test' exists in order to allow an invalid format to be constructed, and therefore to trigger a 'nearest format' calculation.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="actualCodecLabel">
+ <property name="text">
+ <string>Codec</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QLineEdit" name="nearestCodec">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="codecsBox"/>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="actualSampleTypeLabel">
+ <property name="text">
+ <string>SampleType</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QComboBox" name="sampleTypesBox"/>
+ </item>
+ <item row="6" column="2">
+ <widget class="QLineEdit" name="nearestSampleType">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>All formats</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QPushButton" name="populateTableButton">
+ <property name="text">
+ <string>Populate table</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTableWidget" name="allFormatsTable">
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="dragDropOverwriteMode">
+ <bool>false</bool>
+ </property>
+ <property name="selectionMode">
+ <enum>QAbstractItemView::NoSelection</enum>
+ </property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectItems</enum>
+ </property>
+ <property name="textElideMode">
+ <enum>Qt::ElideNone</enum>
+ </property>
+ <property name="sortingEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ <property name="cornerButtonEnabled">
+ <bool>false</bool>
+ </property>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="verticalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="verticalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ <column>
+ <property name="text">
+ <string>Codec</string>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Frequency (Hz)</string>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Channels</string>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Sample type</string>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Sample size (bits)</string>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Endianness</string>
+ </property>
+ <property name="textAlignment">
+ <set>AlignHCenter|AlignVCenter|AlignCenter</set>
+ </property>
+ </column>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/audioinput/audioinput.cpp b/examples/audioinput/audioinput.cpp
new file mode 100644
index 000000000..aa008df1a
--- /dev/null
+++ b/examples/audioinput/audioinput.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <stdlib.h>
+#include <math.h>
+
+#include <QDebug>
+#include <QPainter>
+#include <QVBoxLayout>
+
+#include <qaudiodeviceinfo.h>
+#include <qaudioinput.h>
+
+#include <QtCore/qendian.h>
+
+#include "audioinput.h"
+
+const QString InputTest::PushModeLabel(tr("Enable push mode"));
+const QString InputTest::PullModeLabel(tr("Enable pull mode"));
+const QString InputTest::SuspendLabel(tr("Suspend recording"));
+const QString InputTest::ResumeLabel(tr("Resume recording"));
+
+const int BufferSize = 4096;
+
+AudioInfo::AudioInfo(const QAudioFormat &format, QObject *parent)
+ : QIODevice(parent)
+ , m_format(format)
+ , m_maxAmplitude(0)
+ , m_level(0.0)
+
+{
+ switch (m_format.sampleSize()) {
+ case 8:
+ switch (m_format.sampleType()) {
+ case QAudioFormat::UnSignedInt:
+ m_maxAmplitude = 255;
+ break;
+ case QAudioFormat::SignedInt:
+ m_maxAmplitude = 127;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 16:
+ switch (m_format.sampleType()) {
+ case QAudioFormat::UnSignedInt:
+ m_maxAmplitude = 65535;
+ break;
+ case QAudioFormat::SignedInt:
+ m_maxAmplitude = 32767;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+AudioInfo::~AudioInfo()
+{
+}
+
+void AudioInfo::start()
+{
+ open(QIODevice::WriteOnly);
+}
+
+void AudioInfo::stop()
+{
+ close();
+}
+
+qint64 AudioInfo::readData(char *data, qint64 maxlen)
+{
+ Q_UNUSED(data)
+ Q_UNUSED(maxlen)
+
+ return 0;
+}
+
+qint64 AudioInfo::writeData(const char *data, qint64 len)
+{
+ if (m_maxAmplitude) {
+ Q_ASSERT(m_format.sampleSize() % 8 == 0);
+ const int channelBytes = m_format.sampleSize() / 8;
+ const int sampleBytes = m_format.channels() * channelBytes;
+ Q_ASSERT(len % sampleBytes == 0);
+ const int numSamples = len / sampleBytes;
+
+ quint16 maxValue = 0;
+ const unsigned char *ptr = reinterpret_cast<const unsigned char *>(data);
+
+ for (int i = 0; i < numSamples; ++i) {
+ for(int j = 0; j < m_format.channels(); ++j) {
+ quint16 value = 0;
+
+ if (m_format.sampleSize() == 8 && m_format.sampleType() == QAudioFormat::UnSignedInt) {
+ value = *reinterpret_cast<const quint8*>(ptr);
+ } else if (m_format.sampleSize() == 8 && m_format.sampleType() == QAudioFormat::SignedInt) {
+ value = qAbs(*reinterpret_cast<const qint8*>(ptr));
+ } else if (m_format.sampleSize() == 16 && m_format.sampleType() == QAudioFormat::UnSignedInt) {
+ if (m_format.byteOrder() == QAudioFormat::LittleEndian)
+ value = qFromLittleEndian<quint16>(ptr);
+ else
+ value = qFromBigEndian<quint16>(ptr);
+ } else if (m_format.sampleSize() == 16 && m_format.sampleType() == QAudioFormat::SignedInt) {
+ if (m_format.byteOrder() == QAudioFormat::LittleEndian)
+ value = qAbs(qFromLittleEndian<qint16>(ptr));
+ else
+ value = qAbs(qFromBigEndian<qint16>(ptr));
+ }
+
+ maxValue = qMax(value, maxValue);
+ ptr += channelBytes;
+ }
+ }
+
+ maxValue = qMin(maxValue, m_maxAmplitude);
+ m_level = qreal(maxValue) / m_maxAmplitude;
+ }
+
+ emit update();
+ return len;
+}
+
+RenderArea::RenderArea(QWidget *parent)
+ : QWidget(parent)
+{
+ setBackgroundRole(QPalette::Base);
+ setAutoFillBackground(true);
+
+ m_level = 0;
+ setMinimumHeight(30);
+ setMinimumWidth(200);
+}
+
+void RenderArea::paintEvent(QPaintEvent * /* event */)
+{
+ QPainter painter(this);
+
+ painter.setPen(Qt::black);
+ painter.drawRect(QRect(painter.viewport().left()+10,
+ painter.viewport().top()+10,
+ painter.viewport().right()-20,
+ painter.viewport().bottom()-20));
+ if (m_level == 0.0)
+ return;
+
+ int pos = ((painter.viewport().right()-20)-(painter.viewport().left()+11))*m_level;
+ painter.fillRect(painter.viewport().left()+11,
+ painter.viewport().top()+10,
+ pos,
+ painter.viewport().height()-21,
+ Qt::red);
+}
+
+void RenderArea::setLevel(qreal value)
+{
+ m_level = value;
+ update();
+}
+
+
+InputTest::InputTest()
+ : m_canvas(0)
+ , m_modeButton(0)
+ , m_suspendResumeButton(0)
+ , m_deviceBox(0)
+ , m_device(QAudioDeviceInfo::defaultInputDevice())
+ , m_audioInfo(0)
+ , m_audioInput(0)
+ , m_input(0)
+ , m_pullMode(false)
+ , m_buffer(BufferSize, 0)
+{
+ initializeWindow();
+ initializeAudio();
+}
+
+InputTest::~InputTest() {}
+
+void InputTest::initializeWindow()
+{
+ QScopedPointer<QWidget> window(new QWidget);
+ QScopedPointer<QVBoxLayout> layout(new QVBoxLayout);
+
+ m_canvas = new RenderArea(this);
+ layout->addWidget(m_canvas);
+
+ m_deviceBox = new QComboBox(this);
+ QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
+ for(int i = 0; i < devices.size(); ++i)
+ m_deviceBox->addItem(devices.at(i).deviceName(), qVariantFromValue(devices.at(i)));
+
+ connect(m_deviceBox, SIGNAL(activated(int)), SLOT(deviceChanged(int)));
+ layout->addWidget(m_deviceBox);
+
+ m_modeButton = new QPushButton(this);
+ m_modeButton->setText(PushModeLabel);
+ connect(m_modeButton, SIGNAL(clicked()), SLOT(toggleMode()));
+ layout->addWidget(m_modeButton);
+
+ m_suspendResumeButton = new QPushButton(this);
+ m_suspendResumeButton->setText(SuspendLabel);
+ connect(m_suspendResumeButton, SIGNAL(clicked()), SLOT(toggleSuspend()));
+ layout->addWidget(m_suspendResumeButton);
+
+ window->setLayout(layout.data());
+ layout.take(); // ownership transferred
+
+ setCentralWidget(window.data());
+ QWidget *const windowPtr = window.take(); // ownership transferred
+ windowPtr->show();
+}
+
+void InputTest::initializeAudio()
+{
+ m_pullMode = true;
+
+ m_format.setFrequency(8000);
+ m_format.setChannels(1);
+ m_format.setSampleSize(16);
+ m_format.setSampleType(QAudioFormat::SignedInt);
+ m_format.setByteOrder(QAudioFormat::LittleEndian);
+ m_format.setCodec("audio/pcm");
+
+ QAudioDeviceInfo info(QAudioDeviceInfo::defaultInputDevice());
+ if (!info.isFormatSupported(m_format)) {
+ qWarning() << "Default format not supported - trying to use nearest";
+ m_format = info.nearestFormat(m_format);
+ }
+
+ m_audioInfo = new AudioInfo(m_format, this);
+ connect(m_audioInfo, SIGNAL(update()), SLOT(refreshDisplay()));
+
+ createAudioInput();
+}
+
+void InputTest::createAudioInput()
+{
+ m_audioInput = new QAudioInput(m_device, m_format, this);
+ connect(m_audioInput, SIGNAL(notify()), SLOT(notified()));
+ connect(m_audioInput, SIGNAL(stateChanged(QAudio::State)), SLOT(stateChanged(QAudio::State)));
+ m_audioInfo->start();
+ m_audioInput->start(m_audioInfo);
+}
+
+void InputTest::notified()
+{
+ qWarning() << "bytesReady = " << m_audioInput->bytesReady()
+ << ", " << "elapsedUSecs = " <<m_audioInput->elapsedUSecs()
+ << ", " << "processedUSecs = "<<m_audioInput->processedUSecs();
+}
+
+void InputTest::readMore()
+{
+ if(!m_audioInput)
+ return;
+ qint64 len = m_audioInput->bytesReady();
+ if(len > BufferSize)
+ len = BufferSize;
+ qint64 l = m_input->read(m_buffer.data(), len);
+ if(l > 0) {
+ m_audioInfo->write(m_buffer.constData(), l);
+ }
+}
+
+void InputTest::toggleMode()
+{
+ // Change bewteen pull and push modes
+ m_audioInput->stop();
+
+ if (m_pullMode) {
+ m_modeButton->setText(PullModeLabel);
+ m_input = m_audioInput->start();
+ connect(m_input, SIGNAL(readyRead()), SLOT(readMore()));
+ m_pullMode = false;
+ } else {
+ m_modeButton->setText(PushModeLabel);
+ m_pullMode = true;
+ m_audioInput->start(m_audioInfo);
+ }
+
+ m_suspendResumeButton->setText(SuspendLabel);
+}
+
+void InputTest::toggleSuspend()
+{
+ // toggle suspend/resume
+ if(m_audioInput->state() == QAudio::SuspendedState) {
+ qWarning() << "status: Suspended, resume()";
+ m_audioInput->resume();
+ m_suspendResumeButton->setText(SuspendLabel);
+ } else if (m_audioInput->state() == QAudio::ActiveState) {
+ qWarning() << "status: Active, suspend()";
+ m_audioInput->suspend();
+ m_suspendResumeButton->setText(ResumeLabel);
+ } else if (m_audioInput->state() == QAudio::StoppedState) {
+ qWarning() << "status: Stopped, resume()";
+ m_audioInput->resume();
+ m_suspendResumeButton->setText(SuspendLabel);
+ } else if (m_audioInput->state() == QAudio::IdleState) {
+ qWarning() << "status: IdleState";
+ }
+}
+
+void InputTest::stateChanged(QAudio::State state)
+{
+ qWarning() << "state = " << state;
+}
+
+void InputTest::refreshDisplay()
+{
+ m_canvas->setLevel(m_audioInfo->level());
+}
+
+void InputTest::deviceChanged(int index)
+{
+ m_audioInfo->stop();
+ m_audioInput->stop();
+ m_audioInput->disconnect(this);
+ delete m_audioInput;
+
+ m_device = m_deviceBox->itemData(index).value<QAudioDeviceInfo>();
+ createAudioInput();
+}
diff --git a/examples/audioinput/audioinput.h b/examples/audioinput/audioinput.h
new file mode 100644
index 000000000..540e79845
--- /dev/null
+++ b/examples/audioinput/audioinput.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AUDIOINPUT_H
+#define AUDIOINPUT_H
+
+#include <QPixmap>
+#include <QWidget>
+#include <QObject>
+#include <QMainWindow>
+#include <QPushButton>
+#include <QComboBox>
+#include <QByteArray>
+
+#include <qaudioinput.h>
+
+class AudioInfo : public QIODevice
+{
+ Q_OBJECT
+public:
+ AudioInfo(const QAudioFormat &format, QObject *parent);
+ ~AudioInfo();
+
+ void start();
+ void stop();
+
+ qreal level() const { return m_level; }
+
+ qint64 readData(char *data, qint64 maxlen);
+ qint64 writeData(const char *data, qint64 len);
+
+private:
+ const QAudioFormat m_format;
+ quint16 m_maxAmplitude;
+ qreal m_level; // 0.0 <= m_level <= 1.0
+
+signals:
+ void update();
+};
+
+
+class RenderArea : public QWidget
+{
+ Q_OBJECT
+
+public:
+ RenderArea(QWidget *parent = 0);
+
+ void setLevel(qreal value);
+
+protected:
+ void paintEvent(QPaintEvent *event);
+
+private:
+ qreal m_level;
+ QPixmap m_pixmap;
+};
+
+class InputTest : public QMainWindow
+{
+ Q_OBJECT
+public:
+ InputTest();
+ ~InputTest();
+
+private:
+ void initializeWindow();
+ void initializeAudio();
+ void createAudioInput();
+
+private slots:
+ void refreshDisplay();
+ void notified();
+ void readMore();
+ void toggleMode();
+ void toggleSuspend();
+ void stateChanged(QAudio::State state);
+ void deviceChanged(int index);
+
+private:
+ // Owned by layout
+ RenderArea *m_canvas;
+ QPushButton *m_modeButton;
+ QPushButton *m_suspendResumeButton;
+ QComboBox *m_deviceBox;
+
+ QAudioDeviceInfo m_device;
+ AudioInfo *m_audioInfo;
+ QAudioFormat m_format;
+ QAudioInput *m_audioInput;
+ QIODevice *m_input;
+ bool m_pullMode;
+ QByteArray m_buffer;
+
+ static const QString PushModeLabel;
+ static const QString PullModeLabel;
+ static const QString SuspendLabel;
+ static const QString ResumeLabel;
+};
+
+#endif
+
diff --git a/examples/audioinput/audioinput.pro b/examples/audioinput/audioinput.pro
new file mode 100644
index 000000000..80daa8d65
--- /dev/null
+++ b/examples/audioinput/audioinput.pro
@@ -0,0 +1,16 @@
+TEMPLATE = app
+CONFIG += example
+
+INCLUDEPATH += ../../src/multimedia ../../src/multimedia/audio
+include(../mobility_examples.pri)
+
+CONFIG += mobility
+MOBILITY = multimedia
+
+QMAKE_RPATHDIR += $$DESTDIR
+
+HEADERS = audioinput.h
+
+SOURCES = audioinput.cpp \
+ main.cpp
+
diff --git a/examples/audioinput/main.cpp b/examples/audioinput/main.cpp
new file mode 100644
index 000000000..c14d1c843
--- /dev/null
+++ b/examples/audioinput/main.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include "audioinput.h"
+
+int main(int argv, char **args)
+{
+ QApplication app(argv, args);
+ app.setApplicationName("Audio Input Test");
+
+ InputTest input;
+ input.show();
+
+ return app.exec();
+}
diff --git a/examples/audiooutput/audiooutput.cpp b/examples/audiooutput/audiooutput.cpp
new file mode 100644
index 000000000..df0b226bb
--- /dev/null
+++ b/examples/audiooutput/audiooutput.cpp
@@ -0,0 +1,314 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include <QVBoxLayout>
+
+#include <qaudiooutput.h>
+#include <qaudiodeviceinfo.h>
+#include <QtCore/qmath.h>
+#include <QtCore/qendian.h>
+#include "audiooutput.h"
+
+const QString AudioTest::PushModeLabel(tr("Enable push mode"));
+const QString AudioTest::PullModeLabel(tr("Enable pull mode"));
+const QString AudioTest::SuspendLabel(tr("Suspend playback"));
+const QString AudioTest::ResumeLabel(tr("Resume playback"));
+
+const int DurationSeconds = 1;
+const int ToneFrequencyHz = 600;
+const int DataFrequencyHz = 44100;
+const int BufferSize = 32768;
+
+
+Generator::Generator(const QAudioFormat &format,
+ qint64 durationUs,
+ int frequency,
+ QObject *parent)
+ : QIODevice(parent)
+ , m_pos(0)
+{
+ generateData(format, durationUs, frequency);
+}
+
+Generator::~Generator()
+{
+
+}
+
+void Generator::start()
+{
+ open(QIODevice::ReadOnly);
+}
+
+void Generator::stop()
+{
+ m_pos = 0;
+ close();
+}
+
+void Generator::generateData(const QAudioFormat &format, qint64 durationUs, int frequency)
+{
+ const int channelBytes = format.sampleSize() / 8;
+ const int sampleBytes = format.channels() * channelBytes;
+
+ qint64 length = (format.frequency() * format.channels() * (format.sampleSize() / 8))
+ * durationUs / 100000;
+
+ Q_ASSERT(length % sampleBytes == 0);
+ Q_UNUSED(sampleBytes) // suppress warning in release builds
+
+ m_buffer.resize(length);
+ unsigned char *ptr = reinterpret_cast<unsigned char *>(m_buffer.data());
+ int sampleIndex = 0;
+
+ while (length) {
+ const qreal x = qSin(2 * M_PI * frequency * qreal(sampleIndex % format.frequency()) / format.frequency());
+ for (int i=0; i<format.channels(); ++i) {
+ if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::UnSignedInt) {
+ const quint8 value = static_cast<quint8>((1.0 + x) / 2 * 255);
+ *reinterpret_cast<quint8*>(ptr) = value;
+ } else if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::SignedInt) {
+ const qint8 value = static_cast<qint8>(x * 127);
+ *reinterpret_cast<quint8*>(ptr) = value;
+ } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::UnSignedInt) {
+ quint16 value = static_cast<quint16>((1.0 + x) / 2 * 65535);
+ if (format.byteOrder() == QAudioFormat::LittleEndian)
+ qToLittleEndian<quint16>(value, ptr);
+ else
+ qToBigEndian<quint16>(value, ptr);
+ } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::SignedInt) {
+ qint16 value = static_cast<qint16>(x * 32767);
+ if (format.byteOrder() == QAudioFormat::LittleEndian)
+ qToLittleEndian<qint16>(value, ptr);
+ else
+ qToBigEndian<qint16>(value, ptr);
+ }
+
+ ptr += channelBytes;
+ length -= channelBytes;
+ }
+ ++sampleIndex;
+ }
+}
+
+qint64 Generator::readData(char *data, qint64 len)
+{
+ qint64 total = 0;
+ while (len - total > 0) {
+ const qint64 chunk = qMin((m_buffer.size() - m_pos), len - total);
+ memcpy(data + total, m_buffer.constData() + m_pos, chunk);
+ m_pos = (m_pos + chunk) % m_buffer.size();
+ total += chunk;
+ }
+ return total;
+}
+
+qint64 Generator::writeData(const char *data, qint64 len)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(len);
+
+ return 0;
+}
+
+qint64 Generator::bytesAvailable() const
+{
+ return m_buffer.size() + QIODevice::bytesAvailable();
+}
+
+AudioTest::AudioTest()
+ : m_pullTimer(new QTimer(this))
+ , m_modeButton(0)
+ , m_suspendResumeButton(0)
+ , m_deviceBox(0)
+ , m_device(QAudioDeviceInfo::defaultOutputDevice())
+ , m_generator(0)
+ , m_audioOutput(0)
+ , m_output(0)
+ , m_buffer(BufferSize, 0)
+{
+ initializeWindow();
+ initializeAudio();
+}
+
+void AudioTest::initializeWindow()
+{
+ QScopedPointer<QWidget> window(new QWidget);
+ QScopedPointer<QVBoxLayout> layout(new QVBoxLayout);
+
+ m_deviceBox = new QComboBox(this);
+ foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput))
+ m_deviceBox->addItem(deviceInfo.deviceName(), qVariantFromValue(deviceInfo));
+ connect(m_deviceBox,SIGNAL(activated(int)),SLOT(deviceChanged(int)));
+ layout->addWidget(m_deviceBox);
+
+ m_modeButton = new QPushButton(this);
+ m_modeButton->setText(PushModeLabel);
+ connect(m_modeButton, SIGNAL(clicked()), SLOT(toggleMode()));
+ layout->addWidget(m_modeButton);
+
+ m_suspendResumeButton = new QPushButton(this);
+ m_suspendResumeButton->setText(SuspendLabel);
+ connect(m_suspendResumeButton, SIGNAL(clicked()), SLOT(toggleSuspendResume()));
+ layout->addWidget(m_suspendResumeButton);
+
+ window->setLayout(layout.data());
+ layout.take(); // ownership transferred
+
+ setCentralWidget(window.data());
+ QWidget *const windowPtr = window.take(); // ownership transferred
+ windowPtr->show();
+}
+
+void AudioTest::initializeAudio()
+{
+ connect(m_pullTimer, SIGNAL(timeout()), SLOT(pullTimerExpired()));
+
+ m_pullMode = true;
+
+ m_format.setFrequency(DataFrequencyHz);
+ m_format.setChannels(1);
+ m_format.setSampleSize(16);
+ m_format.setCodec("audio/pcm");
+ m_format.setByteOrder(QAudioFormat::LittleEndian);
+ m_format.setSampleType(QAudioFormat::SignedInt);
+
+ QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
+ if (!info.isFormatSupported(m_format)) {
+ qWarning() << "Default format not supported - trying to use nearest";
+ m_format = info.nearestFormat(m_format);
+ }
+
+ m_generator = new Generator(m_format, DurationSeconds*1000000, ToneFrequencyHz, this);
+
+ createAudioOutput();
+}
+
+void AudioTest::createAudioOutput()
+{
+ delete m_audioOutput;
+ m_audioOutput = 0;
+ m_audioOutput = new QAudioOutput(m_device, m_format, this);
+ connect(m_audioOutput, SIGNAL(notify()), SLOT(notified()));
+ connect(m_audioOutput, SIGNAL(stateChanged(QAudio::State)), SLOT(stateChanged(QAudio::State)));
+ m_generator->start();
+ m_audioOutput->start(m_generator);
+}
+
+AudioTest::~AudioTest()
+{
+
+}
+
+void AudioTest::deviceChanged(int index)
+{
+ m_pullTimer->stop();
+ m_generator->stop();
+ m_audioOutput->stop();
+ m_audioOutput->disconnect(this);
+ m_device = m_deviceBox->itemData(index).value<QAudioDeviceInfo>();
+ createAudioOutput();
+}
+
+void AudioTest::notified()
+{
+ qWarning() << "bytesFree = " << m_audioOutput->bytesFree()
+ << ", " << "elapsedUSecs = " << m_audioOutput->elapsedUSecs()
+ << ", " << "processedUSecs = " << m_audioOutput->processedUSecs();
+}
+
+void AudioTest::pullTimerExpired()
+{
+ if (m_audioOutput && m_audioOutput->state() != QAudio::StoppedState) {
+ int chunks = m_audioOutput->bytesFree()/m_audioOutput->periodSize();
+ while (chunks) {
+ const qint64 len = m_generator->read(m_buffer.data(), m_audioOutput->periodSize());
+ if (len)
+ m_output->write(m_buffer.data(), len);
+ if (len != m_audioOutput->periodSize())
+ break;
+ --chunks;
+ }
+ }
+}
+
+void AudioTest::toggleMode()
+{
+ m_pullTimer->stop();
+ m_audioOutput->stop();
+
+ if (m_pullMode) {
+ m_modeButton->setText(PullModeLabel);
+ m_output = m_audioOutput->start();
+ m_pullMode = false;
+ m_pullTimer->start(20);
+ } else {
+ m_modeButton->setText(PushModeLabel);
+ m_pullMode = true;
+ m_audioOutput->start(m_generator);
+ }
+
+ m_suspendResumeButton->setText(SuspendLabel);
+}
+
+void AudioTest::toggleSuspendResume()
+{
+ if (m_audioOutput->state() == QAudio::SuspendedState) {
+ qWarning() << "status: Suspended, resume()";
+ m_audioOutput->resume();
+ m_suspendResumeButton->setText(SuspendLabel);
+ } else if (m_audioOutput->state() == QAudio::ActiveState) {
+ qWarning() << "status: Active, suspend()";
+ m_audioOutput->suspend();
+ m_suspendResumeButton->setText(ResumeLabel);
+ } else if (m_audioOutput->state() == QAudio::StoppedState) {
+ qWarning() << "status: Stopped, resume()";
+ m_audioOutput->resume();
+ m_suspendResumeButton->setText(SuspendLabel);
+ } else if (m_audioOutput->state() == QAudio::IdleState) {
+ qWarning() << "status: IdleState";
+ }
+}
+
+void AudioTest::stateChanged(QAudio::State state)
+{
+ qWarning() << "state = " << state;
+}
diff --git a/examples/audiooutput/audiooutput.h b/examples/audiooutput/audiooutput.h
new file mode 100644
index 000000000..805168e7c
--- /dev/null
+++ b/examples/audiooutput/audiooutput.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AUDIOOUTPUT_H
+#define AUDIOOUTPUT_H
+
+#include <math.h>
+
+#include <QObject>
+#include <QMainWindow>
+#include <QIODevice>
+#include <QTimer>
+#include <QPushButton>
+#include <QComboBox>
+#include <QByteArray>
+
+#include <qaudiooutput.h>
+
+class Generator : public QIODevice
+{
+ Q_OBJECT
+public:
+ Generator(const QAudioFormat &format, qint64 durationUs, int frequency, QObject *parent);
+ ~Generator();
+
+ void start();
+ void stop();
+
+ qint64 readData(char *data, qint64 maxlen);
+ qint64 writeData(const char *data, qint64 len);
+ qint64 bytesAvailable() const;
+
+private:
+ void generateData(const QAudioFormat &format, qint64 durationUs, int frequency);
+
+private:
+ qint64 m_pos;
+ QByteArray m_buffer;
+};
+
+class AudioTest : public QMainWindow
+{
+ Q_OBJECT
+public:
+ AudioTest();
+ ~AudioTest();
+
+private:
+ void initializeWindow();
+ void initializeAudio();
+ void createAudioOutput();
+
+private:
+ QTimer* m_pullTimer;
+
+ // Owned by layout
+ QPushButton* m_modeButton;
+ QPushButton* m_suspendResumeButton;
+ QComboBox* m_deviceBox;
+
+ QAudioDeviceInfo m_device;
+ Generator* m_generator;
+ QAudioOutput* m_audioOutput;
+ QIODevice* m_output; // not owned
+ QAudioFormat m_format;
+
+ bool m_pullMode;
+ QByteArray m_buffer;
+
+ static const QString PushModeLabel;
+ static const QString PullModeLabel;
+ static const QString SuspendLabel;
+ static const QString ResumeLabel;
+
+private slots:
+ void notified();
+ void pullTimerExpired();
+ void toggleMode();
+ void toggleSuspendResume();
+ void stateChanged(QAudio::State state);
+ void deviceChanged(int index);
+};
+
+#endif
+
diff --git a/examples/audiooutput/audiooutput.pro b/examples/audiooutput/audiooutput.pro
new file mode 100644
index 000000000..63d037f60
--- /dev/null
+++ b/examples/audiooutput/audiooutput.pro
@@ -0,0 +1,15 @@
+TEMPLATE = app
+CONFIG += example
+
+INCLUDEPATH += ../../src/multimedia ../../src/multimedia/audio
+include(../mobility_examples.pri)
+
+CONFIG += mobility
+MOBILITY = multimedia
+
+QMAKE_RPATHDIR += $$DESTDIR
+
+HEADERS = audiooutput.h
+
+SOURCES = audiooutput.cpp \
+ main.cpp
diff --git a/examples/audiooutput/main.cpp b/examples/audiooutput/main.cpp
new file mode 100644
index 000000000..93f972d04
--- /dev/null
+++ b/examples/audiooutput/main.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtGui>
+
+#include "audiooutput.h"
+
+int main(int argv, char **args)
+{
+ QApplication app(argv, args);
+ app.setApplicationName("Audio Output Test");
+
+ AudioTest audio;
+ audio.show();
+
+ return app.exec();
+}
diff --git a/examples/audiorecorder/audiorecorder.cpp b/examples/audiorecorder/audiorecorder.cpp
new file mode 100644
index 000000000..e4d28df14
--- /dev/null
+++ b/examples/audiorecorder/audiorecorder.cpp
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qdir.h>
+#include <QtGui/qfiledialog.h>
+
+#include <qaudiocapturesource.h>
+#include <qmediarecorder.h>
+
+#include "audiorecorder.h"
+
+#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) || defined(SYMBIAN_S60_3X)
+#include "ui_audiorecorder_small.h"
+#else
+#include "ui_audiorecorder.h"
+#endif
+
+AudioRecorder::AudioRecorder(QWidget *parent)
+ :
+ QMainWindow(parent),
+ ui(new Ui::AudioRecorder),
+ outputLocationSet(false)
+{
+ ui->setupUi(this);
+
+ audiosource = new QAudioCaptureSource(this);
+ capture = new QMediaRecorder(audiosource, this);
+
+ //audio devices
+ ui->audioDeviceBox->addItem(tr("Default"), QVariant(QString()));
+ foreach(const QString &device, audiosource->audioInputs()) {
+ ui->audioDeviceBox->addItem(device, QVariant(device));
+ }
+
+ //audio codecs
+ ui->audioCodecBox->addItem(tr("Default"), QVariant(QString()));
+ foreach(const QString &codecName, capture->supportedAudioCodecs()) {
+ ui->audioCodecBox->addItem(codecName, QVariant(codecName));
+ }
+
+ //containers
+ ui->containerBox->addItem(tr("Default"), QVariant(QString()));
+ foreach(const QString &containerName, capture->supportedContainers()) {
+ ui->containerBox->addItem(containerName, QVariant(containerName));
+ }
+
+ //sample rate:
+ ui->sampleRateBox->addItem(tr("Default"), QVariant(0));
+ foreach(int sampleRate, capture->supportedAudioSampleRates()) {
+ ui->sampleRateBox->addItem(QString::number(sampleRate), QVariant(
+ sampleRate));
+ }
+
+ ui->qualitySlider->setRange(0, int(QtMultimediaKit::VeryHighQuality));
+ ui->qualitySlider->setValue(int(QtMultimediaKit::NormalQuality));
+
+ //bitrates:
+ ui->bitrateBox->addItem(QString("Default"), QVariant(0));
+ ui->bitrateBox->addItem(QString("32000"), QVariant(32000));
+ ui->bitrateBox->addItem(QString("64000"), QVariant(64000));
+ ui->bitrateBox->addItem(QString("96000"), QVariant(96000));
+ ui->bitrateBox->addItem(QString("128000"), QVariant(128000));
+
+ connect(capture, SIGNAL(durationChanged(qint64)), this,
+ SLOT(updateProgress(qint64)));
+ connect(capture, SIGNAL(stateChanged(QMediaRecorder::State)), this,
+ SLOT(updateState(QMediaRecorder::State)));
+ connect(capture, SIGNAL(error(QMediaRecorder::Error)), this,
+ SLOT(displayErrorMessage()));
+ }
+
+AudioRecorder::~AudioRecorder()
+{
+ delete capture;
+ delete audiosource;
+}
+
+void AudioRecorder::updateProgress(qint64 duration)
+{
+ if (capture->error() != QMediaRecorder::NoError || duration < 2000)
+ return;
+
+ ui->statusbar->showMessage(tr("Recorded %1 sec").arg(qRound(duration / 1000)));
+}
+
+void AudioRecorder::updateState(QMediaRecorder::State state)
+{
+ QString statusMessage;
+
+ switch (state) {
+ case QMediaRecorder::RecordingState:
+ ui->recordButton->setText(tr("Stop"));
+ ui->pauseButton->setText(tr("Pause"));
+ if (capture->outputLocation().isEmpty())
+ statusMessage = tr("Recording");
+ else
+ statusMessage = tr("Recording to %1").arg(
+ capture->outputLocation().toString());
+ break;
+ case QMediaRecorder::PausedState:
+ ui->recordButton->setText(tr("Stop"));
+ ui->pauseButton->setText(tr("Resume"));
+ statusMessage = tr("Paused");
+ break;
+ case QMediaRecorder::StoppedState:
+ ui->recordButton->setText(tr("Record"));
+ ui->pauseButton->setText(tr("Pause"));
+ statusMessage = tr("Stopped");
+ }
+
+ ui->pauseButton->setEnabled(state != QMediaRecorder::StoppedState);
+
+ if (capture->error() == QMediaRecorder::NoError)
+ ui->statusbar->showMessage(statusMessage);
+}
+
+static QVariant boxValue(const QComboBox *box)
+{
+ int idx = box->currentIndex();
+ if (idx == -1)
+ return QVariant();
+
+ return box->itemData(idx);
+}
+
+void AudioRecorder::toggleRecord()
+{
+ if (capture->state() == QMediaRecorder::StoppedState) {
+ audiosource->setAudioInput(boxValue(ui->audioDeviceBox).toString());
+
+ if (!outputLocationSet)
+ capture->setOutputLocation(generateAudioFilePath());
+
+ QAudioEncoderSettings settings;
+ settings.setCodec(boxValue(ui->audioCodecBox).toString());
+ settings.setSampleRate(boxValue(ui->sampleRateBox).toInt());
+ settings.setBitRate(boxValue(ui->bitrateBox).toInt());
+ settings.setQuality(QtMultimediaKit::EncodingQuality(ui->qualitySlider->value()));
+ settings.setEncodingMode(ui->constantQualityRadioButton->isChecked() ?
+ QtMultimediaKit::ConstantQualityEncoding :
+ QtMultimediaKit::ConstantBitRateEncoding);
+
+ QString container = boxValue(ui->containerBox).toString();
+
+ capture->setEncodingSettings(settings, QVideoEncoderSettings(), container);
+ capture->record();
+ }
+ else {
+ capture->stop();
+ }
+}
+
+void AudioRecorder::togglePause()
+{
+ if (capture->state() != QMediaRecorder::PausedState)
+ capture->pause();
+ else
+ capture->record();
+}
+
+void AudioRecorder::setOutputLocation()
+{
+ QString fileName = QFileDialog::getSaveFileName();
+ capture->setOutputLocation(QUrl(fileName));
+ outputLocationSet = true;
+}
+
+void AudioRecorder::displayErrorMessage()
+{
+ ui->statusbar->showMessage(capture->errorString());
+}
+
+QUrl AudioRecorder::generateAudioFilePath()
+{
+ QDir outputDir(QDir::rootPath());
+
+ int lastImage = 0;
+ int fileCount = 0;
+ foreach(QString fileName, outputDir.entryList(QStringList() << "testclip_*")) {
+ int imgNumber = fileName.mid(5, fileName.size() - 9).toInt();
+ lastImage = qMax(lastImage, imgNumber);
+ if (outputDir.exists(fileName))
+ fileCount += 1;
+ }
+ lastImage += fileCount;
+ QUrl location(QDir::toNativeSeparators(outputDir.canonicalPath() + QString("/testclip_%1").arg(lastImage + 1, 4, 10, QLatin1Char('0'))));
+ return location;
+}
diff --git a/examples/audiorecorder/audiorecorder.h b/examples/audiorecorder/audiorecorder.h
new file mode 100644
index 000000000..3bcebf6ed
--- /dev/null
+++ b/examples/audiorecorder/audiorecorder.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AUDIORECORDER_H
+#define AUDIORECORDER_H
+
+#include <QtCore/qurl.h>
+#include <QtGui/qmainwindow.h>
+
+#include <qmediarecorder.h>
+
+
+QT_BEGIN_NAMESPACE
+
+namespace Ui {
+ class AudioRecorder;
+}
+
+class QAudioCaptureSource;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class AudioRecorder : public QMainWindow
+{
+ Q_OBJECT
+public:
+ AudioRecorder(QWidget *parent = 0);
+ ~AudioRecorder();
+
+private slots:
+ void setOutputLocation();
+ void togglePause();
+ void toggleRecord();
+
+ void updateState(QMediaRecorder::State);
+ void updateProgress(qint64 pos);
+ void displayErrorMessage();
+ QUrl generateAudioFilePath();
+
+private:
+ Ui::AudioRecorder *ui;
+
+ QAudioCaptureSource* audiosource;
+ QMediaRecorder* capture;
+ QAudioEncoderSettings audioSettings;
+ bool outputLocationSet;
+
+};
+
+#endif
diff --git a/examples/audiorecorder/audiorecorder.pro b/examples/audiorecorder/audiorecorder.pro
new file mode 100644
index 000000000..99502414e
--- /dev/null
+++ b/examples/audiorecorder/audiorecorder.pro
@@ -0,0 +1,29 @@
+TEMPLATE = app
+CONFIG += example
+
+INCLUDEPATH += ../../src/multimedia ../../src/multimedia/audio
+include(../mobility_examples.pri)
+
+CONFIG += mobility
+MOBILITY = multimedia
+
+QMAKE_RPATHDIR += $$DESTDIR
+
+HEADERS = \
+ audiorecorder.h
+
+SOURCES = \
+ main.cpp \
+ audiorecorder.cpp
+
+maemo*: {
+ FORMS += audiorecorder_small.ui
+}else:symbian:contains(S60_VERSION, 3.2)|contains(S60_VERSION, 3.1){
+ DEFINES += SYMBIAN_S60_3X
+ FORMS += audiorecorder_small.ui
+}else {
+ FORMS += audiorecorder.ui
+}
+symbian: {
+ TARGET.CAPABILITY = UserEnvironment ReadDeviceData WriteDeviceData
+}
diff --git a/examples/audiorecorder/audiorecorder.ui b/examples/audiorecorder/audiorecorder.ui
new file mode 100644
index 000000000..8ade5ce8c
--- /dev/null
+++ b/examples/audiorecorder/audiorecorder.ui
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AudioRecorder</class>
+ <widget class="QMainWindow" name="AudioRecorder">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>297</width>
+ <height>374</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>MainWindow</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0" colspan="3">
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Input Device:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="audioDeviceBox"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Audio Codec:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="audioCodecBox"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>File Container:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="containerBox"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Sample rate:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="sampleRateBox"/>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0" colspan="3">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Encoding Mode:</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0" colspan="2">
+ <widget class="QRadioButton" name="constantQualityRadioButton">
+ <property name="text">
+ <string>Constant Quality:</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSlider" name="qualitySlider">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QRadioButton" name="constantBitrateRadioButton">
+ <property name="text">
+ <string>Constant Bitrate:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="bitrateBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QPushButton" name="outputButton">
+ <property name="text">
+ <string>Output...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QPushButton" name="recordButton">
+ <property name="text">
+ <string>Record</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QPushButton" name="pauseButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Pause</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>constantQualityRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>qualitySlider</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>113</x>
+ <y>197</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>115</x>
+ <y>223</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>constantBitrateRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>bitrateBox</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>173</x>
+ <y>259</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>190</x>
+ <y>291</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>outputButton</sender>
+ <signal>clicked()</signal>
+ <receiver>AudioRecorder</receiver>
+ <slot>setOutputLocation()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>46</x>
+ <y>340</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>6</x>
+ <y>302</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>recordButton</sender>
+ <signal>clicked()</signal>
+ <receiver>AudioRecorder</receiver>
+ <slot>toggleRecord()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>191</x>
+ <y>340</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>113</x>
+ <y>317</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>pauseButton</sender>
+ <signal>clicked()</signal>
+ <receiver>AudioRecorder</receiver>
+ <slot>togglePause()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>252</x>
+ <y>334</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>258</x>
+ <y>346</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+ <slots>
+ <slot>setOutputLocation()</slot>
+ <slot>toggleRecord()</slot>
+ <slot>togglePause()</slot>
+ </slots>
+</ui>
diff --git a/examples/audiorecorder/audiorecorder_small.ui b/examples/audiorecorder/audiorecorder_small.ui
new file mode 100644
index 000000000..9d23c4267
--- /dev/null
+++ b/examples/audiorecorder/audiorecorder_small.ui
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AudioRecorder</class>
+ <widget class="QMainWindow" name="AudioRecorder">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>420</width>
+ <height>346</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>MainWindow</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QGridLayout" name="gridLayout_5">
+ <item row="0" column="0" colspan="3">
+ <widget class="QScrollArea" name="scrollArea">
+ <property name="focusPolicy">
+ <enum>Qt::ClickFocus</enum>
+ </property>
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="scrollAreaWidgetContents">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>398</width>
+ <height>275</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <widget class="QWidget" name="widget" native="true">
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Input Device:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="audioDeviceBox"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Audio Codec:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="audioCodecBox"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>File Container:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="containerBox"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Sample rate:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="sampleRateBox"/>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QRadioButton" name="constantQualityRadioButton">
+ <property name="text">
+ <string>Quality:</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QRadioButton" name="constantBitrateRadioButton">
+ <property name="text">
+ <string>Bitrate:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QSlider" name="qualitySlider">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="bitrateBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>29</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QPushButton" name="outputButton">
+ <property name="text">
+ <string>Output...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="recordButton">
+ <property name="text">
+ <string>Record</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="pauseButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Pause</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>constantQualityRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>qualitySlider</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>113</x>
+ <y>197</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>115</x>
+ <y>223</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>constantBitrateRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>bitrateBox</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>173</x>
+ <y>259</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>190</x>
+ <y>291</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>outputButton</sender>
+ <signal>clicked()</signal>
+ <receiver>AudioRecorder</receiver>
+ <slot>setOutputLocation()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>46</x>
+ <y>340</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>6</x>
+ <y>302</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>recordButton</sender>
+ <signal>clicked()</signal>
+ <receiver>AudioRecorder</receiver>
+ <slot>toggleRecord()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>191</x>
+ <y>340</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>113</x>
+ <y>317</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>pauseButton</sender>
+ <signal>clicked()</signal>
+ <receiver>AudioRecorder</receiver>
+ <slot>togglePause()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>252</x>
+ <y>334</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>258</x>
+ <y>346</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+ <slots>
+ <slot>setOutputLocation()</slot>
+ <slot>toggleRecord()</slot>
+ <slot>togglePause()</slot>
+ </slots>
+</ui>
diff --git a/examples/audiorecorder/main.cpp b/examples/audiorecorder/main.cpp
new file mode 100644
index 000000000..7dee4f807
--- /dev/null
+++ b/examples/audiorecorder/main.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "audiorecorder.h"
+
+#include <QtGui>
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ AudioRecorder recorder;
+#ifdef Q_OS_SYMBIAN
+ recorder.showMaximized();
+#else
+ recorder.show();
+#endif
+
+ return app.exec();
+};
diff --git a/examples/camera/camera.cpp b/examples/camera/camera.cpp
new file mode 100644
index 000000000..ab8ebf33d
--- /dev/null
+++ b/examples/camera/camera.cpp
@@ -0,0 +1,440 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "camera.h"
+#include "ui_camera.h"
+#include "videosettings.h"
+#include "imagesettings.h"
+
+#include <qmediaservice.h>
+#include <qmediarecorder.h>
+#include <qcamera.h>
+#include <qcameraviewfinder.h>
+
+#include <qmessagebox.h>
+#include <qpalette.h>
+
+#include <QtGui>
+
+#if (defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)) && QT_VERSION >= 0x040700
+#define HAVE_CAMERA_BUTTONS
+#endif
+
+Camera::Camera(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::Camera),
+ camera(0),
+ imageCapture(0),
+ mediaRecorder(0),
+ isCapturingImage(false),
+ applicationExiting(false)
+{
+ ui->setupUi(this);
+
+ //Camera devices:
+ QByteArray cameraDevice;
+
+ QActionGroup *videoDevicesGroup = new QActionGroup(this);
+ videoDevicesGroup->setExclusive(true);
+ foreach(const QByteArray &deviceName, QCamera::availableDevices()) {
+ QString description = camera->deviceDescription(deviceName);
+ QAction *videoDeviceAction = new QAction(description, videoDevicesGroup);
+ videoDeviceAction->setCheckable(true);
+ videoDeviceAction->setData(QVariant(deviceName));
+ if (cameraDevice.isEmpty()) {
+ cameraDevice = deviceName;
+ videoDeviceAction->setChecked(true);
+ }
+ ui->menuDevices->addAction(videoDeviceAction);
+ }
+
+ connect(videoDevicesGroup, SIGNAL(triggered(QAction*)), this, SLOT(updateCameraDevice(QAction*)));
+ connect(ui->captureWidget, SIGNAL(currentChanged(int)), SLOT(updateCaptureMode()));
+
+#ifdef HAVE_CAMERA_BUTTONS
+ ui->lockButton->hide();
+#endif
+
+ setCamera(cameraDevice);
+}
+
+Camera::~Camera()
+{
+ delete mediaRecorder;
+ delete imageCapture;
+ delete camera;
+}
+
+void Camera::setCamera(const QByteArray &cameraDevice)
+{
+ delete imageCapture;
+ delete mediaRecorder;
+ delete camera;
+
+ if (cameraDevice.isEmpty())
+ camera = new QCamera;
+ else
+ camera = new QCamera(cameraDevice);
+
+ connect(camera, SIGNAL(stateChanged(QCamera::State)), this, SLOT(updateCameraState(QCamera::State)));
+ connect(camera, SIGNAL(error(QCamera::Error)), this, SLOT(displayCameraError()));
+
+ mediaRecorder = new QMediaRecorder(camera);
+ connect(mediaRecorder, SIGNAL(stateChanged(QMediaRecorder::State)), this, SLOT(updateRecorderState(QMediaRecorder::State)));
+
+ imageCapture = new QCameraImageCapture(camera);
+
+ connect(mediaRecorder, SIGNAL(durationChanged(qint64)), this, SLOT(updateRecordTime()));
+ connect(mediaRecorder, SIGNAL(error(QMediaRecorder::Error)), this, SLOT(displayRecorderError()));
+
+ mediaRecorder->setMetaData(QtMultimediaKit::Title, QVariant(QLatin1String("Test Title")));
+
+ connect(ui->exposureCompensation, SIGNAL(valueChanged(int)), SLOT(setExposureCompensation(int)));
+
+ camera->setViewfinder(ui->viewfinder);
+
+ updateCameraState(camera->state());
+ updateLockStatus(camera->lockStatus(), QCamera::UserRequest);
+ updateRecorderState(mediaRecorder->state());
+
+ connect(imageCapture, SIGNAL(readyForCaptureChanged(bool)), this, SLOT(readyForCapture(bool)));
+ connect(imageCapture, SIGNAL(imageCaptured(int,QImage)), this, SLOT(processCapturedImage(int,QImage)));
+ connect(imageCapture, SIGNAL(imageSaved(int,QString)), this, SLOT(imageSaved(int,QString)));
+
+ connect(camera, SIGNAL(lockStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
+ this, SLOT(updateLockStatus(QCamera::LockStatus, QCamera::LockChangeReason)));
+
+ ui->captureWidget->setTabEnabled(0, (camera->isCaptureModeSupported(QCamera::CaptureStillImage)));
+ ui->captureWidget->setTabEnabled(1, (camera->isCaptureModeSupported(QCamera::CaptureVideo)));
+
+ updateCaptureMode();
+ camera->start();
+}
+
+void Camera::keyPressEvent(QKeyEvent * event)
+{
+ if (event->isAutoRepeat())
+ return;
+
+ switch (event->key()) {
+#if QT_VERSION >= 0x040700
+ case Qt::Key_CameraFocus:
+ displayViewfinder();
+ camera->searchAndLock();
+ event->accept();
+ break;
+ case Qt::Key_Camera:
+ if (camera->captureMode() == QCamera::CaptureStillImage) {
+ takeImage();
+ } else {
+ if (mediaRecorder->state() == QMediaRecorder::RecordingState)
+ stop();
+ else
+ record();
+ }
+ event->accept();
+ break;
+#endif
+ default:
+ QMainWindow::keyPressEvent(event);
+ }
+}
+
+void Camera::keyReleaseEvent(QKeyEvent * event)
+{
+ if (event->isAutoRepeat())
+ return;
+
+ switch (event->key()) {
+#if QT_VERSION >= 0x040700
+ case Qt::Key_CameraFocus:
+ camera->unlock();
+ break;
+#endif
+ default:
+ QMainWindow::keyReleaseEvent(event);
+ }
+}
+
+void Camera::updateRecordTime()
+{
+ QString str = QString("Recorded %1 sec").arg(mediaRecorder->duration()/1000);
+ ui->statusbar->showMessage(str);
+}
+
+void Camera::processCapturedImage(int requestId, const QImage& img)
+{
+ Q_UNUSED(requestId);
+ QImage scaledImage = img.scaled(ui->viewfinder->size(),
+ Qt::KeepAspectRatio,
+ Qt::SmoothTransformation);
+
+ ui->lastImagePreviewLabel->setPixmap(QPixmap::fromImage(scaledImage));
+ //display captured image for 4 seconds
+ displayCapturedImage();
+ QTimer::singleShot(4000, this, SLOT(displayViewfinder()));
+}
+
+void Camera::configureCaptureSettings()
+{
+ switch (camera->captureMode()) {
+ case QCamera::CaptureStillImage:
+ configureImageSettings();
+ break;
+ case QCamera::CaptureVideo:
+ configureVideoSettings();
+ break;
+ default:
+ break;
+ }
+}
+
+void Camera::configureVideoSettings()
+{
+ VideoSettings settingsDialog(mediaRecorder);
+
+ settingsDialog.setAudioSettings(audioSettings);
+ settingsDialog.setVideoSettings(videoSettings);
+ settingsDialog.setFormat(videoContainerFormat);
+
+ if (settingsDialog.exec()) {
+ audioSettings = settingsDialog.audioSettings();
+ videoSettings = settingsDialog.videoSettings();
+ videoContainerFormat = settingsDialog.format();
+
+ mediaRecorder->setEncodingSettings(
+ audioSettings,
+ videoSettings,
+ videoContainerFormat);
+ }
+}
+
+void Camera::configureImageSettings()
+{
+ ImageSettings settingsDialog(imageCapture);
+
+ settingsDialog.setImageSettings(imageSettings);
+
+ if (settingsDialog.exec()) {
+ imageSettings = settingsDialog.imageSettings();
+ imageCapture->setEncodingSettings(imageSettings);
+ }
+}
+
+void Camera::record()
+{
+ mediaRecorder->record();
+ updateRecordTime();
+}
+
+void Camera::pause()
+{
+ mediaRecorder->pause();
+}
+
+void Camera::stop()
+{
+ mediaRecorder->stop();
+}
+
+void Camera::setMuted(bool muted)
+{
+ mediaRecorder->setMuted(muted);
+}
+
+void Camera::toggleLock()
+{
+ switch (camera->lockStatus()) {
+ case QCamera::Searching:
+ case QCamera::Locked:
+ camera->unlock();
+ break;
+ case QCamera::Unlocked:
+ camera->searchAndLock();
+ }
+}
+
+void Camera::updateLockStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason)
+{
+ QColor indicationColor = Qt::black;
+
+ switch (status) {
+ case QCamera::Searching:
+ indicationColor = Qt::yellow;
+ ui->statusbar->showMessage(tr("Focusing..."));
+ ui->lockButton->setText(tr("Focusing..."));
+ break;
+ case QCamera::Locked:
+ indicationColor = Qt::darkGreen;
+ ui->lockButton->setText(tr("Unlock"));
+ ui->statusbar->showMessage(tr("Focused"), 2000);
+ break;
+ case QCamera::Unlocked:
+ indicationColor = reason == QCamera::LockFailed ? Qt::red : Qt::black;
+ ui->lockButton->setText(tr("Focus"));
+ if (reason == QCamera::LockFailed)
+ ui->statusbar->showMessage(tr("Focus Failed"), 2000);
+ }
+
+ QPalette palette = ui->lockButton->palette();
+ palette.setColor(QPalette::ButtonText, indicationColor);
+ ui->lockButton->setPalette(palette);
+}
+
+void Camera::takeImage()
+
+{
+ isCapturingImage = true;
+ imageCapture->capture();
+}
+
+void Camera::startCamera()
+{
+ camera->start();
+}
+
+void Camera::stopCamera()
+{
+ camera->stop();
+}
+
+void Camera::updateCaptureMode()
+{
+ int tabIndex = ui->captureWidget->currentIndex();
+ QCamera::CaptureMode captureMode = tabIndex == 0 ? QCamera::CaptureStillImage : QCamera::CaptureVideo;
+
+ if (camera->isCaptureModeSupported(captureMode))
+ camera->setCaptureMode(captureMode);
+}
+
+void Camera::updateCameraState(QCamera::State state)
+{
+ switch (state) {
+ case QCamera::ActiveState:
+ ui->actionStartCamera->setEnabled(false);
+ ui->actionStopCamera->setEnabled(true);
+ ui->captureWidget->setEnabled(true);
+ ui->actionSettings->setEnabled(true);
+ break;
+ case QCamera::UnloadedState:
+ case QCamera::LoadedState:
+ ui->actionStartCamera->setEnabled(true);
+ ui->actionStopCamera->setEnabled(false);
+ ui->captureWidget->setEnabled(false);
+ ui->actionSettings->setEnabled(false);
+ }
+}
+
+void Camera::updateRecorderState(QMediaRecorder::State state)
+{
+ switch (state) {
+ case QMediaRecorder::StoppedState:
+ ui->recordButton->setEnabled(true);
+ ui->pauseButton->setEnabled(true);
+ ui->stopButton->setEnabled(false);
+ break;
+ case QMediaRecorder::PausedState:
+ ui->recordButton->setEnabled(true);
+ ui->pauseButton->setEnabled(false);
+ ui->stopButton->setEnabled(true);
+ break;
+ case QMediaRecorder::RecordingState:
+ ui->recordButton->setEnabled(false);
+ ui->pauseButton->setEnabled(true);
+ ui->stopButton->setEnabled(true);
+ break;
+ }
+}
+
+void Camera::setExposureCompensation(int index)
+{
+ camera->exposure()->setExposureCompensation(index*0.5);
+}
+
+void Camera::displayRecorderError()
+{
+ QMessageBox::warning(this, tr("Capture error"), mediaRecorder->errorString());
+}
+
+void Camera::displayCameraError()
+{
+ QMessageBox::warning(this, tr("Camera error"), camera->errorString());
+}
+
+void Camera::updateCameraDevice(QAction *action)
+{
+ setCamera(action->data().toByteArray());
+}
+
+void Camera::displayViewfinder()
+{
+ ui->stackedWidget->setCurrentIndex(0);
+}
+
+void Camera::displayCapturedImage()
+{
+ ui->stackedWidget->setCurrentIndex(1);
+}
+
+void Camera::readyForCapture(bool ready)
+{
+ ui->takeImageButton->setEnabled(ready);
+}
+
+void Camera::imageSaved(int id, const QString &fileName)
+{
+ Q_UNUSED(id);
+ Q_UNUSED(fileName);
+
+ isCapturingImage = false;
+ if (applicationExiting)
+ close();
+}
+
+void Camera::closeEvent(QCloseEvent *event)
+{
+ if (isCapturingImage) {
+ setEnabled(false);
+ applicationExiting = true;
+ event->ignore();
+ } else {
+ event->accept();
+ }
+}
diff --git a/examples/camera/camera.h b/examples/camera/camera.h
new file mode 100644
index 000000000..e569baf31
--- /dev/null
+++ b/examples/camera/camera.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CAMERA_H
+#define CAMERA_H
+
+#include <qcamera.h>
+#include <qmediarecorder.h>
+#include <qcameraimagecapture.h>
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+ class Camera;
+}
+class QCameraViewfinder;
+QT_END_NAMESPACE
+
+#include <QMainWindow>
+#include <QDir>
+
+QT_USE_NAMESPACE
+
+class Camera : public QMainWindow
+{
+ Q_OBJECT
+public:
+ Camera(QWidget *parent = 0);
+ ~Camera();
+
+private slots:
+ void setCamera(const QByteArray &cameraDevice);
+
+ void startCamera();
+ void stopCamera();
+
+ void record();
+ void pause();
+ void stop();
+ void setMuted(bool);
+
+ void toggleLock();
+ void takeImage();
+
+ void configureCaptureSettings();
+ void configureVideoSettings();
+ void configureImageSettings();
+
+ void displayRecorderError();
+ void displayCameraError();
+
+ void updateCameraDevice(QAction*);
+
+ void updateCameraState(QCamera::State);
+ void updateCaptureMode();
+ void updateRecorderState(QMediaRecorder::State state);
+ void setExposureCompensation(int index);
+
+ void updateRecordTime();
+
+ void processCapturedImage(int requestId, const QImage& img);
+ void updateLockStatus(QCamera::LockStatus, QCamera::LockChangeReason);
+
+ void displayViewfinder();
+ void displayCapturedImage();
+
+ void readyForCapture(bool);
+ void imageSaved(int, const QString&);
+
+protected:
+ void keyPressEvent(QKeyEvent * event);
+ void keyReleaseEvent(QKeyEvent * event);
+ void closeEvent(QCloseEvent *event );
+
+private:
+ Ui::Camera *ui;
+
+ QCamera *camera;
+ QCameraImageCapture *imageCapture;
+ QMediaRecorder* mediaRecorder;
+
+ QImageEncoderSettings imageSettings;
+ QAudioEncoderSettings audioSettings;
+ QVideoEncoderSettings videoSettings;
+ QString videoContainerFormat;
+ bool isCapturingImage;
+ bool applicationExiting;
+};
+
+#endif
diff --git a/examples/camera/camera.pro b/examples/camera/camera.pro
new file mode 100644
index 000000000..2d657e887
--- /dev/null
+++ b/examples/camera/camera.pro
@@ -0,0 +1,33 @@
+TEMPLATE = app
+TARGET = camera
+
+INCLUDEPATH+=../../src/multimedia \
+ ../../src/multimedia/video
+
+include(../mobility_examples.pri)
+
+CONFIG += mobility
+MOBILITY = multimedia
+
+HEADERS = \
+ camera.h \
+ imagesettings.h \
+ videosettings.h
+
+SOURCES = \
+ main.cpp \
+ camera.cpp \
+ imagesettings.cpp \
+ videosettings.cpp
+
+FORMS += \
+ camera.ui \
+ videosettings.ui \
+ imagesettings.ui
+
+symbian {
+ include(camerakeyevent_symbian/camerakeyevent_symbian.pri)
+ TARGET.CAPABILITY += UserEnvironment WriteUserData ReadUserData
+ TARGET.EPOCHEAPSIZE = 0x20000 0x3000000
+ LIBS += -lavkon -leiksrv -lcone -leikcore
+}
diff --git a/examples/camera/camera.ui b/examples/camera/camera.ui
new file mode 100644
index 000000000..ea790fab0
--- /dev/null
+++ b/examples/camera/camera.ui
@@ -0,0 +1,492 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Camera</class>
+ <widget class="QMainWindow" name="Camera">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>668</width>
+ <height>422</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Camera</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0" rowspan="3">
+ <widget class="QStackedWidget" name="stackedWidget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>145</red>
+ <green>145</green>
+ <blue>145</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>145</red>
+ <green>145</green>
+ <blue>145</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>145</red>
+ <green>145</green>
+ <blue>145</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>145</red>
+ <green>145</green>
+ <blue>145</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="viewfinderPage">
+ <layout class="QGridLayout" name="gridLayout_5">
+ <item row="0" column="0">
+ <widget class="QCameraViewfinder" name="viewfinder" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="previewPage">
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <widget class="QLabel" name="lastImagePreviewLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::Box</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="1" column="1" colspan="2">
+ <widget class="QPushButton" name="lockButton">
+ <property name="text">
+ <string>Focus</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" colspan="2">
+ <widget class="QTabWidget" name="captureWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string>Image</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QPushButton" name="takeImageButton">
+ <property name="text">
+ <string>Capture Photo</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>161</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Exposure Compensation:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QSlider" name="exposureCompensation">
+ <property name="minimum">
+ <number>-4</number>
+ </property>
+ <property name="maximum">
+ <number>4</number>
+ </property>
+ <property name="pageStep">
+ <number>2</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksAbove</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Video</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QPushButton" name="recordButton">
+ <property name="text">
+ <string>Record</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QPushButton" name="pauseButton">
+ <property name="text">
+ <string>Pause</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QPushButton" name="stopButton">
+ <property name="text">
+ <string>Stop</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>76</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="4" column="0">
+ <widget class="QPushButton" name="muteButton">
+ <property name="text">
+ <string>Mute</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>668</width>
+ <height>29</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuFile">
+ <property name="title">
+ <string>File</string>
+ </property>
+ <addaction name="actionStartCamera"/>
+ <addaction name="actionStopCamera"/>
+ <addaction name="separator"/>
+ <addaction name="actionSettings"/>
+ <addaction name="separator"/>
+ <addaction name="actionExit"/>
+ </widget>
+ <widget class="QMenu" name="menuDevices">
+ <property name="title">
+ <string>Devices</string>
+ </property>
+ </widget>
+ <addaction name="menuFile"/>
+ <addaction name="menuDevices"/>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ <action name="actionExit">
+ <property name="text">
+ <string>Exit</string>
+ </property>
+ </action>
+ <action name="actionStartCamera">
+ <property name="text">
+ <string>Start Camera</string>
+ </property>
+ </action>
+ <action name="actionStopCamera">
+ <property name="text">
+ <string>Stop Camera</string>
+ </property>
+ </action>
+ <action name="actionSettings">
+ <property name="text">
+ <string>Settings</string>
+ </property>
+ </action>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QCameraViewfinder</class>
+ <extends>QWidget</extends>
+ <header>qcameraviewfinder.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>recordButton</sender>
+ <signal>clicked()</signal>
+ <receiver>Camera</receiver>
+ <slot>record()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>647</x>
+ <y>149</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>61</x>
+ <y>238</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>stopButton</sender>
+ <signal>clicked()</signal>
+ <receiver>Camera</receiver>
+ <slot>stop()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>647</x>
+ <y>225</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>140</x>
+ <y>236</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>pauseButton</sender>
+ <signal>clicked()</signal>
+ <receiver>Camera</receiver>
+ <slot>pause()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>647</x>
+ <y>187</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>234</x>
+ <y>237</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>actionExit</sender>
+ <signal>triggered()</signal>
+ <receiver>Camera</receiver>
+ <slot>close()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>-1</x>
+ <y>-1</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>154</x>
+ <y>130</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>takeImageButton</sender>
+ <signal>clicked()</signal>
+ <receiver>Camera</receiver>
+ <slot>takeImage()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>625</x>
+ <y>132</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>603</x>
+ <y>169</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>lockButton</sender>
+ <signal>clicked()</signal>
+ <receiver>Camera</receiver>
+ <slot>toggleLock()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>658</x>
+ <y>75</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>453</x>
+ <y>119</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>muteButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>Camera</receiver>
+ <slot>setMuted(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>647</x>
+ <y>377</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>5</x>
+ <y>280</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>exposureCompensation</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>Camera</receiver>
+ <slot>setExposureCompensation(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>559</x>
+ <y>367</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>665</x>
+ <y>365</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>actionSettings</sender>
+ <signal>triggered()</signal>
+ <receiver>Camera</receiver>
+ <slot>configureCaptureSettings()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>-1</x>
+ <y>-1</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>333</x>
+ <y>210</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>actionStartCamera</sender>
+ <signal>triggered()</signal>
+ <receiver>Camera</receiver>
+ <slot>startCamera()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>-1</x>
+ <y>-1</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>333</x>
+ <y>210</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>actionStopCamera</sender>
+ <signal>triggered()</signal>
+ <receiver>Camera</receiver>
+ <slot>stopCamera()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>-1</x>
+ <y>-1</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>333</x>
+ <y>210</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+ <slots>
+ <slot>record()</slot>
+ <slot>pause()</slot>
+ <slot>stop()</slot>
+ <slot>enablePreview(bool)</slot>
+ <slot>configureCaptureSettings()</slot>
+ <slot>takeImage()</slot>
+ <slot>startCamera()</slot>
+ <slot>toggleLock()</slot>
+ <slot>setMuted(bool)</slot>
+ <slot>stopCamera()</slot>
+ <slot>setExposureCompensation(int)</slot>
+ </slots>
+</ui>
diff --git a/examples/camera/camerakeyevent_symbian/camerakeyevent_symbian.cpp b/examples/camera/camerakeyevent_symbian/camerakeyevent_symbian.cpp
new file mode 100644
index 000000000..30723af40
--- /dev/null
+++ b/examples/camera/camerakeyevent_symbian/camerakeyevent_symbian.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "camerakeyevent_symbian.h"
+
+#include <QtGui/QWidget> // WId
+#include <eikon.hrh> // EKeyCamera
+#include <coecntrl.h> // CCoeControl (WId)
+#include <w32std.h> // RWindowbase, RWindowGroup, RWsSession
+
+QSymbianCameraKeyListener::QSymbianCameraKeyListener(QWidget *widget):
+ QObject(widget),
+ m_widget(widget)
+{
+ if (!m_widget)
+ return;
+
+ // Get view's native Symbian window
+ WId windowId = 0;
+ if (m_widget->internalWinId())
+ windowId = m_widget->internalWinId();
+ else if (m_widget->parentWidget() && m_widget->effectiveWinId())
+ windowId = m_widget->effectiveWinId();
+ RWindowBase *window = windowId ? static_cast<RWindowBase*>(windowId->DrawableWindow()) : 0;
+
+ // Get hold of the window group
+ TInt wGroupId = window ? window->WindowGroupId() : 0;
+ if (!wGroupId)
+ return;
+ RWsSession &wsSession = CCoeEnv::Static()->WsSession();
+ TUint wGroupHandle = wsSession.GetWindowGroupHandle(wGroupId);
+ if (wGroupHandle) {
+ RWindowGroup wGroup(wsSession);
+ wGroup.Construct(wGroupHandle);
+ if (wGroup.CaptureKey(EKeyCamera, 0, 0, 100) < 0)
+ qWarning("Unable to register for camera capture key events, SwEvent capability may be missing");
+ }
+}
+
+QSymbianCameraKeyListener::~QSymbianCameraKeyListener()
+{
+ if (!m_widget)
+ return;
+
+ // Get view's native Symbian window
+ WId windowId = 0;
+ if (m_widget->internalWinId())
+ windowId = m_widget->internalWinId();
+ else if (m_widget->parentWidget() && m_widget->effectiveWinId())
+ windowId = m_widget->effectiveWinId();
+ RWindowBase *window = windowId ? static_cast<RWindowBase*>(windowId->DrawableWindow()) : 0;
+
+ // Get hold of the window group
+ TInt wGroupId = window ? window->WindowGroupId() : 0;
+ if (!wGroupId)
+ return;
+ RWsSession &wsSession = CCoeEnv::Static()->WsSession();
+ TUint wGroupHandle = wsSession.GetWindowGroupHandle(wGroupId);
+ if (wGroupHandle) {
+ RWindowGroup wGroup(wsSession);
+ wGroup.Construct(wGroupHandle);
+ wGroup.CancelCaptureKey(EKeyCamera);
+ }
+}
diff --git a/examples/camera/camerakeyevent_symbian/camerakeyevent_symbian.h b/examples/camera/camerakeyevent_symbian/camerakeyevent_symbian.h
new file mode 100644
index 000000000..4cd5701b9
--- /dev/null
+++ b/examples/camera/camerakeyevent_symbian/camerakeyevent_symbian.h
@@ -0,0 +1,87 @@
+#ifndef CAMERAKEYEVENT_SYMBIAN_H
+#define CAMERAKEYEVENT_SYMBIAN_H
+
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ * Description:
+ * This header can be used to register application on Symbian platforms
+ * for the Camera capture button key events. Application can avoid native
+ * camera application from starting by not forwarding the key event.
+ *
+ * Usage:
+ * Application needs to include this header and include the needed Symbian
+ * libraries. Optionally application can include camerakeyevent_symbian.pri
+ * file. Application can register and unregister for the Camera capture
+ * key events by creating/destructing the QSymbianCameraKeyListener helper
+ * object. The widget needs to be shown before it registers for the
+ * Camera key event.
+ *
+ * Libraries needed:
+ * User needs to define following in the .pro file (or optionally include
+ * the camerakeyevent_symbian.pri):
+ * LIBS += -lcone -lws32
+ *
+ * Symbian Capabilities needed:
+ * To use this header user needs to have SwEvent capability (included in
+ * the camerakeyevent_symbian.pri):
+ * TARGET.CAPABILITY += SwEvent
+ */
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+QT_FORWARD_DECLARE_CLASS(QWidget)
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class QSymbianCameraKeyListener : public QObject
+{
+ Q_OBJECT
+public:
+ QSymbianCameraKeyListener(QWidget *parent = 0);
+ ~QSymbianCameraKeyListener();
+private:
+ QWidget *m_widget;
+};
+
+#endif // CAMERAKEYEVENT_SYMBIAN_H
diff --git a/examples/camera/camerakeyevent_symbian/camerakeyevent_symbian.pri b/examples/camera/camerakeyevent_symbian/camerakeyevent_symbian.pri
new file mode 100644
index 000000000..097c3b245
--- /dev/null
+++ b/examples/camera/camerakeyevent_symbian/camerakeyevent_symbian.pri
@@ -0,0 +1,7 @@
+message("camerakeyevent_symbian: Including Symbian camera capture key event register methods")
+
+HEADERS += $$PWD/camerakeyevent_symbian.h
+SOURCES += $$PWD/camerakeyevent_symbian.cpp
+INCLUDEPATH += $$PWD
+LIBS *= -lcone -lws32
+TARGET.CAPABILITY *= SwEvent
diff --git a/examples/camera/imagesettings.cpp b/examples/camera/imagesettings.cpp
new file mode 100644
index 000000000..a7f389bb9
--- /dev/null
+++ b/examples/camera/imagesettings.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "imagesettings.h"
+#include "ui_imagesettings.h"
+
+#include <QtGui/qcombobox.h>
+#include <QtCore/qdebug.h>
+#include <qcameraimagecapture.h>
+#include <qmediaservice.h>
+
+
+
+ImageSettings::ImageSettings(QCameraImageCapture *imageCapture, QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::ImageSettingsUi),
+ imagecapture(imageCapture)
+{
+ ui->setupUi(this);
+
+ //image codecs
+ ui->imageCodecBox->addItem(tr("Default image format"), QVariant(QString()));
+ foreach(const QString &codecName, imagecapture->supportedImageCodecs()) {
+ QString description = imagecapture->imageCodecDescription(codecName);
+ ui->imageCodecBox->addItem(codecName+": "+description, QVariant(codecName));
+ }
+
+ ui->imageQualitySlider->setRange(0, int(QtMultimediaKit::VeryHighQuality));
+
+ ui->imageResolutionBox->addItem(tr("Default Resolution"));
+ QList<QSize> supportedResolutions = imagecapture->supportedResolutions();
+ foreach(const QSize &resolution, supportedResolutions) {
+ ui->imageResolutionBox->addItem(QString("%1x%2").arg(resolution.width()).arg(resolution.height()),
+ QVariant(resolution));
+ }
+}
+
+ImageSettings::~ImageSettings()
+{
+ delete ui;
+}
+
+void ImageSettings::changeEvent(QEvent *e)
+{
+ QDialog::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+QImageEncoderSettings ImageSettings::imageSettings() const
+{
+ QImageEncoderSettings settings = imagecapture->encodingSettings();
+ settings.setCodec(boxValue(ui->imageCodecBox).toString());
+ settings.setQuality(QtMultimediaKit::EncodingQuality(ui->imageQualitySlider->value()));
+ settings.setResolution(boxValue(ui->imageResolutionBox).toSize());
+
+ return settings;
+}
+
+void ImageSettings::setImageSettings(const QImageEncoderSettings &imageSettings)
+{
+ selectComboBoxItem(ui->imageCodecBox, QVariant(imageSettings.codec()));
+ selectComboBoxItem(ui->imageResolutionBox, QVariant(imageSettings.resolution()));
+ ui->imageQualitySlider->setValue(imageSettings.quality());
+}
+
+QVariant ImageSettings::boxValue(const QComboBox *box) const
+{
+ int idx = box->currentIndex();
+ if (idx == -1)
+ return QVariant();
+
+ return box->itemData(idx);
+}
+
+void ImageSettings::selectComboBoxItem(QComboBox *box, const QVariant &value)
+{
+ for (int i=0; i<box->count(); i++) {
+ if (box->itemData(i) == value) {
+ box->setCurrentIndex(i);
+ break;
+ }
+ }
+}
diff --git a/examples/camera/imagesettings.h b/examples/camera/imagesettings.h
new file mode 100644
index 000000000..b4b000f6a
--- /dev/null
+++ b/examples/camera/imagesettings.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef IMAGESETTINGS_H
+#define IMAGESETTINGS_H
+
+#include <QtGui/QDialog>
+#include <qmediaencodersettings.h>
+
+QT_BEGIN_NAMESPACE
+class QComboBox;
+namespace Ui {
+ class ImageSettingsUi;
+}
+
+class QCameraImageCapture;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class ImageSettings : public QDialog {
+ Q_OBJECT
+public:
+ ImageSettings(QCameraImageCapture *imageCapture, QWidget *parent = 0);
+ ~ImageSettings();
+
+ QAudioEncoderSettings audioSettings() const;
+ void setAudioSettings(const QAudioEncoderSettings&);
+
+ QImageEncoderSettings imageSettings() const;
+ void setImageSettings(const QImageEncoderSettings&);
+
+ QString format() const;
+ void setFormat(const QString &format);
+
+protected:
+ void changeEvent(QEvent *e);
+
+private:
+ QVariant boxValue(const QComboBox*) const;
+ void selectComboBoxItem(QComboBox *box, const QVariant &value);
+
+ Ui::ImageSettingsUi *ui;
+ QCameraImageCapture *imagecapture;
+};
+
+#endif // IMAGESETTINGS_H
diff --git a/examples/camera/imagesettings.ui b/examples/camera/imagesettings.ui
new file mode 100644
index 000000000..f790c770d
--- /dev/null
+++ b/examples/camera/imagesettings.ui
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ImageSettingsUi</class>
+ <widget class="QDialog" name="ImageSettingsUi">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>332</width>
+ <height>270</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Image</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0" colspan="2">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>Resolution:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QComboBox" name="imageResolutionBox"/>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Image Format:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QComboBox" name="imageCodecBox"/>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Quality:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QSlider" name="imageQualitySlider">
+ <property name="maximum">
+ <number>4</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>14</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ImageSettingsUi</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>322</x>
+ <y>272</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>44</x>
+ <y>230</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ImageSettingsUi</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>405</x>
+ <y>262</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>364</x>
+ <y>227</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/examples/camera/main.cpp b/examples/camera/main.cpp
new file mode 100644
index 000000000..7fd9a61f7
--- /dev/null
+++ b/examples/camera/main.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "camera.h"
+#ifdef Q_OS_SYMBIAN
+#include "camerakeyevent_symbian.h"
+#endif // Q_OS_SYMBIAN
+
+#include <QtGui>
+
+int main(int argc, char *argv[])
+{
+#if defined (Q_OS_SYMBIAN)
+ QApplication::setGraphicsSystem("raster");
+ QApplication app(argc, argv);
+ // lock orientation before constructing camera
+ CAknAppUi* appUi = dynamic_cast<CAknAppUi*>(CEikonEnv::Static()->AppUi());
+ if(appUi){
+ QT_TRAP_THROWING(appUi ->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape));
+ }
+#else
+ QApplication app(argc, argv);
+#endif
+
+ Camera camera;
+
+#ifdef Q_OS_SYMBIAN
+ camera.showMaximized();
+ new QSymbianCameraKeyListener(&camera);
+#else
+ camera.show();
+#endif
+
+ return app.exec();
+};
diff --git a/examples/camera/videosettings.cpp b/examples/camera/videosettings.cpp
new file mode 100644
index 000000000..f6beb70b5
--- /dev/null
+++ b/examples/camera/videosettings.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "videosettings.h"
+#include "ui_videosettings.h"
+
+#include <QtGui/qcombobox.h>
+#include <QtCore/qdebug.h>
+#include <qmediarecorder.h>
+#include <qmediaservice.h>
+
+
+VideoSettings::VideoSettings(QMediaRecorder *mediaRecorder, QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::VideoSettingsUi),
+ mediaRecorder(mediaRecorder)
+{
+ ui->setupUi(this);
+
+ //audio codecs
+ ui->audioCodecBox->addItem(tr("Default audio codec"), QVariant(QString()));
+ foreach(const QString &codecName, mediaRecorder->supportedAudioCodecs()) {
+ QString description = mediaRecorder->audioCodecDescription(codecName);
+ ui->audioCodecBox->addItem(codecName+": "+description, QVariant(codecName));
+ }
+
+ //sample rate:
+ foreach(int sampleRate, mediaRecorder->supportedAudioSampleRates()) {
+ ui->audioSampleRateBox->addItem(QString::number(sampleRate), QVariant(sampleRate));
+ }
+
+ ui->audioQualitySlider->setRange(0, int(QtMultimediaKit::VeryHighQuality));
+
+ //video codecs
+ ui->videoCodecBox->addItem(tr("Default video codec"), QVariant(QString()));
+ foreach(const QString &codecName, mediaRecorder->supportedVideoCodecs()) {
+ QString description = mediaRecorder->videoCodecDescription(codecName);
+ ui->videoCodecBox->addItem(codecName+": "+description, QVariant(codecName));
+ }
+
+ ui->videoQualitySlider->setRange(0, int(QtMultimediaKit::VeryHighQuality));
+
+
+ ui->videoResolutionBox->addItem(tr("Default"));
+ QList<QSize> supportedResolutions = mediaRecorder->supportedResolutions();
+ foreach(const QSize &resolution, supportedResolutions) {
+ ui->videoResolutionBox->addItem(QString("%1x%2").arg(resolution.width()).arg(resolution.height()),
+ QVariant(resolution));
+ }
+
+ ui->videoFramerateBox->addItem(tr("Default"));
+ QList<qreal> supportedFrameRates = mediaRecorder->supportedFrameRates();
+ qreal rate;
+ foreach(rate, supportedFrameRates) {
+ QString rateString = QString("%1").arg(rate, 0, 'f', 2);
+ ui->videoFramerateBox->addItem(rateString, QVariant(rate));
+ }
+
+ //containers
+ ui->containerFormatBox->addItem(tr("Default container"), QVariant(QString()));
+ foreach(const QString &format, mediaRecorder->supportedContainers()) {
+ ui->containerFormatBox->addItem(format+":"+mediaRecorder->containerDescription(format),
+ QVariant(format));
+ }
+}
+
+VideoSettings::~VideoSettings()
+{
+ delete ui;
+}
+
+void VideoSettings::changeEvent(QEvent *e)
+{
+ QDialog::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+QAudioEncoderSettings VideoSettings::audioSettings() const
+{
+ QAudioEncoderSettings settings = mediaRecorder->audioSettings();
+ settings.setCodec(boxValue(ui->audioCodecBox).toString());
+ settings.setQuality(QtMultimediaKit::EncodingQuality(ui->audioQualitySlider->value()));
+ settings.setSampleRate(boxValue(ui->audioSampleRateBox).toInt());
+ return settings;
+}
+
+void VideoSettings::setAudioSettings(const QAudioEncoderSettings &audioSettings)
+{
+ selectComboBoxItem(ui->audioCodecBox, QVariant(audioSettings.codec()));
+ selectComboBoxItem(ui->audioSampleRateBox, QVariant(audioSettings.sampleRate()));
+ ui->audioQualitySlider->setValue(audioSettings.quality());
+}
+
+QVideoEncoderSettings VideoSettings::videoSettings() const
+{
+ QVideoEncoderSettings settings = mediaRecorder->videoSettings();
+ settings.setCodec(boxValue(ui->videoCodecBox).toString());
+ settings.setQuality(QtMultimediaKit::EncodingQuality(ui->videoQualitySlider->value()));
+ settings.setResolution(boxValue(ui->videoResolutionBox).toSize());
+ settings.setFrameRate(boxValue(ui->videoFramerateBox).value<qreal>());
+
+ return settings;
+}
+
+void VideoSettings::setVideoSettings(const QVideoEncoderSettings &videoSettings)
+{
+ selectComboBoxItem(ui->videoCodecBox, QVariant(videoSettings.codec()));
+ selectComboBoxItem(ui->videoResolutionBox, QVariant(videoSettings.resolution()));
+ ui->videoQualitySlider->setValue(videoSettings.quality());
+
+ //special case for frame rate
+ for (int i=0; i<ui->videoFramerateBox->count(); i++) {
+ qreal itemRate = ui->videoFramerateBox->itemData(i).value<qreal>();
+ if (qFuzzyCompare(itemRate, videoSettings.frameRate())) {
+ ui->videoFramerateBox->setCurrentIndex(i);
+ break;
+ }
+ }
+}
+
+QString VideoSettings::format() const
+{
+ return boxValue(ui->containerFormatBox).toString();
+}
+
+void VideoSettings::setFormat(const QString &format)
+{
+ selectComboBoxItem(ui->containerFormatBox, QVariant(format));
+}
+
+QVariant VideoSettings::boxValue(const QComboBox *box) const
+{
+ int idx = box->currentIndex();
+ if (idx == -1)
+ return QVariant();
+
+ return box->itemData(idx);
+}
+
+void VideoSettings::selectComboBoxItem(QComboBox *box, const QVariant &value)
+{
+ for (int i=0; i<box->count(); i++) {
+ if (box->itemData(i) == value) {
+ box->setCurrentIndex(i);
+ break;
+ }
+ }
+}
diff --git a/examples/camera/videosettings.h b/examples/camera/videosettings.h
new file mode 100644
index 000000000..8eeea35b1
--- /dev/null
+++ b/examples/camera/videosettings.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIDEOSETTINGS_H
+#define VIDEOSETTINGS_H
+
+#include <QtGui/QDialog>
+#include <qmediaencodersettings.h>
+
+QT_BEGIN_NAMESPACE
+class QComboBox;
+namespace Ui {
+ class VideoSettingsUi;
+}
+
+class QMediaRecorder;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class VideoSettings : public QDialog {
+ Q_OBJECT
+public:
+ VideoSettings(QMediaRecorder *mediaRecorder, QWidget *parent = 0);
+ ~VideoSettings();
+
+ QAudioEncoderSettings audioSettings() const;
+ void setAudioSettings(const QAudioEncoderSettings&);
+
+ QVideoEncoderSettings videoSettings() const;
+ void setVideoSettings(const QVideoEncoderSettings&);
+
+ QString format() const;
+ void setFormat(const QString &format);
+
+protected:
+ void changeEvent(QEvent *e);
+
+private:
+ QVariant boxValue(const QComboBox*) const;
+ void selectComboBoxItem(QComboBox *box, const QVariant &value);
+
+ Ui::VideoSettingsUi *ui;
+ QMediaRecorder *mediaRecorder;
+};
+
+#endif // VIDEOSETTINGS_H
diff --git a/examples/camera/videosettings.ui b/examples/camera/videosettings.ui
new file mode 100644
index 000000000..f6aa004c5
--- /dev/null
+++ b/examples/camera/videosettings.ui
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>VideoSettingsUi</class>
+ <widget class="QDialog" name="VideoSettingsUi">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>561</width>
+ <height>369</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <widget class="QScrollArea" name="scrollArea">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="scrollAreaWidgetContents">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>543</width>
+ <height>250</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Audio</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0" colspan="2">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Audio Codec:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QComboBox" name="audioCodecBox"/>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Sample Rate:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QComboBox" name="audioSampleRateBox"/>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Quality:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QSlider" name="audioQualitySlider">
+ <property name="maximum">
+ <number>4</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1" rowspan="3">
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Video</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0" colspan="2">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>Resolution:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QComboBox" name="videoResolutionBox"/>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Framerate:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QComboBox" name="videoFramerateBox"/>
+ </item>
+ <item row="4" column="0" colspan="2">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Video Codec:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0" colspan="2">
+ <widget class="QComboBox" name="videoCodecBox"/>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Quality:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QSlider" name="videoQualitySlider">
+ <property name="maximum">
+ <number>4</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Container Format:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QComboBox" name="containerFormatBox"/>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>14</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>VideoSettingsUi</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>322</x>
+ <y>272</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>44</x>
+ <y>230</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>VideoSettingsUi</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>405</x>
+ <y>262</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>364</x>
+ <y>227</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/examples/declarative-camera/CameraButton.qml b/examples/declarative-camera/CameraButton.qml
new file mode 100644
index 000000000..cc0b1e787
--- /dev/null
+++ b/examples/declarative-camera/CameraButton.qml
@@ -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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+
+Item {
+ id: button
+
+ signal clicked
+
+ property string text
+ property color color: "white"
+
+ width : 144
+ height: 70
+
+ BorderImage {
+ id: buttonImage
+ source: "images/toolbutton.sci"
+ width: button.width; height: button.height
+ }
+ MouseArea {
+ id: mouseRegion
+ anchors.fill: buttonImage
+ onClicked: { button.clicked(); }
+ }
+ Text {
+ id: btnText
+ color: button.color
+ anchors.centerIn: buttonImage; font.bold: true
+ text: button.text; style: Text.Raised; styleColor: "black"
+ font.pixelSize: 14
+ }
+}
diff --git a/examples/declarative-camera/CameraPropertyButton.qml b/examples/declarative-camera/CameraPropertyButton.qml
new file mode 100644
index 000000000..8787ecbe2
--- /dev/null
+++ b/examples/declarative-camera/CameraPropertyButton.qml
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import QtMultimediaKit 1.1
+
+Item {
+ id: propertyButton
+ property alias value : popup.currentValue
+ property alias model : popup.model
+
+ width : 144
+ height: 70
+
+ BorderImage {
+ id: buttonImage
+ source: "images/toolbutton.sci"
+ width: propertyButton.width; height: propertyButton.height
+ }
+
+ CameraButton {
+ anchors.fill: parent
+ Image {
+ anchors.centerIn: parent
+ source: popup.currentItem.icon
+ }
+
+ onClicked: popup.toggle()
+ }
+
+ CameraPropertyPopup {
+ id: popup
+ anchors.right: parent.left
+ anchors.rightMargin: 16
+ anchors.top: parent.top
+ state: "invisible"
+ visible: opacity > 0
+
+ currentValue: propertyButton.value
+
+ states: [
+ State {
+ name: "invisible"
+ PropertyChanges { target: popup; opacity: 0 }
+ PropertyChanges { target: camera; focus: true }
+ },
+
+ State {
+ name: "visible"
+ PropertyChanges { target: popup; opacity: 1.0 }
+ }
+ ]
+
+ transitions: Transition {
+ NumberAnimation { properties: "opacity"; duration: 100 }
+ }
+
+ function toggle() {
+ if (state == "visible")
+ state = "invisible";
+ else
+ state = "visible";
+ }
+
+ onSelected: {
+ popup.state = "invisible"
+ }
+ }
+}
+
diff --git a/examples/declarative-camera/CameraPropertyPopup.qml b/examples/declarative-camera/CameraPropertyPopup.qml
new file mode 100644
index 000000000..4d49bb904
--- /dev/null
+++ b/examples/declarative-camera/CameraPropertyPopup.qml
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+
+Rectangle {
+ id: propertyPopup
+
+ property alias model : view.model
+ property variant currentValue
+ property variant currentItem : model.get(view.currentIndex)
+
+ property int itemWidth : 100
+ property int itemHeight : 70
+ property int columns : 2
+
+ width: columns*itemWidth + view.anchors.margins*2
+ height: Math.ceil(model.count/columns)*itemHeight + view.anchors.margins*2 + 25
+
+ radius: 5
+ border.color: "#000000"
+ border.width: 2
+ smooth: true
+ color: "#5e5e5e"
+
+ signal selected
+
+ function indexForValue(value) {
+ for (var i = 0; i < view.count; i++) {
+ if (model.get(i).value == value) {
+ return i;
+ }
+ }
+
+ return 0;
+ }
+
+ GridView {
+ id: view
+ anchors.fill: parent
+ anchors.margins: 5
+ cellWidth: propertyPopup.itemWidth
+ cellHeight: propertyPopup.itemHeight
+ snapMode: ListView.SnapOneItem
+ highlightFollowsCurrentItem: true
+ highlight: Rectangle { color: "gray"; radius: 5 }
+ currentIndex: indexForValue(propertyPopup.currentValue)
+
+ onCurrentIndexChanged: {
+ propertyPopup.currentValue = model.get(view.currentIndex).value
+ }
+
+ delegate: Item {
+ width: propertyPopup.itemWidth
+ height: 70
+
+ Image {
+ anchors.centerIn: parent
+ source: icon
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ propertyPopup.currentValue = value
+ propertyPopup.selected(value)
+ }
+ }
+ }
+ }
+
+ Text {
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 8
+ anchors.left: parent.left
+ anchors.leftMargin: 16
+
+ color: "#ffffff"
+ font.bold: true
+ style: Text.Raised;
+ styleColor: "black"
+ font.pixelSize: 14
+
+ text: view.model.get(view.currentIndex).text
+ }
+}
diff --git a/examples/declarative-camera/CaptureControls.qml b/examples/declarative-camera/CaptureControls.qml
new file mode 100644
index 000000000..e431b73b5
--- /dev/null
+++ b/examples/declarative-camera/CaptureControls.qml
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import QtMultimediaKit 1.1
+
+FocusScope {
+ property Camera camera
+ property bool previewAvailable : false
+
+ property alias whiteBalance : wbModesButton.value
+ property alias flashMode : flashModesButton.value
+ property alias exposureCompensation : exposureCompensationButton.value
+
+ property int buttonsPanelWidth: buttonPaneShadow.width
+
+ signal previewSelected
+ id : captureControls
+
+ Rectangle {
+ id: buttonPaneShadow
+ width: buttonPanningPane.width + 16
+ height: parent.height
+ anchors.top: parent.top
+ anchors.right: parent.right
+ color: Qt.rgba(0.08, 0.08, 0.08, 1)
+
+ Flickable {
+ id: buttonPanningPane
+ anchors {
+ right: parent.right
+ top: parent.top
+ bottom: parent.bottom
+ margins: 8
+ }
+ width: buttonsColumn.width
+
+ contentWidth: buttonsColumn.width
+ contentHeight: buttonsColumn.height
+
+ Column {
+ id: buttonsColumn
+ spacing: 8
+
+ FocusButton {
+ camera: captureControls.camera
+ }
+
+ CameraButton {
+ text: "Capture"
+ onClicked: camera.captureImage()
+ }
+
+ CameraPropertyButton {
+ id : flashModesButton
+ value: Camera.FlashOff
+ model: ListModel {
+ ListElement {
+ icon: "images/camera_flash_auto.png"
+ value: Camera.FlashAuto
+ text: "Auto"
+ }
+ ListElement {
+ icon: "images/camera_flash_off.png"
+ value: Camera.FlashOff
+ text: "Off"
+ }
+ ListElement {
+ icon: "images/camera_flash_fill.png"
+ value: Camera.FlashOn
+ text: "On"
+ }
+ ListElement {
+ icon: "images/camera_flash_redeye.png"
+ value: Camera.FlashRedEyeReduction
+ text: "Red Eye Reduction"
+ }
+ }
+ }
+
+ CameraPropertyButton {
+ id : wbModesButton
+ value: Camera.WhiteBalanceAuto
+ model: ListModel {
+ ListElement {
+ icon: "images/camera_auto_mode.png"
+ value: Camera.WhiteBalanceAuto
+ text: "Auto"
+ }
+ ListElement {
+ icon: "images/camera_white_balance_sunny.png"
+ value: Camera.WhiteBalanceSunlight
+ text: "Sunlight"
+ }
+ ListElement {
+ icon: "images/camera_white_balance_cloudy.png"
+ value: Camera.WhiteBalanceCloudy
+ text: "Cloudy"
+ }
+ ListElement {
+ icon: "images/camera_white_balance_incandescent.png"
+ value: Camera.WhiteBalanceIncandescent
+ text: "Incandescent"
+ }
+ ListElement {
+ icon: "images/camera_white_balance_flourescent.png"
+ value: Camera.WhiteBalanceFluorescent
+ text: "Fluorescent"
+ }
+ }
+ }
+
+ ExposureCompensationButton {
+ id : exposureCompensationButton
+ }
+
+ CameraButton {
+ text: "View"
+ onClicked: captureControls.previewSelected()
+ visible: captureControls.previewAvailable
+ }
+
+ CameraButton {
+ id: quitButton
+ text: "Quit"
+ onClicked: Qt.quit()
+ }
+
+ }
+ }
+ }
+
+
+ Item {
+ id: exposureDetails
+ anchors.bottom : parent.bottom
+ anchors.left : parent.left
+ anchors.bottomMargin: 16
+ anchors.leftMargin: 16
+ height: childrenRect.height
+ width: childrenRect.width
+
+ visible : camera.lockStatus == Camera.Locked
+
+ Rectangle {
+ opacity: 0.4
+ color: "black"
+ anchors.fill: parent
+ }
+
+ Row {
+ spacing : 16
+
+ Text {
+ text: "Av: "+camera.aperture.toFixed(1)
+ font.pixelSize: 18
+ color: "white"
+ visible: camera.aperture > 0
+ }
+
+ Text {
+ font.pixelSize: 18
+ color: "white"
+ visible: camera.shutterSpped > 0
+ text: "Tv: "+printableExposureTime(camera.shutterSpeed)
+
+ function printableExposureTime(t) {
+ if (t > 3.9)
+ return "Tv: "+t.toFixed() + "\"";
+
+ if (t > 0.24 )
+ return "Tv: "+t.toFixed(1) + "\"";
+
+ if (t > 0)
+ return "Tv: 1/"+(1/t).toFixed();
+
+ return "";
+ }
+ }
+
+ Text {
+ text: "ISO: "+camera.iso.toFixed()
+ font.pixelSize: 18
+ color: "white"
+ visible: camera.iso > 0
+ }
+ }
+ }
+
+ ZoomControl {
+ x : 0
+ y : 0
+ width : 100
+ height: parent.height
+
+ currentZoom: camera.digitalZoom
+ maximumZoom: Math.min(4.0, camera.maximumDigitalZoom)
+ onZoomTo: camera.setDigitalZoom(value)
+ }
+}
diff --git a/examples/declarative-camera/ExposureCompensationButton.qml b/examples/declarative-camera/ExposureCompensationButton.qml
new file mode 100644
index 000000000..98e038b8a
--- /dev/null
+++ b/examples/declarative-camera/ExposureCompensationButton.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+
+Item {
+ id: exposureCompensation
+ property real value : flickableList.items[flickableList.index]
+ signal clicked
+
+ width : 144
+ height: 70
+
+ BorderImage {
+ id: buttonImage
+ source: "images/toolbutton.sci"
+ width: exposureCompensation.width; height: exposureCompensation.height
+ }
+
+ Text {
+ text: "Ev:"
+ x: 8
+ y: 8
+ font.pixelSize: 18
+ color: "white"
+ }
+
+ FlickableList {
+ anchors.fill: buttonImage
+ id: flickableList
+ items: ["-2", "-1.5", "-1", "-0.5", "0", "+0.5", "+1", "+1.5", "+2"]
+ index: 4
+
+ onClicked: exposureCompensation.clicked()
+
+ delegate: Text {
+ font.pixelSize: 22
+ color: "white"
+ styleColor: "black"
+ width: flickableList.width
+ height: flickableList.height
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: flickableList.items[index]
+ }
+ }
+}
+
diff --git a/examples/declarative-camera/FlickableList.qml b/examples/declarative-camera/FlickableList.qml
new file mode 100644
index 000000000..f33c45311
--- /dev/null
+++ b/examples/declarative-camera/FlickableList.qml
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+
+Item {
+ id: flickableList
+ clip: true
+
+ signal clicked
+
+ property alias delegate : repeater.delegate
+
+ property variant items: []
+ property int index: 0
+ property int itemWidth : flickableList.width
+
+ function scrollTo(id) {
+ var x = id*flickableList.itemWidth
+ if (flickArea.contentX != x) {
+ centeringAnimation.stop();
+ flickArea.newX = id*flickableList.itemWidth
+ centeringAnimation.start();
+ }
+ }
+
+ onIndexChanged: scrollTo(index)
+ onWidthChanged: scrollTo(index)
+
+ Flickable {
+ id: flickArea
+ property int newX: 0
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ var x = mapToItem(flickableList, mouseX, mouseY).x
+
+ if (x < flickableList.width/3) {
+ if (flickableList.index > 0)
+ flickableList.scrollTo(flickableList.index-1);
+ } else if (x > flickableList.width*2/3) {
+ if (flickableList.index < flickableList.items.length-1)
+ flickableList.scrollTo(flickableList.index+1);
+ } else {
+ flickableList.clicked()
+ }
+
+ }
+ }
+
+ PropertyAnimation {
+ id: centeringAnimation
+ target: flickArea
+ properties: "contentX"
+ easing.type: Easing.OutQuad
+ from: flickArea.contentX
+ to: flickArea.newX
+
+ onCompleted: {
+ flickableList.index = flickArea.newX / flickableList.itemWidth
+ }
+ }
+
+ onMovementStarted: {
+ centeringAnimation.stop();
+ }
+
+ onMovementEnded: {
+ var modulo = flickArea.contentX % flickableList.itemWidth;
+ var offset = flickableList.itemWidth / 2;
+ flickArea.newX = modulo < offset ? flickArea.contentX - modulo : flickArea.contentX + (flickableList.itemWidth - modulo);
+ centeringAnimation.start();
+ }
+
+
+ width: flickableList.width
+ height: flickableList.height
+ contentWidth: items.width
+ contentHeight: items.height
+ flickDeceleration: 4000
+
+ Row {
+ id: items
+ Repeater {
+ id: repeater
+ model: flickableList.items.length
+ }
+ }
+ }
+}
diff --git a/examples/declarative-camera/FocusButton.qml b/examples/declarative-camera/FocusButton.qml
new file mode 100644
index 000000000..39848c043
--- /dev/null
+++ b/examples/declarative-camera/FocusButton.qml
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import QtMultimediaKit 1.1
+
+CameraButton {
+ property Camera camera
+
+ onClicked: {
+ if (camera.lockStatus == Camera.Unlocked)
+ camera.searchAndLock();
+ else
+ camera.unlock();
+ }
+
+ text: {
+ if (camera.lockStatus == Camera.Unlocked)
+ "Focus";
+ else if (camera.lockStatus == Camera.Searching)
+ "Focusing"
+ else
+ "Unlock"
+ }
+}
diff --git a/examples/declarative-camera/PhotoPreview.qml b/examples/declarative-camera/PhotoPreview.qml
new file mode 100644
index 000000000..c161d7f1c
--- /dev/null
+++ b/examples/declarative-camera/PhotoPreview.qml
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import QtMultimediaKit 1.1
+
+Item {
+ property alias source : preview.source
+ signal closed
+
+ Image {
+ id: preview
+ anchors.fill : parent
+ fillMode: Image.PreserveAspectFit
+ smooth: true
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ parent.closed();
+ }
+ }
+}
+
diff --git a/examples/declarative-camera/ZoomControl.qml b/examples/declarative-camera/ZoomControl.qml
new file mode 100644
index 000000000..681f63bd5
--- /dev/null
+++ b/examples/declarative-camera/ZoomControl.qml
@@ -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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import QtMultimediaKit 1.1
+
+Item {
+ id : zoomControl
+ property real currentZoom : 1
+ property real maximumZoom : 1
+ signal zoomTo(real value)
+
+ MouseArea {
+ id : mouseArea
+ anchors.fill: parent
+
+ property real initialZoom : 0
+ property real initialPos : 0
+
+ onPressed: {
+ initialPos = mouseY
+ initialZoom = zoomControl.currentZoom
+ }
+
+ onMousePositionChanged: {
+ if (pressed) {
+ var target = initialZoom * Math.pow(2, (initialPos-mouseY)/zoomControl.height);
+ target = Math.max(1, Math.min(target, zoomControl.maximumZoom))
+ zoomControl.zoomTo(target)
+ }
+ }
+ }
+
+ Item {
+ id : bar
+ x : 16
+ y : parent.height/4
+ width : 24
+ height : parent.height/2
+ opacity : 0
+
+ Rectangle {
+ anchors.fill: parent
+
+ smooth: true
+ radius: 8
+ border.color: "black"
+ border.width: 2
+ color: "white"
+ opacity: 0.3
+ }
+
+ Rectangle {
+ x : 0
+ y : parent.height * (1.0 - (zoomControl.currentZoom-1.0) / (zoomControl.maximumZoom-1.0))
+ width: parent.width
+ height: parent.height - y
+ smooth: true
+ radius: 8
+ color: "black"
+ opacity: 0.5
+ }
+
+ states: State {
+ name: "ShowBar"
+ when: mouseArea.pressed || zoomControl.currentZoom > 1.0
+ PropertyChanges { target: bar; opacity: 1 }
+ }
+
+ transitions: [
+ Transition {
+ to : "ShowBar"
+ NumberAnimation { properties: "opacity"; duration: 100 }
+ },
+ Transition {
+ from : "ShowBar"
+ NumberAnimation { properties: "opacity"; duration: 500 }
+ }
+ ]
+ }
+}
diff --git a/examples/declarative-camera/camerakeyevent_symbian/camerakeyevent_symbian.cpp b/examples/declarative-camera/camerakeyevent_symbian/camerakeyevent_symbian.cpp
new file mode 100644
index 000000000..30723af40
--- /dev/null
+++ b/examples/declarative-camera/camerakeyevent_symbian/camerakeyevent_symbian.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "camerakeyevent_symbian.h"
+
+#include <QtGui/QWidget> // WId
+#include <eikon.hrh> // EKeyCamera
+#include <coecntrl.h> // CCoeControl (WId)
+#include <w32std.h> // RWindowbase, RWindowGroup, RWsSession
+
+QSymbianCameraKeyListener::QSymbianCameraKeyListener(QWidget *widget):
+ QObject(widget),
+ m_widget(widget)
+{
+ if (!m_widget)
+ return;
+
+ // Get view's native Symbian window
+ WId windowId = 0;
+ if (m_widget->internalWinId())
+ windowId = m_widget->internalWinId();
+ else if (m_widget->parentWidget() && m_widget->effectiveWinId())
+ windowId = m_widget->effectiveWinId();
+ RWindowBase *window = windowId ? static_cast<RWindowBase*>(windowId->DrawableWindow()) : 0;
+
+ // Get hold of the window group
+ TInt wGroupId = window ? window->WindowGroupId() : 0;
+ if (!wGroupId)
+ return;
+ RWsSession &wsSession = CCoeEnv::Static()->WsSession();
+ TUint wGroupHandle = wsSession.GetWindowGroupHandle(wGroupId);
+ if (wGroupHandle) {
+ RWindowGroup wGroup(wsSession);
+ wGroup.Construct(wGroupHandle);
+ if (wGroup.CaptureKey(EKeyCamera, 0, 0, 100) < 0)
+ qWarning("Unable to register for camera capture key events, SwEvent capability may be missing");
+ }
+}
+
+QSymbianCameraKeyListener::~QSymbianCameraKeyListener()
+{
+ if (!m_widget)
+ return;
+
+ // Get view's native Symbian window
+ WId windowId = 0;
+ if (m_widget->internalWinId())
+ windowId = m_widget->internalWinId();
+ else if (m_widget->parentWidget() && m_widget->effectiveWinId())
+ windowId = m_widget->effectiveWinId();
+ RWindowBase *window = windowId ? static_cast<RWindowBase*>(windowId->DrawableWindow()) : 0;
+
+ // Get hold of the window group
+ TInt wGroupId = window ? window->WindowGroupId() : 0;
+ if (!wGroupId)
+ return;
+ RWsSession &wsSession = CCoeEnv::Static()->WsSession();
+ TUint wGroupHandle = wsSession.GetWindowGroupHandle(wGroupId);
+ if (wGroupHandle) {
+ RWindowGroup wGroup(wsSession);
+ wGroup.Construct(wGroupHandle);
+ wGroup.CancelCaptureKey(EKeyCamera);
+ }
+}
diff --git a/examples/declarative-camera/camerakeyevent_symbian/camerakeyevent_symbian.h b/examples/declarative-camera/camerakeyevent_symbian/camerakeyevent_symbian.h
new file mode 100644
index 000000000..4cd5701b9
--- /dev/null
+++ b/examples/declarative-camera/camerakeyevent_symbian/camerakeyevent_symbian.h
@@ -0,0 +1,87 @@
+#ifndef CAMERAKEYEVENT_SYMBIAN_H
+#define CAMERAKEYEVENT_SYMBIAN_H
+
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ * Description:
+ * This header can be used to register application on Symbian platforms
+ * for the Camera capture button key events. Application can avoid native
+ * camera application from starting by not forwarding the key event.
+ *
+ * Usage:
+ * Application needs to include this header and include the needed Symbian
+ * libraries. Optionally application can include camerakeyevent_symbian.pri
+ * file. Application can register and unregister for the Camera capture
+ * key events by creating/destructing the QSymbianCameraKeyListener helper
+ * object. The widget needs to be shown before it registers for the
+ * Camera key event.
+ *
+ * Libraries needed:
+ * User needs to define following in the .pro file (or optionally include
+ * the camerakeyevent_symbian.pri):
+ * LIBS += -lcone -lws32
+ *
+ * Symbian Capabilities needed:
+ * To use this header user needs to have SwEvent capability (included in
+ * the camerakeyevent_symbian.pri):
+ * TARGET.CAPABILITY += SwEvent
+ */
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+QT_FORWARD_DECLARE_CLASS(QWidget)
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class QSymbianCameraKeyListener : public QObject
+{
+ Q_OBJECT
+public:
+ QSymbianCameraKeyListener(QWidget *parent = 0);
+ ~QSymbianCameraKeyListener();
+private:
+ QWidget *m_widget;
+};
+
+#endif // CAMERAKEYEVENT_SYMBIAN_H
diff --git a/examples/declarative-camera/camerakeyevent_symbian/camerakeyevent_symbian.pri b/examples/declarative-camera/camerakeyevent_symbian/camerakeyevent_symbian.pri
new file mode 100644
index 000000000..097c3b245
--- /dev/null
+++ b/examples/declarative-camera/camerakeyevent_symbian/camerakeyevent_symbian.pri
@@ -0,0 +1,7 @@
+message("camerakeyevent_symbian: Including Symbian camera capture key event register methods")
+
+HEADERS += $$PWD/camerakeyevent_symbian.h
+SOURCES += $$PWD/camerakeyevent_symbian.cpp
+INCLUDEPATH += $$PWD
+LIBS *= -lcone -lws32
+TARGET.CAPABILITY *= SwEvent
diff --git a/examples/declarative-camera/declarative-camera.pro b/examples/declarative-camera/declarative-camera.pro
new file mode 100644
index 000000000..297361cf3
--- /dev/null
+++ b/examples/declarative-camera/declarative-camera.pro
@@ -0,0 +1,31 @@
+include (../mobility_examples.pri)
+
+TEMPLATE=app
+
+QT += declarative network
+
+!maemo5 {
+ contains(QT_CONFIG, opengl) {
+ QT += opengl
+ }
+}
+
+win32 {
+ #required by Qt SDK to resolve Mobility libraries
+ CONFIG+=mobility
+ MOBILITY+=multimedia
+}
+
+SOURCES += $$PWD/qmlcamera.cpp
+!mac:TARGET = qml_camera
+else:TARGET = QmlCamera
+
+RESOURCES += declarative-camera.qrc
+
+symbian {
+ include(camerakeyevent_symbian/camerakeyevent_symbian.pri)
+ load(data_caging_paths)
+ TARGET.CAPABILITY += UserEnvironment NetworkServices Location ReadUserData WriteUserData
+ TARGET.EPOCHEAPSIZE = 0x20000 0x3000000
+}
+
diff --git a/examples/declarative-camera/declarative-camera.qml b/examples/declarative-camera/declarative-camera.qml
new file mode 100644
index 000000000..0d9f984de
--- /dev/null
+++ b/examples/declarative-camera/declarative-camera.qml
@@ -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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import QtMultimediaKit 1.1
+
+Rectangle {
+ id : cameraUI
+ color: "black"
+ state: "PhotoCapture"
+
+ states: [
+ State {
+ name: "PhotoCapture"
+ StateChangeScript {
+ script: {
+ camera.visible = true
+ camera.focus = true
+ stillControls.visible = true
+ photoPreview.visible = false
+ }
+ }
+ },
+ State {
+ name: "PhotoPreview"
+ StateChangeScript {
+ script: {
+ camera.visible = false
+ stillControls.visible = false
+ photoPreview.visible = true
+ photoPreview.focus = true
+ }
+ }
+ }
+ ]
+
+ PhotoPreview {
+ id : photoPreview
+ anchors.fill : parent
+ onClosed: cameraUI.state = "PhotoCapture"
+ focus: visible
+
+ Keys.onPressed : {
+ //return to capture mode if the shutter button is touched
+ if (event.key == Qt.Key_CameraFocus && !event.isAutoRepeat) {
+ cameraUI.state = "PhotoCapture"
+ event.accepted = true;
+ }
+ }
+ }
+
+ Camera {
+ id: camera
+ x: 0
+ y: 0
+ width: parent.width - stillControls.buttonsPanelWidth
+ height: parent.height
+ focus: visible //to receive focus and capture key events
+ //captureResolution : "640x480"
+
+ flashMode: stillControls.flashMode
+ whiteBalanceMode: stillControls.whiteBalance
+ exposureCompensation: stillControls.exposureCompensation
+
+ onImageCaptured : {
+ photoPreview.source = preview
+ stillControls.previewAvailable = true
+ cameraUI.state = "PhotoPreview"
+ }
+ }
+
+ CaptureControls {
+ id: stillControls
+ anchors.fill: parent
+ camera: camera
+ onPreviewSelected: cameraUI.state = "PhotoPreview"
+ }
+
+}
diff --git a/examples/declarative-camera/declarative-camera.qmlproject b/examples/declarative-camera/declarative-camera.qmlproject
new file mode 100644
index 000000000..53f5ecb8d
--- /dev/null
+++ b/examples/declarative-camera/declarative-camera.qmlproject
@@ -0,0 +1,18 @@
+/* File generated by QtCreator */
+
+import QmlProject 1.0
+
+Project {
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+ /* List of plugin directories passed to QML runtime */
+ // importPaths: [ "../exampleplugin" ]
+}
diff --git a/examples/declarative-camera/declarative-camera.qrc b/examples/declarative-camera/declarative-camera.qrc
new file mode 100644
index 000000000..f8ce52784
--- /dev/null
+++ b/examples/declarative-camera/declarative-camera.qrc
@@ -0,0 +1,28 @@
+<!DOCTYPE RCC>
+ <RCC version="1.0">
+
+ <qresource prefix="/">
+ <file>declarative-camera.qml</file>
+ <file>CameraButton.qml</file>
+ <file>CameraPropertyPopup.qml</file>
+ <file>CameraPropertyButton.qml</file>
+ <file>CaptureControls.qml</file>
+ <file>ExposureCompensationButton.qml</file>
+ <file>FlickableList.qml</file>
+ <file>FocusButton.qml</file>
+ <file>PhotoPreview.qml</file>
+ <file>ZoomControl.qml</file>
+ <file>images/camera_auto_mode.png</file>
+ <file>images/camera_camera_setting.png</file>
+ <file>images/camera_flash_auto.png</file>
+ <file>images/camera_flash_fill.png</file>
+ <file>images/camera_flash_off.png</file>
+ <file>images/camera_flash_redeye.png</file>
+ <file>images/camera_white_balance_cloudy.png</file>
+ <file>images/camera_white_balance_flourescent.png</file>
+ <file>images/camera_white_balance_incandescent.png</file>
+ <file>images/camera_white_balance_sunny.png</file>
+ <file>images/toolbutton.png</file>
+ <file>images/toolbutton.sci</file>
+ </qresource>
+ </RCC>
diff --git a/examples/declarative-camera/images/camera_auto_mode.png b/examples/declarative-camera/images/camera_auto_mode.png
new file mode 100644
index 000000000..f168296cf
--- /dev/null
+++ b/examples/declarative-camera/images/camera_auto_mode.png
Binary files differ
diff --git a/examples/declarative-camera/images/camera_camera_setting.png b/examples/declarative-camera/images/camera_camera_setting.png
new file mode 100644
index 000000000..7b993eee9
--- /dev/null
+++ b/examples/declarative-camera/images/camera_camera_setting.png
Binary files differ
diff --git a/examples/declarative-camera/images/camera_flash_auto.png b/examples/declarative-camera/images/camera_flash_auto.png
new file mode 100644
index 000000000..fb5cc40ec
--- /dev/null
+++ b/examples/declarative-camera/images/camera_flash_auto.png
Binary files differ
diff --git a/examples/declarative-camera/images/camera_flash_fill.png b/examples/declarative-camera/images/camera_flash_fill.png
new file mode 100644
index 000000000..7bc5949ac
--- /dev/null
+++ b/examples/declarative-camera/images/camera_flash_fill.png
Binary files differ
diff --git a/examples/declarative-camera/images/camera_flash_off.png b/examples/declarative-camera/images/camera_flash_off.png
new file mode 100644
index 000000000..3c5db10cc
--- /dev/null
+++ b/examples/declarative-camera/images/camera_flash_off.png
Binary files differ
diff --git a/examples/declarative-camera/images/camera_flash_redeye.png b/examples/declarative-camera/images/camera_flash_redeye.png
new file mode 100644
index 000000000..534a087df
--- /dev/null
+++ b/examples/declarative-camera/images/camera_flash_redeye.png
Binary files differ
diff --git a/examples/declarative-camera/images/camera_white_balance_cloudy.png b/examples/declarative-camera/images/camera_white_balance_cloudy.png
new file mode 100644
index 000000000..243b699e7
--- /dev/null
+++ b/examples/declarative-camera/images/camera_white_balance_cloudy.png
Binary files differ
diff --git a/examples/declarative-camera/images/camera_white_balance_flourescent.png b/examples/declarative-camera/images/camera_white_balance_flourescent.png
new file mode 100644
index 000000000..032efe1d1
--- /dev/null
+++ b/examples/declarative-camera/images/camera_white_balance_flourescent.png
Binary files differ
diff --git a/examples/declarative-camera/images/camera_white_balance_incandescent.png b/examples/declarative-camera/images/camera_white_balance_incandescent.png
new file mode 100644
index 000000000..98f906741
--- /dev/null
+++ b/examples/declarative-camera/images/camera_white_balance_incandescent.png
Binary files differ
diff --git a/examples/declarative-camera/images/camera_white_balance_sunny.png b/examples/declarative-camera/images/camera_white_balance_sunny.png
new file mode 100644
index 000000000..d7d5c9a36
--- /dev/null
+++ b/examples/declarative-camera/images/camera_white_balance_sunny.png
Binary files differ
diff --git a/examples/declarative-camera/images/toolbutton.png b/examples/declarative-camera/images/toolbutton.png
new file mode 100644
index 000000000..11310013e
--- /dev/null
+++ b/examples/declarative-camera/images/toolbutton.png
Binary files differ
diff --git a/examples/declarative-camera/images/toolbutton.sci b/examples/declarative-camera/images/toolbutton.sci
new file mode 100644
index 000000000..9e4f96530
--- /dev/null
+++ b/examples/declarative-camera/images/toolbutton.sci
@@ -0,0 +1,5 @@
+border.left: 15
+border.top: 4
+border.bottom: 4
+border.right: 15
+source: toolbutton.png
diff --git a/examples/declarative-camera/qmlcamera.cpp b/examples/declarative-camera/qmlcamera.cpp
new file mode 100644
index 000000000..f6d3e9c36
--- /dev/null
+++ b/examples/declarative-camera/qmlcamera.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include <QtDeclarative/QDeclarativeView>
+#include <QtDeclarative/QDeclarativeEngine>
+
+#if !defined(QT_NO_OPENGL)
+#include <QtOpenGL/QGLWidget>
+#endif
+
+#ifdef Q_OS_SYMBIAN
+#include "camerakeyevent_symbian.h"
+#endif // Q_OS_SYMBIAN
+
+int main(int argc, char *argv[])
+{
+
+#if defined (Q_WS_X11) || defined (Q_WS_MAC) || defined (Q_OS_SYMBIAN)
+ //### default to using raster graphics backend for now
+ bool gsSpecified = false;
+ for (int i = 0; i < argc; ++i) {
+ QString arg = argv[i];
+ if (arg == "-graphicssystem") {
+ gsSpecified = true;
+ break;
+ }
+ }
+
+ if (!gsSpecified)
+ QApplication::setGraphicsSystem("raster");
+#endif
+
+ QApplication application(argc, argv);
+ const QString mainQmlApp = QLatin1String("qrc:/declarative-camera.qml");
+ QDeclarativeView view;
+#if !defined(QT_NO_OPENGL) && !defined(Q_WS_MAEMO_5) && !defined(Q_WS_S60)
+ view.setViewport(new QGLWidget);
+#endif
+ view.setSource(QUrl(mainQmlApp));
+ view.setResizeMode(QDeclarativeView::SizeRootObjectToView);
+ // Qt.quit() called in embedded .qml by default only emits
+ // quit() signal, so do this (optionally use Qt.exit()).
+ QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit()));
+#if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
+ view.setGeometry(application.desktop()->screenGeometry());
+ view.showFullScreen();
+#ifdef Q_OS_SYMBIAN
+ new QSymbianCameraKeyListener(&view);
+#endif // Q_OS_SYMBIAN
+#else
+ view.setGeometry(QRect(100, 100, 800, 480));
+ view.show();
+#endif
+ return application.exec();
+}
+
diff --git a/examples/examples.pro b/examples/examples.pro
new file mode 100644
index 000000000..fd0069732
--- /dev/null
+++ b/examples/examples.pro
@@ -0,0 +1,21 @@
+TEMPLATE = subdirs
+
+SUBDIRS += \
+ radio \
+ camera \
+ slideshow \
+ audiorecorder \
+ audiodevices \
+ audioinput \
+ audiooutput \
+ videographicsitem \
+ videowidget
+
+contains(QT_CONFIG, declarative) {
+ SUBDIRS += declarative-camera
+}
+
+sources.path = $$QT_MOBILITY_EXAMPLES
+
+INSTALLS += sources
+
diff --git a/examples/main.cpp b/examples/main.cpp
new file mode 100644
index 000000000..451be57b9
--- /dev/null
+++ b/examples/main.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include "audiodevices.h"
+
+int main(int argv, char **args)
+{
+ QApplication app(argv, args);
+ app.setApplicationName("Audio Device Test");
+
+ AudioTest audio;
+#ifdef Q_OS_SYMBIAN
+ audio.showMaximized();
+#else
+ audio.show();
+#endif
+
+ return app.exec();
+}
diff --git a/examples/radio/main.cpp b/examples/radio/main.cpp
new file mode 100644
index 000000000..89e2c70b6
--- /dev/null
+++ b/examples/radio/main.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "radio.h"
+
+#include <QtGui>
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ Radio radio;
+#ifdef Q_OS_SYMBIAN
+ radio.showMaximized();
+#else
+ radio.show();
+#endif
+
+ return app.exec();
+};
diff --git a/examples/radio/radio.cpp b/examples/radio/radio.cpp
new file mode 100644
index 000000000..b37b0b551
--- /dev/null
+++ b/examples/radio/radio.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "radio.h"
+
+#include <QtGui>
+
+Radio::Radio()
+{
+ radio = new QRadioTuner;
+ connect(radio,SIGNAL(frequencyChanged(int)),this,SLOT(freqChanged(int)));
+ connect(radio,SIGNAL(signalStrengthChanged(int)),this,SLOT(signalChanged(int)));
+ connect(radio, SIGNAL(error(QRadioTuner::Error)), this, SLOT(error(QRadioTuner::Error)));
+
+ if(radio->isBandSupported(QRadioTuner::FM))
+ radio->setBand(QRadioTuner::FM);
+
+ QWidget *window = new QWidget;
+ QVBoxLayout* layout = new QVBoxLayout;
+ QHBoxLayout* buttonBar = new QHBoxLayout;
+#if defined Q_OS_SYMBIAN // this is so that we can see all buttons also in 3.1 devices, where the screens are smaller..
+ QHBoxLayout* buttonBar2 = new QHBoxLayout;
+#endif
+ QHBoxLayout* topBar = new QHBoxLayout;
+
+ layout->addLayout(topBar);
+
+ freq = new QLabel;
+ freq->setText(QString("%1 kHz").arg(radio->frequency()/1000));
+ topBar->addWidget(freq);
+
+ signal = new QLabel;
+ if (radio->isAvailable())
+ signal->setText(tr("No Signal"));
+ else
+ signal->setText(tr("No radio found"));
+ topBar->addWidget(signal);
+#if defined Q_WS_MAEMO_5
+ QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ topBar->addItem(spacer);
+ volumeSlider = new QSlider(Qt::Horizontal,this);
+#else
+ volumeSlider = new QSlider(Qt::Vertical,this);
+#endif
+ volumeSlider->setRange(0,100);
+ volumeSlider->setValue(50);
+ connect(volumeSlider,SIGNAL(valueChanged(int)),this,SLOT(updateVolume(int)));
+ topBar->addWidget(volumeSlider);
+
+ layout->addLayout(buttonBar);
+#if defined Q_OS_SYMBIAN
+ layout->addLayout(buttonBar2);
+#endif
+
+ searchLeft = new QPushButton;
+ searchLeft->setText(tr("scan Down"));
+ connect(searchLeft,SIGNAL(clicked()),SLOT(searchDown()));
+ buttonBar->addWidget(searchLeft);
+
+ left = new QPushButton;
+ left->setText(tr("Freq Down"));
+ connect(left,SIGNAL(clicked()),SLOT(freqDown()));
+#if defined Q_OS_SYMBIAN
+ buttonBar2->addWidget(left);
+#else
+ buttonBar->addWidget(left);
+#endif
+
+ right = new QPushButton;
+ connect(right,SIGNAL(clicked()),SLOT(freqUp()));
+ right->setText(tr("Freq Up"));
+#if defined Q_OS_SYMBIAN
+ buttonBar2->addWidget(right);
+#else
+ buttonBar->addWidget(right);
+#endif
+
+ searchRight = new QPushButton;
+ searchRight->setText(tr("scan Up"));
+ connect(searchRight,SIGNAL(clicked()),SLOT(searchUp()));
+ buttonBar->addWidget(searchRight);
+
+ window->setLayout(layout);
+ setCentralWidget(window);
+ window->show();
+
+ radio->start();
+}
+
+Radio::~Radio()
+{
+}
+
+void Radio::freqUp()
+{
+ int f = radio->frequency();
+ f = f + radio->frequencyStep(QRadioTuner::FM);
+ radio->setFrequency(f);
+}
+
+void Radio::freqDown()
+{
+ int f = radio->frequency();
+ f = f - radio->frequencyStep(QRadioTuner::FM);
+ radio->setFrequency(f);
+}
+
+void Radio::searchUp()
+{
+ radio->searchForward();
+}
+
+void Radio::searchDown()
+{
+ radio->searchBackward();
+}
+
+void Radio::freqChanged(int)
+{
+ freq->setText(QString("%1 kHz").arg(radio->frequency()/1000));
+}
+
+void Radio::signalChanged(int)
+{
+ if(radio->signalStrength() > 25)
+ signal->setText(tr("Got Signal"));
+ else
+ signal->setText(tr("No Signal"));
+}
+
+void Radio::updateVolume(int v)
+{
+ radio->setVolume(v);
+}
+
+void Radio::error(QRadioTuner::Error error)
+{
+ const QMetaObject* metaObj = radio->metaObject();
+ QMetaEnum errorEnum = metaObj->enumerator(metaObj->indexOfEnumerator("Error"));
+ qWarning().nospace() << "Warning: Example application received error QRadioTuner::" << errorEnum.valueToKey(error);
+}
+
diff --git a/examples/radio/radio.h b/examples/radio/radio.h
new file mode 100644
index 000000000..2cdcd5c01
--- /dev/null
+++ b/examples/radio/radio.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RADIO_H
+#define RADIO_H
+
+#include <QtGui>
+
+#include <qradiotuner.h>
+
+QT_BEGIN_NAMESPACE
+class QLabel;
+class QPushButton;
+class QSlider;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class Radio : public QMainWindow
+{
+ Q_OBJECT
+public:
+ Radio();
+ ~Radio();
+
+public slots:
+ void freqUp();
+ void freqDown();
+ void searchUp();
+ void searchDown();
+ void freqChanged(int f);
+ void signalChanged(int s);
+ void updateVolume(int v);
+ void error(QRadioTuner::Error error);
+
+private:
+ QLabel* freq;
+ QLabel* signal;
+ QPushButton* left;
+ QPushButton* right;
+ QPushButton* searchLeft;
+ QPushButton* searchRight;
+ QSlider* volumeSlider;
+ QRadioTuner* radio;
+};
+
+#endif
diff --git a/examples/radio/radio.pro b/examples/radio/radio.pro
new file mode 100644
index 000000000..386efd4a5
--- /dev/null
+++ b/examples/radio/radio.pro
@@ -0,0 +1,21 @@
+TEMPLATE = app
+CONFIG += example
+
+INCLUDEPATH += ../../src/multimedia
+include(../mobility_examples.pri)
+
+CONFIG += mobility
+MOBILITY = multimedia
+
+QMAKE_RPATHDIR += $$DESTDIR
+
+HEADERS = \
+ radio.h
+
+SOURCES = \
+ main.cpp \
+ radio.cpp
+
+symbian: {
+ TARGET.CAPABILITY = UserEnvironment WriteDeviceData ReadDeviceData SwEvent
+}
diff --git a/examples/slideshow/main.cpp b/examples/slideshow/main.cpp
new file mode 100644
index 000000000..665c0490d
--- /dev/null
+++ b/examples/slideshow/main.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "slideshow.h"
+
+#include <QtGui>
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ SlideShow slideShow;
+#ifdef Q_OS_SYMBIAN
+ slideShow.showMaximized();
+#else
+ slideShow.show();
+#endif
+
+ return app.exec();
+}
diff --git a/examples/slideshow/slideshow.cpp b/examples/slideshow/slideshow.cpp
new file mode 100644
index 000000000..5c877de66
--- /dev/null
+++ b/examples/slideshow/slideshow.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "slideshow.h"
+
+#include <qmediaservice.h>
+#include <qmediaplaylist.h>
+#include <qvideowidget.h>
+
+#include <QtGui>
+
+SlideShow::SlideShow(QWidget *parent)
+ : QMainWindow(parent)
+ , imageViewer(0)
+ , playlist(0)
+ , statusLabel(0)
+ , countdownLabel(0)
+ , playAction(0)
+ , stopAction(0)
+{
+ imageViewer = new QMediaImageViewer(this);
+
+ connect(imageViewer, SIGNAL(stateChanged(QMediaImageViewer::State)),
+ this, SLOT(stateChanged(QMediaImageViewer::State)));
+ connect(imageViewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)),
+ this, SLOT(statusChanged(QMediaImageViewer::MediaStatus)));
+ connect(imageViewer, SIGNAL(elapsedTimeChanged(int)), this, SLOT(elapsedTimeChanged(int)));
+
+ playlist = new QMediaPlaylist;
+ imageViewer->bind(playlist);
+
+ connect(playlist, SIGNAL(loaded()), this, SLOT(playlistLoaded()));
+ connect(playlist, SIGNAL(loadFailed()), this, SLOT(playlistLoadFailed()));
+
+ QVideoWidget *videoWidget = new QVideoWidget;
+ imageViewer->setVideoOutput(videoWidget);
+
+ menuBar()->addAction(tr("Open Directory..."), this, SLOT(openDirectory()));
+ menuBar()->addAction(tr("Open Playlist..."), this, SLOT(openPlaylist()));
+
+ toolBar = new QToolBar;
+ toolBar->setMovable(false);
+ toolBar->setFloatable(false);
+ toolBar->setEnabled(false);
+
+ toolBar->addAction(
+ style()->standardIcon(QStyle::SP_MediaSkipBackward),
+ tr("Previous"),
+ playlist,
+ SLOT(previous()));
+ stopAction = toolBar->addAction(
+ style()->standardIcon(QStyle::SP_MediaStop), tr("Stop"), imageViewer, SLOT(stop()));
+ playAction = toolBar->addAction(
+ style()->standardIcon(QStyle::SP_MediaPlay), tr("Play"), this, SLOT(play()));
+ toolBar->addAction(
+ style()->standardIcon(QStyle::SP_MediaSkipForward), tr("Next"), playlist, SLOT(next()));
+
+ addToolBar(Qt::BottomToolBarArea, toolBar);
+
+ statusLabel = new QLabel(tr("%1 Images").arg(0));
+ statusLabel->setAlignment(Qt::AlignCenter);
+
+ countdownLabel = new QLabel;
+ countdownLabel->setAlignment(Qt::AlignRight);
+
+ statusBar()->addPermanentWidget(statusLabel, 1);
+ statusBar()->addPermanentWidget(countdownLabel);
+
+ setCentralWidget(videoWidget);
+}
+
+void SlideShow::openPlaylist()
+{
+ QString path = QFileDialog::getOpenFileName(this);
+
+ if (!path.isEmpty()) {
+ playlist->clear();
+ playlist->load(QUrl::fromLocalFile(path));
+ }
+}
+
+void SlideShow::openDirectory()
+{
+ QString path = QFileDialog::getExistingDirectory(this);
+
+ if (!path.isEmpty()) {
+ playlist->clear();
+
+ QDir dir(path);
+
+ foreach (const QString &fileName, dir.entryList(QDir::Files))
+ playlist->addMedia(QUrl::fromLocalFile(dir.absoluteFilePath(fileName)));
+
+ statusChanged(imageViewer->mediaStatus());
+
+ toolBar->setEnabled(playlist->mediaCount() > 0);
+ }
+}
+
+void SlideShow::play()
+{
+ switch (imageViewer->state()) {
+ case QMediaImageViewer::StoppedState:
+ case QMediaImageViewer::PausedState:
+ imageViewer->play();
+ break;
+ case QMediaImageViewer::PlayingState:
+ imageViewer->pause();
+ break;
+ }
+}
+
+void SlideShow::stateChanged(QMediaImageViewer::State state)
+{
+ switch (state) {
+ case QMediaImageViewer::StoppedState:
+ stopAction->setEnabled(false);
+ playAction->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
+ break;
+ case QMediaImageViewer::PlayingState:
+ stopAction->setEnabled(true);
+ playAction->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
+ break;
+ case QMediaImageViewer::PausedState:
+ stopAction->setEnabled(true);
+ playAction->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
+ break;
+ }
+}
+
+void SlideShow::statusChanged(QMediaImageViewer::MediaStatus status)
+{
+ switch (status) {
+ case QMediaImageViewer::NoMedia:
+ statusLabel->setText(tr("%1 Images").arg(playlist->mediaCount()));
+ break;
+ case QMediaImageViewer::LoadingMedia:
+ statusLabel->setText(tr("Image %1 of %2\nLoading...")
+ .arg(playlist->currentIndex())
+ .arg(playlist->mediaCount()));
+ break;
+ case QMediaImageViewer::LoadedMedia:
+ statusLabel->setText(tr("Image %1 of %2")
+ .arg(playlist->currentIndex())
+ .arg(playlist->mediaCount()));
+ break;
+ case QMediaImageViewer::InvalidMedia:
+ statusLabel->setText(tr("Image %1 of %2\nInvalid")
+ .arg(playlist->currentIndex())
+ .arg(playlist->mediaCount()));
+ break;
+ default:
+ break;
+ }
+}
+
+void SlideShow::playlistLoaded()
+{
+ statusChanged(imageViewer->mediaStatus());
+
+ toolBar->setEnabled(playlist->mediaCount() > 0);
+}
+
+void SlideShow::playlistLoadFailed()
+{
+ statusLabel->setText(playlist->errorString());
+
+ toolBar->setEnabled(false);
+}
+
+void SlideShow::elapsedTimeChanged(int time)
+{
+ const int remaining = (imageViewer->timeout() - time) / 1000;
+
+ countdownLabel->setText(tr("%1:%2")
+ .arg(remaining / 60, 2, 10, QLatin1Char('0'))
+ .arg(remaining % 60, 2, 10, QLatin1Char('0')));
+}
diff --git a/examples/slideshow/slideshow.h b/examples/slideshow/slideshow.h
new file mode 100644
index 000000000..196ec4723
--- /dev/null
+++ b/examples/slideshow/slideshow.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SLIDESHOW_H
+#define SLIDESHOW_H
+
+#include <QMainWindow>
+#include <qmediaimageviewer.h>
+
+QT_BEGIN_NAMESPACE
+class QAbstractButton;
+class QLabel;
+class QStackedLayout;
+
+class QMediaPlaylist;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class SlideShow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ SlideShow(QWidget *parent = 0);
+
+private slots:
+ void openPlaylist();
+ void openDirectory();
+
+ void play();
+
+ void stateChanged(QMediaImageViewer::State state);
+ void statusChanged(QMediaImageViewer::MediaStatus status);
+
+ void playlistLoaded();
+ void playlistLoadFailed();
+
+ void elapsedTimeChanged(int time);
+
+private:
+ QMediaImageViewer *imageViewer;
+ QMediaPlaylist *playlist;
+ QLabel *statusLabel;
+ QLabel *countdownLabel;
+ QAction *playAction;
+ QAction *stopAction;
+ QToolBar *toolBar;
+};
+
+#endif
diff --git a/examples/slideshow/slideshow.pro b/examples/slideshow/slideshow.pro
new file mode 100644
index 000000000..76c660a16
--- /dev/null
+++ b/examples/slideshow/slideshow.pro
@@ -0,0 +1,19 @@
+TEMPLATE = app
+TARGET = slideshow
+INCLUDEPATH+=../../src/multimedia
+include (../mobility_examples.pri)
+
+CONFIG += mobility
+MOBILITY = multimedia
+
+HEADERS = \
+ slideshow.h
+
+SOURCES = \
+ main.cpp \
+ slideshow.cpp
+
+symbian {
+ TARGET.CAPABILITY = NetworkServices
+ TARGET.EPOCHEAPSIZE = 0x20000 0x3000000
+}
diff --git a/examples/videographicsitem/main.cpp b/examples/videographicsitem/main.cpp
new file mode 100644
index 000000000..46e66d26c
--- /dev/null
+++ b/examples/videographicsitem/main.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "videoplayer.h"
+
+#include <QtGui/QApplication>
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ VideoPlayer player;
+ player.show();
+
+ return app.exec();
+}
+
diff --git a/examples/videographicsitem/videographicsitem.pro b/examples/videographicsitem/videographicsitem.pro
new file mode 100644
index 000000000..8461bebe6
--- /dev/null
+++ b/examples/videographicsitem/videographicsitem.pro
@@ -0,0 +1,19 @@
+TEMPLATE = app
+CONFIG += example
+
+INCLUDEPATH += ../../src/multimedia ../../src/multimedia/video
+include(../mobility_examples.pri)
+
+CONFIG += mobility
+MOBILITY = multimedia
+
+QMAKE_RPATHDIR += $$DESTDIR
+
+!symbian:contains(QT_CONFIG, opengl): QT += opengl
+
+HEADERS += videoplayer.h \
+ videoitem.h
+
+SOURCES += main.cpp \
+ videoplayer.cpp \
+ videoitem.cpp
diff --git a/examples/videographicsitem/videoitem.cpp b/examples/videographicsitem/videoitem.cpp
new file mode 100644
index 000000000..a0a71a06b
--- /dev/null
+++ b/examples/videographicsitem/videoitem.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "videoitem.h"
+
+#include <QtGui>
+#include <qvideosurfaceformat.h>
+
+VideoItem::VideoItem(QGraphicsItem *parent)
+ : QGraphicsItem(parent)
+ , imageFormat(QImage::Format_Invalid)
+ , framePainted(false)
+{
+}
+
+VideoItem::~VideoItem()
+{
+}
+
+QRectF VideoItem::boundingRect() const
+{
+ return QRectF(QPointF(0,0), surfaceFormat().sizeHint());
+}
+
+void VideoItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ if (currentFrame.map(QAbstractVideoBuffer::ReadOnly)) {
+ const QTransform oldTransform = painter->transform();
+
+ if (surfaceFormat().scanLineDirection() == QVideoSurfaceFormat::BottomToTop) {
+ painter->scale(1, -1);
+ painter->translate(0, -boundingRect().height());
+ }
+
+ painter->drawImage(boundingRect(), QImage(
+ currentFrame.bits(),
+ imageSize.width(),
+ imageSize.height(),
+ imageFormat));
+
+ painter->setTransform(oldTransform);
+
+ framePainted = true;
+
+ currentFrame.unmap();
+ }
+}
+
+QList<QVideoFrame::PixelFormat> VideoItem::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ if (handleType == QAbstractVideoBuffer::NoHandle) {
+ return QList<QVideoFrame::PixelFormat>()
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_ARGB32
+ << QVideoFrame::Format_ARGB32_Premultiplied
+ << QVideoFrame::Format_RGB565
+ << QVideoFrame::Format_RGB555;
+ } else {
+ return QList<QVideoFrame::PixelFormat>();
+ }
+}
+
+bool VideoItem::start(const QVideoSurfaceFormat &format)
+{
+ if (isFormatSupported(format)) {
+ imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
+ imageSize = format.frameSize();
+ framePainted = true;
+
+ QAbstractVideoSurface::start(format);
+
+ prepareGeometryChange();
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void VideoItem::stop()
+{
+ currentFrame = QVideoFrame();
+ framePainted = false;
+
+ QAbstractVideoSurface::stop();
+}
+
+bool VideoItem::present(const QVideoFrame &frame)
+{
+ if (!framePainted) {
+ if (!QAbstractVideoSurface::isActive())
+ setError(StoppedError);
+
+ return false;
+ } else {
+ currentFrame = frame;
+ framePainted = false;
+
+ update();
+
+ return true;
+ }
+}
diff --git a/examples/videographicsitem/videoitem.h b/examples/videographicsitem/videoitem.h
new file mode 100644
index 000000000..85388fb6a
--- /dev/null
+++ b/examples/videographicsitem/videoitem.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIDEOITEM_H
+#define VIDEOITEM_H
+
+#include <qabstractvideosurface.h>
+#include <QtGui/QGraphicsItem>
+
+class VideoItem
+ : public QAbstractVideoSurface,
+ public QGraphicsItem
+{
+ Q_OBJECT
+ Q_INTERFACES(QGraphicsItem)
+public:
+ explicit VideoItem(QGraphicsItem *parentItem = 0);
+ ~VideoItem();
+
+ QRectF boundingRect() const;
+ void paint(
+ QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ //video surface
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
+
+ bool start(const QVideoSurfaceFormat &format);
+ void stop();
+ bool present(const QVideoFrame &frame);
+
+private:
+ QImage::Format imageFormat;
+ QSize imageSize;
+
+ QVideoFrame currentFrame;
+ bool framePainted;
+};
+
+#endif
+
diff --git a/examples/videographicsitem/videoplayer.cpp b/examples/videographicsitem/videoplayer.cpp
new file mode 100644
index 000000000..48df7f36b
--- /dev/null
+++ b/examples/videographicsitem/videoplayer.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "videoplayer.h"
+#include "videoitem.h"
+
+#include <QtGui>
+#include <qvideosurfaceformat.h>
+
+#if !defined(QT_NO_OPENGL) && !defined(Q_OS_SYMBIAN)
+# include <QtOpenGL/QGLWidget>
+#endif
+
+VideoPlayer::VideoPlayer(QWidget *parent, Qt::WindowFlags flags)
+ : QWidget(parent, flags)
+ , mediaPlayer(0, QMediaPlayer::VideoSurface)
+ , videoItem(0)
+ , playButton(0)
+ , positionSlider(0)
+{
+ videoItem = new VideoItem;
+
+ QGraphicsScene *scene = new QGraphicsScene(this);
+ QGraphicsView *graphicsView = new QGraphicsView(scene);
+
+#if !defined(QT_NO_OPENGL) && !defined(Q_OS_SYMBIAN)
+ graphicsView->setViewport(new QGLWidget);
+#endif
+
+ scene->addItem(videoItem);
+
+ QSlider *rotateSlider = new QSlider(Qt::Horizontal);
+ rotateSlider->setRange(-180, 180);
+ rotateSlider->setValue(0);
+
+ connect(rotateSlider, SIGNAL(valueChanged(int)),
+ this, SLOT(rotateVideo(int)));
+
+ QAbstractButton *openButton = new QPushButton(tr("Open..."));
+ connect(openButton, SIGNAL(clicked()), this, SLOT(openFile()));
+
+ playButton = new QPushButton;
+ playButton->setEnabled(false);
+ playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
+
+ connect(playButton, SIGNAL(clicked()),
+ this, SLOT(play()));
+
+ positionSlider = new QSlider(Qt::Horizontal);
+ positionSlider->setRange(0, 0);
+
+ connect(positionSlider, SIGNAL(sliderMoved(int)),
+ this, SLOT(setPosition(int)));
+
+ QBoxLayout *controlLayout = new QHBoxLayout;
+ controlLayout->setMargin(0);
+ controlLayout->addWidget(openButton);
+ controlLayout->addWidget(playButton);
+ controlLayout->addWidget(positionSlider);
+
+ QBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(graphicsView);
+ layout->addWidget(rotateSlider);
+ layout->addLayout(controlLayout);
+
+ setLayout(layout);
+
+ mediaPlayer.setVideoOutput(videoItem);
+ connect(&mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)),
+ this, SLOT(mediaStateChanged(QMediaPlayer::State)));
+ connect(&mediaPlayer, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64)));
+ connect(&mediaPlayer, SIGNAL(durationChanged(qint64)), this, SLOT(durationChanged(qint64)));
+}
+
+VideoPlayer::~VideoPlayer()
+{
+}
+
+
+void VideoPlayer::openFile()
+{
+ QString fileName = QFileDialog::getOpenFileName(this, tr("Open Movie"),QDir::homePath());
+
+ if (!fileName.isEmpty()) {
+ mediaPlayer.setMedia(QUrl::fromLocalFile(fileName));
+
+ playButton->setEnabled(true);
+ }
+}
+
+void VideoPlayer::play()
+{
+ switch(mediaPlayer.state()) {
+ case QMediaPlayer::PlayingState:
+ mediaPlayer.pause();
+ break;
+ default:
+ mediaPlayer.play();
+ break;
+ }
+}
+
+void VideoPlayer::mediaStateChanged(QMediaPlayer::State state)
+{
+ switch(state) {
+ case QMediaPlayer::PlayingState:
+ playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
+ break;
+ default:
+ playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
+ break;
+ }
+}
+
+void VideoPlayer::positionChanged(qint64 position)
+{
+ positionSlider->setValue(position);
+}
+
+void VideoPlayer::durationChanged(qint64 duration)
+{
+ positionSlider->setRange(0, duration);
+}
+
+void VideoPlayer::setPosition(int position)
+{
+ mediaPlayer.setPosition(position);
+}
+
+
+void VideoPlayer::rotateVideo(int angle)
+{
+ //rotate around the center of video element
+ qreal x = videoItem->boundingRect().width() / 2.0;
+ qreal y = videoItem->boundingRect().height() / 2.0;
+ videoItem->setTransform(QTransform().translate(x, y).rotate(angle).translate(-x, -y));
+}
diff --git a/examples/videographicsitem/videoplayer.h b/examples/videographicsitem/videoplayer.h
new file mode 100644
index 000000000..e04d54d59
--- /dev/null
+++ b/examples/videographicsitem/videoplayer.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIDEOPLAYER_H
+#define VIDEOPLAYER_H
+
+#include <qmediaplayer.h>
+
+#include <QtGui/QMovie>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+class QAbstractButton;
+class QSlider;
+QT_END_NAMESPACE
+
+
+class VideoItem;
+
+class VideoPlayer : public QWidget
+{
+ Q_OBJECT
+public:
+ VideoPlayer(QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ ~VideoPlayer();
+
+ QSize sizeHint() const { return QSize(800, 600); }
+
+public slots:
+ void openFile();
+ void play();
+
+private slots:
+ void mediaStateChanged(QMediaPlayer::State state);
+ void positionChanged(qint64 position);
+ void durationChanged(qint64 duration);
+ void setPosition(int position);
+ void rotateVideo(int angle);
+
+private:
+ QMediaPlayer mediaPlayer;
+ VideoItem *videoItem;
+ QAbstractButton *playButton;
+ QSlider *positionSlider;
+};
+
+#endif
+
diff --git a/examples/videowidget/main.cpp b/examples/videowidget/main.cpp
new file mode 100644
index 000000000..7165108f0
--- /dev/null
+++ b/examples/videowidget/main.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "videoplayer.h"
+
+#include <QtGui/QApplication>
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ VideoPlayer player;
+ player.show();
+
+ return app.exec();
+}
diff --git a/examples/videowidget/videoplayer.cpp b/examples/videowidget/videoplayer.cpp
new file mode 100644
index 000000000..9276c9b25
--- /dev/null
+++ b/examples/videowidget/videoplayer.cpp
@@ -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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "videoplayer.h"
+
+#include "videowidget.h"
+
+#include <QtGui>
+#include <qvideosurfaceformat.h>
+
+VideoPlayer::VideoPlayer(QWidget *parent)
+ : QWidget(parent)
+ , mediaPlayer(0, QMediaPlayer::VideoSurface)
+ , playButton(0)
+ , positionSlider(0)
+{
+ VideoWidget *videoWidget = new VideoWidget;
+
+ QAbstractButton *openButton = new QPushButton(tr("Open..."));
+ connect(openButton, SIGNAL(clicked()), this, SLOT(openFile()));
+
+ playButton = new QPushButton;
+ playButton->setEnabled(false);
+ playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
+
+ connect(playButton, SIGNAL(clicked()),
+ this, SLOT(play()));
+
+ positionSlider = new QSlider(Qt::Horizontal);
+ positionSlider->setRange(0, 0);
+
+ connect(positionSlider, SIGNAL(sliderMoved(int)),
+ this, SLOT(setPosition(int)));
+
+ QBoxLayout *controlLayout = new QHBoxLayout;
+ controlLayout->setMargin(0);
+ controlLayout->addWidget(openButton);
+ controlLayout->addWidget(playButton);
+ controlLayout->addWidget(positionSlider);
+
+ QBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(videoWidget);
+ layout->addLayout(controlLayout);
+
+ setLayout(layout);
+
+ mediaPlayer.setVideoOutput(videoWidget->videoSurface());
+ connect(&mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)),
+ this, SLOT(mediaStateChanged(QMediaPlayer::State)));
+ connect(&mediaPlayer, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64)));
+ connect(&mediaPlayer, SIGNAL(durationChanged(qint64)), this, SLOT(durationChanged(qint64)));
+}
+
+VideoPlayer::~VideoPlayer()
+{
+}
+
+void VideoPlayer::openFile()
+{
+ QString fileName = QFileDialog::getOpenFileName(this, tr("Open Movie"),QDir::homePath());
+
+ if (!fileName.isEmpty()) {
+ mediaPlayer.setMedia(QUrl::fromLocalFile(fileName));
+
+ playButton->setEnabled(true);
+ }
+}
+
+void VideoPlayer::play()
+{
+ switch(mediaPlayer.state()) {
+ case QMediaPlayer::PlayingState:
+ mediaPlayer.pause();
+ break;
+ default:
+ mediaPlayer.play();
+ break;
+ }
+}
+
+void VideoPlayer::mediaStateChanged(QMediaPlayer::State state)
+{
+ switch(state) {
+ case QMediaPlayer::PlayingState:
+ playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
+ break;
+ default:
+ playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
+ break;
+ }
+}
+
+void VideoPlayer::positionChanged(qint64 position)
+{
+ positionSlider->setValue(position);
+}
+
+void VideoPlayer::durationChanged(qint64 duration)
+{
+ positionSlider->setRange(0, duration);
+}
+
+void VideoPlayer::setPosition(int position)
+{
+ mediaPlayer.setPosition(position);
+}
diff --git a/examples/videowidget/videoplayer.h b/examples/videowidget/videoplayer.h
new file mode 100644
index 000000000..79334a373
--- /dev/null
+++ b/examples/videowidget/videoplayer.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIDEOPLAYER_H
+#define VIDEOPLAYER_H
+
+#include <qmediaplayer.h>
+
+#include <QtGui/QMovie>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+class QAbstractButton;
+class QSlider;
+QT_END_NAMESPACE
+
+class VideoPlayer : public QWidget
+{
+ Q_OBJECT
+public:
+ VideoPlayer(QWidget *parent = 0);
+ ~VideoPlayer();
+
+public slots:
+ void openFile();
+ void play();
+
+private slots:
+ void mediaStateChanged(QMediaPlayer::State state);
+ void positionChanged(qint64 position);
+ void durationChanged(qint64 duration);
+ void setPosition(int position);
+
+private:
+ QMediaPlayer mediaPlayer;
+ QAbstractButton *playButton;
+ QSlider *positionSlider;
+};
+
+#endif
diff --git a/examples/videowidget/videowidget.cpp b/examples/videowidget/videowidget.cpp
new file mode 100644
index 000000000..925b27d9b
--- /dev/null
+++ b/examples/videowidget/videowidget.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "videowidget.h"
+
+#include "videowidgetsurface.h"
+
+#include <QtGui>
+#include <qvideosurfaceformat.h>
+
+//! [0]
+VideoWidget::VideoWidget(QWidget *parent)
+ : QWidget(parent)
+ , surface(0)
+{
+ setAutoFillBackground(false);
+ setAttribute(Qt::WA_NoSystemBackground, true);
+ setAttribute(Qt::WA_PaintOnScreen, true);
+
+ QPalette palette = this->palette();
+ palette.setColor(QPalette::Background, Qt::black);
+ setPalette(palette);
+
+ setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+
+ surface = new VideoWidgetSurface(this);
+}
+//! [0]
+
+//! [1]
+VideoWidget::~VideoWidget()
+{
+ delete surface;
+}
+//! [1]
+
+//! [2]
+QSize VideoWidget::sizeHint() const
+{
+ return surface->surfaceFormat().sizeHint();
+}
+//! [2]
+
+
+//! [3]
+void VideoWidget::paintEvent(QPaintEvent *event)
+{
+ QPainter painter(this);
+
+ if (surface->isActive()) {
+ const QRect videoRect = surface->videoRect();
+
+ if (!videoRect.contains(event->rect())) {
+ QRegion region = event->region();
+ region.subtract(videoRect);
+
+ QBrush brush = palette().background();
+
+ foreach (const QRect &rect, region.rects())
+ painter.fillRect(rect, brush);
+ }
+
+ surface->paint(&painter);
+ } else {
+ painter.fillRect(event->rect(), palette().background());
+ }
+}
+//! [3]
+
+//! [4]
+void VideoWidget::resizeEvent(QResizeEvent *event)
+{
+ QWidget::resizeEvent(event);
+
+ surface->updateVideoRect();
+}
+//! [4]
diff --git a/examples/videowidget/videowidget.h b/examples/videowidget/videowidget.h
new file mode 100644
index 000000000..3e888cfe3
--- /dev/null
+++ b/examples/videowidget/videowidget.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIDEOWIDGET_H
+#define VIDEOWIDGET_H
+
+#include "videowidgetsurface.h"
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+class QAbstractVideoSurface;
+QT_END_NAMESPACE
+
+class VideoWidgetSurface;
+
+//! [0]
+class VideoWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ VideoWidget(QWidget *parent = 0);
+ ~VideoWidget();
+
+ QAbstractVideoSurface *videoSurface() const { return surface; }
+
+ QSize sizeHint() const;
+
+protected:
+ void paintEvent(QPaintEvent *event);
+ void resizeEvent(QResizeEvent *event);
+
+private:
+ VideoWidgetSurface *surface;
+};
+//! [0]
+
+#endif
diff --git a/examples/videowidget/videowidget.pro b/examples/videowidget/videowidget.pro
new file mode 100644
index 000000000..1ef79fcaa
--- /dev/null
+++ b/examples/videowidget/videowidget.pro
@@ -0,0 +1,22 @@
+TEMPLATE = app
+CONFIG += example
+
+INCLUDEPATH += ../../src/multimedia ../../src/multimedia/video
+include(../mobility_examples.pri)
+
+CONFIG += mobility
+MOBILITY = multimedia
+
+QMAKE_RPATHDIR += $$DESTDIR
+
+HEADERS = \
+ videoplayer.h \
+ videowidget.h \
+ videowidgetsurface.h
+
+SOURCES = \
+ main.cpp \
+ videoplayer.cpp \
+ videowidget.cpp \
+ videowidgetsurface.cpp
+
diff --git a/examples/videowidget/videowidgetsurface.cpp b/examples/videowidget/videowidgetsurface.cpp
new file mode 100644
index 000000000..5819f2b25
--- /dev/null
+++ b/examples/videowidget/videowidgetsurface.cpp
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "videowidgetsurface.h"
+
+#include <QtGui>
+#include <qabstractvideosurface.h>
+#include <qvideosurfaceformat.h>
+
+VideoWidgetSurface::VideoWidgetSurface(QWidget *widget, QObject *parent)
+ : QAbstractVideoSurface(parent)
+ , widget(widget)
+ , imageFormat(QImage::Format_Invalid)
+{
+}
+
+//! [0]
+QList<QVideoFrame::PixelFormat> VideoWidgetSurface::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ if (handleType == QAbstractVideoBuffer::NoHandle) {
+ return QList<QVideoFrame::PixelFormat>()
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_ARGB32
+ << QVideoFrame::Format_ARGB32_Premultiplied
+ << QVideoFrame::Format_RGB565
+ << QVideoFrame::Format_RGB555;
+ } else {
+ return QList<QVideoFrame::PixelFormat>();
+ }
+}
+//! [0]
+
+//! [1]
+bool VideoWidgetSurface::isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const
+{
+ Q_UNUSED(similar);
+
+ const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
+ const QSize size = format.frameSize();
+
+ return imageFormat != QImage::Format_Invalid
+ && !size.isEmpty()
+ && format.handleType() == QAbstractVideoBuffer::NoHandle;
+}
+//! [1]
+
+//! [2]
+bool VideoWidgetSurface::start(const QVideoSurfaceFormat &format)
+{
+ const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
+ const QSize size = format.frameSize();
+
+ if (imageFormat != QImage::Format_Invalid && !size.isEmpty()) {
+ this->imageFormat = imageFormat;
+ imageSize = size;
+ sourceRect = format.viewport();
+
+ QAbstractVideoSurface::start(format);
+
+ widget->updateGeometry();
+ updateVideoRect();
+
+ return true;
+ } else {
+ return false;
+ }
+}
+//! [2]
+
+//! [3]
+void VideoWidgetSurface::stop()
+{
+ currentFrame = QVideoFrame();
+ targetRect = QRect();
+
+ QAbstractVideoSurface::stop();
+
+ widget->update();
+}
+//! [3]
+
+//! [4]
+bool VideoWidgetSurface::present(const QVideoFrame &frame)
+{
+ if (surfaceFormat().pixelFormat() != frame.pixelFormat()
+ || surfaceFormat().frameSize() != frame.size()) {
+ setError(IncorrectFormatError);
+ stop();
+
+ return false;
+ } else {
+ currentFrame = frame;
+
+ widget->repaint(targetRect);
+
+ return true;
+ }
+}
+//! [4]
+
+//! [5]
+void VideoWidgetSurface::updateVideoRect()
+{
+ QSize size = surfaceFormat().sizeHint();
+ size.scale(widget->size().boundedTo(size), Qt::KeepAspectRatio);
+
+ targetRect = QRect(QPoint(0, 0), size);
+ targetRect.moveCenter(widget->rect().center());
+}
+//! [5]
+
+//! [6]
+void VideoWidgetSurface::paint(QPainter *painter)
+{
+ if (currentFrame.map(QAbstractVideoBuffer::ReadOnly)) {
+ const QTransform oldTransform = painter->transform();
+
+ if (surfaceFormat().scanLineDirection() == QVideoSurfaceFormat::BottomToTop) {
+ painter->scale(1, -1);
+ painter->translate(0, -widget->height());
+ }
+
+ QImage image(
+ currentFrame.bits(),
+ currentFrame.width(),
+ currentFrame.height(),
+ currentFrame.bytesPerLine(),
+ imageFormat);
+
+ painter->drawImage(targetRect, image, sourceRect);
+
+ painter->setTransform(oldTransform);
+
+ currentFrame.unmap();
+ }
+}
+//! [6]
diff --git a/examples/videowidget/videowidgetsurface.h b/examples/videowidget/videowidgetsurface.h
new file mode 100644
index 000000000..fa3bfce23
--- /dev/null
+++ b/examples/videowidget/videowidgetsurface.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIDEOWIDGETSURFACE_H
+#define VIDEOWIDGETSURFACE_H
+
+#include <QtCore/QRect>
+#include <QtGui/QImage>
+#include <qabstractvideosurface.h>
+#include <qvideoframe.h>
+
+//! [0]
+class VideoWidgetSurface : public QAbstractVideoSurface
+{
+ Q_OBJECT
+public:
+ VideoWidgetSurface(QWidget *widget, QObject *parent = 0);
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
+ bool isFormatSupported(const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const;
+
+ bool start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ bool present(const QVideoFrame &frame);
+
+ QRect videoRect() const { return targetRect; }
+ void updateVideoRect();
+
+ void paint(QPainter *painter);
+
+private:
+ QWidget *widget;
+ QImage::Format imageFormat;
+ QRect targetRect;
+ QSize imageSize;
+ QRect sourceRect;
+ QVideoFrame currentFrame;
+};
+//! [0]
+
+#endif
diff --git a/features/basic_examples_setup.pri b/features/basic_examples_setup.pri
new file mode 100644
index 000000000..8915a03f5
--- /dev/null
+++ b/features/basic_examples_setup.pri
@@ -0,0 +1,59 @@
+symbian: {
+ vendorinfo = \
+ "; Localised Vendor name" \
+ "%{\"Nokia, Qt\"}" \
+ " " \
+ "; Unique Vendor name" \
+ ":\"Nokia, Qt\"" \
+ " "
+ examples_deployment.pkg_prerules += vendorinfo
+ DEPLOYMENT += examples_deployment
+}
+
+win32:contains(CONFIG_WIN32,build_all):Win32DebugAndRelease=yes
+mac | contains(Win32DebugAndRelease,yes) {
+ #due to different debug/release library names we have to comply with
+ #whatever Qt does
+ !contains(QT_CONFIG,debug)|!contains(QT_CONFIG,release) {
+ CONFIG -= debug_and_release debug release
+ contains(QT_CONFIG,debug): CONFIG+=debug
+ contains(QT_CONFIG,release): CONFIG+=release
+ }
+}
+
+CONFIG(debug, debug|release) {
+ SUBDIRPART=Debug
+} else {
+ SUBDIRPART=Release
+}
+
+OUTPUT_DIR = $$QT_MOBILITY_BUILD_TREE
+MOC_DIR = $$OUTPUT_DIR/build/$$SUBDIRPART/$$TARGET/moc
+RCC_DIR = $$OUTPUT_DIR/build/$$SUBDIRPART/$$TARGET/rcc
+UI_DIR = $$OUTPUT_DIR/build/$$SUBDIRPART/$$TARGET/ui
+OBJECTS_DIR = $$OUTPUT_DIR/build/$$SUBDIRPART/$$TARGET
+
+# See common.pri for comments on why using QMAKE_FRAMEWORKPATH/QMAKE_LIBDIR
+# rather than LIBS here.
+mac:contains(QT_CONFIG,qt_framework) {
+ QMAKE_FRAMEWORKPATH = $$OUTPUT_DIR/lib
+}
+QMAKE_LIBDIR = $$OUTPUT_DIR/lib
+
+QMAKE_RPATHDIR+=$$QT_MOBILITY_LIB
+INCLUDEPATH+= $$QT_MOBILITY_SOURCE_TREE/src/global
+
+maemo6 {
+ DEFINES+= Q_WS_MAEMO_6
+ DEFINES+= QTM_EXAMPLES_SMALL_SCREEN
+ DEFINES+= QTM_EXAMPLES_PREFER_LANDSCAPE
+}
+maemo5 {
+ error(Maemo5/Freemantle not supported by QtMobility 1.2+ \(Not building any examples and demos\).)
+ DEFINES+= Q_WS_MAEMO_5
+ DEFINES+= QTM_EXAMPLES_SMALL_SCREEN
+ DEFINES+= QTM_EXAMPLES_PREFER_LANDSCAPE
+}
+symbian {
+ DEFINES+= QTM_EXAMPLES_SMALL_SCREEN
+}
diff --git a/features/deploy.pri b/features/deploy.pri
new file mode 100644
index 000000000..0f712409a
--- /dev/null
+++ b/features/deploy.pri
@@ -0,0 +1,61 @@
+headers.files = $$PUBLIC_HEADERS
+headers.path = $$QT_MOBILITY_INCLUDE/$$TARGET
+
+contains(TEMPLATE,.*lib) {
+ target.path=$$QT_MOBILITY_LIB
+
+ maemo5|maemo6|meego {
+ CONFIG += create_pc create_prl
+ QMAKE_PKGCONFIG_NAME = lib$$TARGET
+ QMAKE_PKGCONFIG_DESTDIR = pkgconfig
+ QMAKE_PKGCONFIG_LIBDIR = $$target.path
+ QMAKE_PKGCONFIG_INCDIR = $$headers.path
+ QMAKE_PKGCONFIG_CFLAGS = -I$${QT_MOBILITY_INCLUDE}/QtMobility
+
+ pkgconfig.files = $${TARGET}.pc
+ pkgconfig.path = $$QT_MOBILITY_LIB/pkgconfig
+ INSTALLS += pkgconfig
+ }
+
+ TARGET = $$qtLibraryTarget($${TARGET}$${QT_LIBINFIX})
+
+ symbian {
+ middleware { path=$$MW_LAYER_PUBLIC_EXPORT_PATH("") }
+ app { path=$$APP_LAYER_PUBLIC_EXPORT_PATH("") }
+
+ exportPath=$$EPOCROOT"."$$dirname(path)
+ nativePath=$$replace(exportPath,/,\\)
+ exists($$nativePath) {
+ } else {
+ system($$QMAKE_MKDIR $$nativePath)
+ }
+
+ for(header, headers.files) {
+ middleware { BLD_INF_RULES.prj_exports += "$$header $$MW_LAYER_PUBLIC_EXPORT_PATH($$basename(header))"}
+ app { BLD_INF_RULES.prj_exports += "$$header $$APP_LAYER_PUBLIC_EXPORT_PATH($$basename(header))"}
+ }
+
+ }
+
+} else {
+ contains(TEMPLATE,.*app):target.path=$$QT_MOBILITY_BIN
+}
+
+INSTALLS+=target headers
+
+mac:contains(QT_CONFIG,qt_framework) {
+ CONFIG += lib_bundle absolute_library_soname
+
+ CONFIG(debug, debug|release) {
+ !build_pass:CONFIG += build_all
+ } else { #release
+ !debug_and_release|build_pass {
+ FRAMEWORK_HEADERS.version = Versions
+ FRAMEWORK_HEADERS.files = $${PUBLIC_HEADERS}
+ FRAMEWORK_HEADERS.path = Headers
+ }
+ QMAKE_BUNDLE_DATA += FRAMEWORK_HEADERS
+ }
+}
+
+CONFIG+= create_prl
diff --git a/features/mobility.prf.template b/features/mobility.prf.template
new file mode 100644
index 000000000..47ebecd75
--- /dev/null
+++ b/features/mobility.prf.template
@@ -0,0 +1,130 @@
+!isEmpty(QT_MOBILITY_BUILD_TREE):CONFIG+=mobility_build
+
+defineTest(qtMobilityAddLibrary) {
+ # If we are currently building Mobility itself, do not add the install
+ # include paths. It can't help since we haven't installed our headers yet,
+ # and it may hurt since incompatible headers may be present from an
+ # earlier build.
+ !mobility_build:!isEmpty(MOBILITY_INCLUDE) {
+ INCLUDEPATH -= $${MOBILITY_INCLUDE}/$$1
+ INCLUDEPATH = $${MOBILITY_INCLUDE}/$$1 $$INCLUDEPATH
+ }
+
+ # qtAddLibrary will add $$QMAKE_INCDIR_QT/$$1 to the INCLUDEPATH, which we
+ # don't want, but we want everything else it does.
+ OLD_INCLUDEPATH = $$INCLUDEPATH
+ qtAddLibrary($$1)
+ INCLUDEPATH = $$OLD_INCLUDEPATH
+
+ export(INCLUDEPATH)
+}
+
+!symbian {
+ !mobility_build:INCLUDEPATH += $${MOBILITY_INCLUDE}
+} else {
+ load(data_caging_paths)
+ contains(MOBILITY, contacts|versit|organizer) {
+ INCLUDEPATH+=$$APP_LAYER_SYSTEMINCLUDE
+ }
+
+ INCLUDEPATH+=$$MW_LAYER_SYSTEMINCLUDE
+}
+
+!mobility_build {
+ mac: LIBS += -F$${MOBILITY_LIB}
+
+ LIBS+= -L$${MOBILITY_LIB}
+}
+
+QMAKE_RPATHDIR+=$${MOBILITY_LIB}
+
+# versit depends on contacts
+contains(MOBILITY, versit) {
+ MOBILITY += contacts
+}
+
+
+simulator: qtMobilityAddLibrary(QtMobilitySimulator)
+
+contains(MOBILITY, bearer) {
+ DEFINES += QT_MOBILITY_BEARER
+ qtMobilityAddLibrary(QtBearer)
+ !equals(QT_MAJOR_VERSION,4)|!equals(QT_MINOR_VERSION, 6) {
+ message(Qt Mobility Bearer API is deprecated when using Qt 4.7 or higher.)
+ message(Please use source compatible replacement Bearer API in QtNetwork.)
+ }
+}
+
+#for includes from src/global
+!mobility_build:!isEmpty(MOBILITY_INCLUDE):INCLUDEPATH += $${MOBILITY_INCLUDE}/QtMobility
+
+contains(MOBILITY, publishsubscribe) {
+ qtMobilityAddLibrary(QtPublishSubscribe)
+}
+
+contains(MOBILITY, location) {
+ qtMobilityAddLibrary(QtLocation)
+}
+
+contains(MOBILITY, serviceframework) {
+ qtMobilityAddLibrary(QtServiceFramework)
+}
+
+contains(MOBILITY, systeminfo) {
+ #QSystemInfo header requires QNetworkInterface
+ QT += network
+ qtMobilityAddLibrary(QtSystemInfo)
+}
+
+contains(MOBILITY, multimedia) {
+ QT += network
+ contains(QT_CONFIG, opengl): QT += opengl
+ qtMobilityAddLibrary(QtMultimediaKit)
+}
+
+contains(MOBILITY, contacts) {
+ qtMobilityAddLibrary(QtContacts)
+}
+
+contains(MOBILITY, messaging) {
+ qtMobilityAddLibrary(QtMessaging)
+}
+
+contains(MOBILITY, versit) {
+ qtMobilityAddLibrary(QtVersit)
+ contains(MOBILITY, organizer) {
+ qtMobilityAddLibrary(QtVersitOrganizer)
+ }
+}
+
+contains(MOBILITY, sensors) {
+ qtMobilityAddLibrary(QtSensors)
+}
+
+contains(MOBILITY, feedback) {
+ qtMobilityAddLibrary(QtFeedback)
+}
+
+contains(MOBILITY, gallery) {
+ qtMobilityAddLibrary(QtGallery)
+}
+
+contains(MOBILITY, organizer) {
+ qtMobilityAddLibrary(QtOrganizer)
+}
+
+contains(MOBILITY, connectivity) {
+ INCLUDEPATH += $${QMAKE_INCDIR_QT}/QtNetwork
+ qtMobilityAddLibrary(QtConnectivity)
+}
+
+# Add dependency to QtMobility package to all projects besides QtMobility package itself.
+# Mobility libs have UID3 0x2002AC89
+# self-signed Mobility libs have UID3 0xE002AC89
+symbian:contains(CONFIG, mobility)::contains(default_deployment.pkg_prerules, pkg_depends_qt):!contains(TARGET.UID3, 0x2002AC89):!contains(TARGET.UID3, 0xE002AC89) {
+ mobility_pkg_name = QtMobility
+ mobility_default_deployment.pkg_prerules += \
+ "; Default dependency to QtMobility libraries" \
+ "(0x2002AC89), 1, 2, 0, {$$addLanguageDependentPkgItem(mobility_pkg_name)}"
+ DEPLOYMENT += mobility_default_deployment
+}
diff --git a/modules/qt_multimediakit.pri b/modules/qt_multimediakit.pri
new file mode 100644
index 000000000..bbcf685c4
--- /dev/null
+++ b/modules/qt_multimediakit.pri
@@ -0,0 +1,17 @@
+QT.multimediakit.VERSION = 5.0.0
+QT.multimediakit.MAJOR_VERSION = 5
+QT.multimediakit.MINOR_VERSION = 0
+QT.multimediakit.PATCH_VERSION = 0
+
+QT.multimediakit.name = QtMultimediaKit
+QT.multimediakit.bins = $$QT_MODULE_BIN_BASE
+QT.multimediakit.includes = $$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/QtMultimediaKit
+QT.multimediakit.private_includes = $$QT_MODULE_INCLUDE_BASE/QtMultimediaKit/$$QT.multimediakit.VERSION
+QT.multimediakit.sources = $$QT_MODULE_BASE/src/multimediakit
+QT.multimediakit.libs = $$QT_MODULE_LIB_BASE
+QT.multimediakit.plugins = $$QT_MODULE_PLUGIN_BASE
+QT.multimediakit.imports = $$QT_MODULE_IMPORT_BASE
+QT.multimediakit.depends = gui network
+QT.multimediakit.DEFINES = QT_MULTIMEDIAKIT_LIB
+
+DEFINES += multimediakit
diff --git a/qtmultimediakit.pro b/qtmultimediakit.pro
new file mode 100644
index 000000000..bf60839f4
--- /dev/null
+++ b/qtmultimediakit.pro
@@ -0,0 +1,29 @@
+TEMPLATE = subdirs
+
+module_qtmultimediakit_src.subdir = src
+module_qtmultimediakit_src.target = module-qtmultimediakit-src
+
+module_qtmultimediakit_demos.subdir = demos
+module_qtmultimediakit_demos.target = module-qtmultimediakit-demos
+module_qtmultimediakit_demos.depends = module_qtmultimediakit_src
+!contains(QT_BUILD_PARTS,demos) {
+ module_qtmultimediakit_demos.CONFIG = no_default_target no_default_install
+}
+
+module_qtmultimediakit_examples.subdir = examples/multimediakit
+module_qtmultimediakit_examples.target = module-qtmultimediakit-examples
+module_qtmultimediakit_examples.depends = module_qtmultimediakit_src
+!contains(QT_BUILD_PARTS,examples) {
+ module_qtmultimediakit_examples.CONFIG = no_default_target no_default_install
+}
+
+module_qtmultimediakit_tests.subdir = tests
+module_qtmultimediakit_tests.target = module-qtmultimediakit-tests
+module_qtmultimediakit_tests.depends = module_qtmultimediakit_src
+module_qtmultimediakit_tests.CONFIG = no_default_target no_default_install
+
+SUBDIRS += module_qtmultimediakit_src \
+ module_qtmultimediakit_demos \
+ module_qtmultimediakit_examples \
+ module_qtmultimediakit_tests \
+
diff --git a/src/harmattaninstalls/README b/src/harmattaninstalls/README
new file mode 100644
index 000000000..2712122ae
--- /dev/null
+++ b/src/harmattaninstalls/README
@@ -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
+
diff --git a/src/harmattaninstalls/api b/src/harmattaninstalls/api
new file mode 100644
index 000000000..adf69eedc
--- /dev/null
+++ b/src/harmattaninstalls/api
@@ -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
+
diff --git a/src/harmattaninstalls/changelog b/src/harmattaninstalls/changelog
new file mode 100644
index 000000000..b88e2e473
--- /dev/null
+++ b/src/harmattaninstalls/changelog
@@ -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
+
diff --git a/src/harmattaninstalls/compat b/src/harmattaninstalls/compat
new file mode 100644
index 000000000..7ed6ff82d
--- /dev/null
+++ b/src/harmattaninstalls/compat
@@ -0,0 +1 @@
+5
diff --git a/src/harmattaninstalls/control b/src/harmattaninstalls/control
new file mode 100644
index 000000000..8cb347d44
--- /dev/null
+++ b/src/harmattaninstalls/control
@@ -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.
diff --git a/src/harmattaninstalls/docs b/src/harmattaninstalls/docs
new file mode 100644
index 000000000..11bffb5ba
--- /dev/null
+++ b/src/harmattaninstalls/docs
@@ -0,0 +1,2 @@
+INSTALL.txt
+LGPL_EXCEPTION.txt
diff --git a/src/harmattaninstalls/libqtm-contacts-tests.aegis b/src/harmattaninstalls/libqtm-contacts-tests.aegis
new file mode 100644
index 000000000..4f5fc8dca
--- /dev/null
+++ b/src/harmattaninstalls/libqtm-contacts-tests.aegis
@@ -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>
diff --git a/src/harmattaninstalls/libqtm-doc.install b/src/harmattaninstalls/libqtm-doc.install
new file mode 100644
index 000000000..a1c81d47c
--- /dev/null
+++ b/src/harmattaninstalls/libqtm-doc.install
@@ -0,0 +1 @@
+usr/doc/html/* usr/share/qt4/QtMobility/doc/html
diff --git a/src/harmattaninstalls/libqtm-examples.aegis b/src/harmattaninstalls/libqtm-examples.aegis
new file mode 100644
index 000000000..21e8207d5
--- /dev/null
+++ b/src/harmattaninstalls/libqtm-examples.aegis
@@ -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>
diff --git a/src/harmattaninstalls/libqtm-examples.install b/src/harmattaninstalls/libqtm-examples.install
new file mode 100644
index 000000000..dc9ddb19d
--- /dev/null
+++ b/src/harmattaninstalls/libqtm-examples.install
@@ -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
diff --git a/src/harmattaninstalls/libqtm-multimedia-dev.install b/src/harmattaninstalls/libqtm-multimedia-dev.install
new file mode 100644
index 000000000..ec82185b5
--- /dev/null
+++ b/src/harmattaninstalls/libqtm-multimedia-dev.install
@@ -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
diff --git a/src/harmattaninstalls/libqtm-multimedia-tests.install b/src/harmattaninstalls/libqtm-multimedia-tests.install
new file mode 100644
index 000000000..966d6e7db
--- /dev/null
+++ b/src/harmattaninstalls/libqtm-multimedia-tests.install
@@ -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
diff --git a/src/harmattaninstalls/libqtm-multimedia.install b/src/harmattaninstalls/libqtm-multimedia.install
new file mode 100644
index 000000000..b8a1fb7c6
--- /dev/null
+++ b/src/harmattaninstalls/libqtm-multimedia.install
@@ -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
diff --git a/src/harmattaninstalls/libqtm-systeminfo-tests.aegis b/src/harmattaninstalls/libqtm-systeminfo-tests.aegis
new file mode 100644
index 000000000..599c7818b
--- /dev/null
+++ b/src/harmattaninstalls/libqtm-systeminfo-tests.aegis
@@ -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>
diff --git a/src/harmattaninstalls/patches/series b/src/harmattaninstalls/patches/series
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/harmattaninstalls/patches/series
diff --git a/src/harmattaninstalls/rules b/src/harmattaninstalls/rules
new file mode 100755
index 000000000..75c2f13fe
--- /dev/null
+++ b/src/harmattaninstalls/rules
@@ -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
+
diff --git a/src/harmattaninstalls/tests/install_tests b/src/harmattaninstalls/tests/install_tests
new file mode 100755
index 000000000..05fbc232b
--- /dev/null
+++ b/src/harmattaninstalls/tests/install_tests
@@ -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
diff --git a/src/harmattaninstalls/tests/testset.txt b/src/harmattaninstalls/tests/testset.txt
new file mode 100644
index 000000000..e741a4d25
--- /dev/null
+++ b/src/harmattaninstalls/tests/testset.txt
@@ -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>
diff --git a/src/harmattaninstalls/tests/testsuite_footer.txt b/src/harmattaninstalls/tests/testsuite_footer.txt
new file mode 100644
index 000000000..8c71c93a4
--- /dev/null
+++ b/src/harmattaninstalls/tests/testsuite_footer.txt
@@ -0,0 +1,2 @@
+ </suite>
+</testdefinition>
diff --git a/src/harmattaninstalls/tests/testsuite_header.txt b/src/harmattaninstalls/tests/testsuite_header.txt
new file mode 100644
index 000000000..4c57f766d
--- /dev/null
+++ b/src/harmattaninstalls/tests/testsuite_header.txt
@@ -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 />
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
new file mode 100644
index 000000000..669064baa
--- /dev/null
+++ b/src/imports/imports.pro
@@ -0,0 +1,5 @@
+
+TEMPLATE = subdirs
+
+SUBDIRS += multimedia
+
diff --git a/src/imports/multimedia/multimedia.cpp b/src/imports/multimedia/multimedia.cpp
new file mode 100644
index 000000000..59137390b
--- /dev/null
+++ b/src/imports/multimedia/multimedia.cpp
@@ -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));
+
diff --git a/src/imports/multimedia/multimedia.pro b/src/imports/multimedia/multimedia.pro
new file mode 100644
index 000000000..c3874d3ba
--- /dev/null
+++ b/src/imports/multimedia/multimedia.pro
@@ -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
+}
diff --git a/src/imports/multimedia/qdeclarativeaudio.cpp b/src/imports/multimedia/qdeclarativeaudio.cpp
new file mode 100644
index 000000000..6ba8b39de
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativeaudio.cpp
@@ -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"
+
+
diff --git a/src/imports/multimedia/qdeclarativeaudio_p.h b/src/imports/multimedia/qdeclarativeaudio_p.h
new file mode 100644
index 000000000..6b7c64453
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativeaudio_p.h
@@ -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
diff --git a/src/imports/multimedia/qdeclarativecamera.cpp b/src/imports/multimedia/qdeclarativecamera.cpp
new file mode 100644
index 000000000..08562dd76
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativecamera.cpp
@@ -0,0 +1,1342 @@
+/****************************************************************************
+**
+** 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 "qdeclarativecamera_p.h"
+#include "qdeclarativecamerapreviewprovider_p.h"
+
+#include <qmediaplayercontrol.h>
+#include <qmediaservice.h>
+#include <private/qpaintervideosurface_p.h>
+#include <qvideorenderercontrol.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+#include <QtCore/QTimer>
+#include <QtGui/qevent.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class FocusZoneItem : public QGraphicsItem {
+public:
+ FocusZoneItem(const QCameraFocusZone & zone, const QColor &color, QGraphicsItem *parent = 0)
+ :QGraphicsItem(parent),m_zone(zone), m_color(color)
+ {}
+
+ virtual ~FocusZoneItem() {}
+ void paint(QPainter *painter,
+ const QStyleOptionGraphicsItem *option,
+ QWidget *widget = 0)
+ {
+ Q_UNUSED(widget);
+ Q_UNUSED(option);
+
+ painter->setPen(QPen(QBrush(m_color), 2.5));
+ QRectF r = boundingRect();
+ QPointF dw(r.width()/10, 0);
+ QPointF dh(0, r.width()/10);
+
+ painter->drawLine(r.topLeft(), r.topLeft()+dw);
+ painter->drawLine(r.topLeft(), r.topLeft()+dh);
+
+ painter->drawLine(r.topRight(), r.topRight()-dw);
+ painter->drawLine(r.topRight(), r.topRight()+dh);
+
+ painter->drawLine(r.bottomLeft(), r.bottomLeft()+dw);
+ painter->drawLine(r.bottomLeft(), r.bottomLeft()-dh);
+
+ painter->drawLine(r.bottomRight(), r.bottomRight()-dw);
+ painter->drawLine(r.bottomRight(), r.bottomRight()-dh);
+ }
+
+ QRectF boundingRect() const {
+ if (!parentItem())
+ return QRectF();
+
+ QRectF p = parentItem()->boundingRect();
+ QRectF zone = m_zone.area();
+
+ return QRectF(p.left() + zone.left()*p.width(),
+ p.top() + zone.top()*p.height(),
+ p.width()*zone.width(),
+ p.height()*zone.height());
+ }
+
+
+ QCameraFocusZone m_zone;
+ QColor m_color;
+};
+
+
+void QDeclarativeCamera::_q_nativeSizeChanged(const QSizeF &size)
+{
+ setImplicitWidth(size.width());
+ setImplicitHeight(size.height());
+}
+
+void QDeclarativeCamera::_q_error(int errorCode, const QString &errorString)
+{
+ emit error(Error(errorCode), errorString);
+ emit errorChanged();
+}
+
+void QDeclarativeCamera::_q_imageCaptured(int id, const QImage &preview)
+{
+ m_capturedImagePreview = preview;
+ QString previewId = QString("preview_%1").arg(id);
+ QDeclarativeCameraPreviewProvider::registerPreview(previewId, preview);
+
+ emit imageCaptured(QLatin1String("image://camera/")+previewId);
+}
+
+void QDeclarativeCamera::_q_imageSaved(int id, const QString &fileName)
+{
+ Q_UNUSED(id);
+ m_capturedImagePath = fileName;
+ emit imageSaved(fileName);
+}
+
+void QDeclarativeCamera::_q_updateState(QCamera::State state)
+{
+ emit cameraStateChanged(QDeclarativeCamera::State(state));
+}
+
+void QDeclarativeCamera::_q_updateLockStatus(QCamera::LockType type,
+ QCamera::LockStatus status,
+ QCamera::LockChangeReason reason)
+{
+ if (type == QCamera::LockFocus) {
+ if (status == QCamera::Unlocked && reason == QCamera::LockFailed) {
+ //display failed focus points in red for 1 second
+ m_focusFailedTime = QTime::currentTime();
+ QTimer::singleShot(1000, this, SLOT(_q_updateFocusZones()));
+ } else {
+ m_focusFailedTime = QTime();
+ }
+ _q_updateFocusZones();
+ }
+}
+
+void QDeclarativeCamera::_q_updateFocusZones()
+{
+ qDeleteAll(m_focusZones);
+ m_focusZones.clear();
+
+ foreach(const QCameraFocusZone &zone, m_camera->focus()->focusZones()) {
+ QColor c;
+ QCamera::LockStatus lockStatus = m_camera->lockStatus(QCamera::LockFocus);
+
+ if (lockStatus == QCamera::Unlocked) {
+ //display failed focus points in red for 1 second
+ if (zone.status() == QCameraFocusZone::Selected &&
+ m_focusFailedTime.msecsTo(QTime::currentTime()) < 500) {
+ c = Qt::red;
+ }
+ } else {
+ switch (zone.status()) {
+ case QCameraFocusZone::Focused:
+ c = Qt::green;
+ break;
+ case QCameraFocusZone::Selected:
+ c = lockStatus == QCamera::Searching ? Qt::yellow : Qt::black;
+ break;
+ default:
+ c= QColor::Invalid;
+ break;
+ }
+ }
+
+ if (c.isValid())
+ m_focusZones.append(new FocusZoneItem(zone, c, m_viewfinderItem));
+ }
+}
+
+void QDeclarativeCamera::_q_updateImageSettings()
+{
+ if (m_imageSettingsChanged) {
+ m_imageSettingsChanged = false;
+ m_capture->setEncodingSettings(m_imageSettings);
+ }
+}
+
+void QDeclarativeCamera::_q_applyPendingState()
+{
+ if (!m_isStateSet) {
+ m_isStateSet = true;
+ setCameraState(m_pendingState);
+ }
+}
+
+void QDeclarativeCamera::_q_captureFailed(int id, QCameraImageCapture::Error error, const QString &message)
+{
+ Q_UNUSED(id);
+ Q_UNUSED(error);
+ emit captureFailed(message);
+}
+
+
+/*!
+ \qmlclass Camera QDeclarativeCamera
+ \since 4.7
+ \brief The Camera element allows you to add camera viewfinder to a scene.
+ \ingroup qml-multimedia
+ \inherits Item
+
+ This element is part of the \bold{QtMultimediaKit 1.1} module.
+
+ \qml
+ import Qt 4.7
+ import QtMultimediaKit 1.1
+
+ Camera {
+ focus : visible // to receive focus and capture key events when visible
+
+ flashMode: Camera.FlashRedEyeReduction
+ whiteBalanceMode: Camera.WhiteBalanceFlash
+ exposureCompensation: -1.0
+
+ onImageCaptured : {
+ photoPreview.source = preview // Show the preview in an Image element
+ }
+
+ }
+ \endqml
+
+ You can use the \c Camera element to capture images from a camera, and manipulate the capture and
+ processing settings that get applied to the image.
+
+ \note On Symbian, your process requires the \c UserEnvironment capability to use this element.
+*/
+
+/*!
+ \class QDeclarativeCamera
+ \brief The QDeclarativeCamera class provides a camera item that you can add to a QDeclarativeView.
+*/
+
+/*!
+ Construct a declarative camera object using \a parent object.
+ */
+QDeclarativeCamera::QDeclarativeCamera(QDeclarativeItem *parent) :
+ QDeclarativeItem(parent),
+ m_camera(0),
+ m_viewfinderItem(0),
+ m_imageSettingsChanged(false),
+ m_pendingState(ActiveState),
+ m_isStateSet(false),
+ m_isValid(true)
+{
+#if defined(Q_OS_SYMBIAN)
+ RProcess thisProcess;
+ if (!thisProcess.HasCapability(ECapabilityUserEnvironment)) {
+ qmlInfo(this) << "Camera Element requires UserEnvironment Capability to be successfully used on Symbian";
+ m_isValid = false;
+ return;
+ }
+#endif
+ m_camera = new QCamera(this);
+ m_viewfinderItem = new QGraphicsVideoItem(this);
+ m_camera->setViewfinder(m_viewfinderItem);
+ m_exposure = m_camera->exposure();
+ m_focus = m_camera->focus();
+
+ connect(m_viewfinderItem, SIGNAL(nativeSizeChanged(QSizeF)),
+ this, SLOT(_q_nativeSizeChanged(QSizeF)));
+
+ connect(m_camera, SIGNAL(lockStatusChanged(QCamera::LockStatus,QCamera::LockChangeReason)), this, SIGNAL(lockStatusChanged()));
+ connect(m_camera, SIGNAL(stateChanged(QCamera::State)), this, SLOT(_q_updateState(QCamera::State)));
+
+ m_capture = new QCameraImageCapture(m_camera, this);
+
+ connect(m_capture, SIGNAL(imageCaptured(int,QImage)), this, SLOT(_q_imageCaptured(int, QImage)));
+ connect(m_capture, SIGNAL(imageSaved(int,QString)), this, SLOT(_q_imageSaved(int, QString)));
+ connect(m_capture, SIGNAL(error(int,QCameraImageCapture::Error,QString)),
+ this, SLOT(_q_captureFailed(int,QCameraImageCapture::Error,QString)));
+
+ connect(m_focus, SIGNAL(focusZonesChanged()), this, SLOT(_q_updateFocusZones()));
+ connect(m_camera, SIGNAL(lockStatusChanged(QCamera::LockType,QCamera::LockStatus,QCamera::LockChangeReason)),
+ this, SLOT(_q_updateLockStatus(QCamera::LockType,QCamera::LockStatus,QCamera::LockChangeReason)));
+
+ connect(m_exposure, SIGNAL(isoSensitivityChanged(int)), this, SIGNAL(isoSensitivityChanged(int)));
+ connect(m_exposure, SIGNAL(apertureChanged(qreal)), this, SIGNAL(apertureChanged(qreal)));
+ connect(m_exposure, SIGNAL(shutterSpeedChanged(qreal)), this, SIGNAL(shutterSpeedChanged(qreal)));
+
+ //connect(m_exposure, SIGNAL(exposureCompensationChanged(qreal)), this, SIGNAL(exposureCompensationChanged(qreal)));
+
+ connect(m_focus, SIGNAL(opticalZoomChanged(qreal)), this, SIGNAL(opticalZoomChanged(qreal)));
+ connect(m_focus, SIGNAL(digitalZoomChanged(qreal)), this, SIGNAL(digitalZoomChanged(qreal)));
+ connect(m_focus, SIGNAL(maximumOpticalZoomChanged(qreal)), this, SIGNAL(maximumOpticalZoomChanged(qreal)));
+ connect(m_focus, SIGNAL(maximumDigitalZoomChanged(qreal)), this, SIGNAL(maximumDigitalZoomChanged(qreal)));
+
+ //delayed start to evoid stopping the cammera immediately if
+ //stop() is called after constructor,
+ //or to set the rest of camera settings before starting the camera
+ QMetaObject::invokeMethod(this, "_q_applyPendingState", Qt::QueuedConnection);
+
+}
+
+/*! Destructor, clean up memory */
+QDeclarativeCamera::~QDeclarativeCamera()
+{
+ if (m_isValid) {
+ m_camera->unload();
+
+ delete m_viewfinderItem;
+ delete m_capture;
+ delete m_camera;
+ }
+}
+
+/*!
+ Returns any camera error.
+ \sa QDeclarativeError::Error
+*/
+QDeclarativeCamera::Error QDeclarativeCamera::error() const
+{
+ if (!m_isValid)
+ return QDeclarativeCamera::CameraError;
+
+ return QDeclarativeCamera::Error(m_camera->error());
+}
+
+/*!
+ \qmlproperty string Camera::errorString
+
+ A description of the current error, if any.
+*/
+/*!
+ \property QDeclarativeCamera::errorString
+
+ A description of the current error, if any.
+*/
+QString QDeclarativeCamera::errorString() const
+{
+ if (!m_isValid)
+ return QString();
+
+ return m_camera->errorString();
+}
+
+/*!
+ \qmlproperty enumeration Camera::cameraState
+
+ The current state of the camera object.
+
+ \table
+ \header \o Value \o Description
+ \row \o UnloadedState
+ \o The initial camera state, with camera not loaded,
+ the camera capabilities except of supported capture modes
+ are unknown.
+ While the supported settings are unknown in this state,
+ it's allowed to set the camera capture settings like codec,
+ resolution, or frame rate.
+
+ \row \o LoadedState
+ \o The camera is loaded and ready to be configured.
+
+ In the Idle state it's allowed to query camera capabilities,
+ set capture resolution, codecs, etc.
+
+ The viewfinder is not active in the loaded state.
+
+ \row \o ActiveState
+ \o In the active state as soon as camera is started
+ the viewfinder displays video frames and the
+ camera is ready for capture.
+ \endtable
+*/
+/*!
+ \property QDeclarativeCamera::cameraState
+
+ The current state of the camera object.
+
+ \table
+ \header \o Value \o Description
+ \row \o UnloadedState
+ \o The initial camera state, with camera not loaded,
+ the camera capabilities except of supported capture modes
+ are unknown.
+ While the supported settings are unknown in this state,
+ it's allowed to set the camera capture settings like codec,
+ resolution, or frame rate.
+
+ \row \o LoadedState
+ \o The camera is loaded and ready to be configured.
+
+ In the Idle state it's allowed to query camera capabilities,
+ set capture resolution, codecs, etc.
+
+ The viewfinder is not active in the loaded state.
+
+ \row \o ActiveState
+ \o In the active state as soon as camera is started
+ the viewfinder displays video frames and the
+ camera is ready for capture.
+ \endtable
+*/
+/*!
+ \enum QDeclarativeCamera::State
+ \value UnloadedState
+ The initial camera state, with camera not loaded,
+ the camera capabilities except of supported capture modes
+ are unknown.
+ While the supported settings are unknown in this state,
+ it's allowed to set the camera capture settings like codec,
+ resolution, or frame rate.
+
+ \value LoadedState
+ The camera is loaded and ready to be configured.
+ In the Idle state it's allowed to query camera capabilities,
+ set capture resolution, codecs, etc.
+ The viewfinder is not active in the loaded state.
+
+ \value ActiveState
+ In the active state as soon as camera is started
+ the viewfinder displays video frames and the
+ camera is ready for capture.
+
+
+ The default camera state is ActiveState.
+*/
+
+QDeclarativeCamera::State QDeclarativeCamera::cameraState() const
+{
+ if (!m_isValid)
+ return QDeclarativeCamera::UnloadedState;
+
+ return m_isStateSet ? QDeclarativeCamera::State(m_camera->state()) : m_pendingState;
+}
+
+void QDeclarativeCamera::setCameraState(QDeclarativeCamera::State state)
+{
+ if (!m_isValid)
+ return;
+
+ if (!m_isStateSet) {
+ m_pendingState = state;
+ return;
+ }
+
+ switch (state) {
+ case QDeclarativeCamera::ActiveState:
+ m_camera->start();
+ break;
+ case QDeclarativeCamera::UnloadedState:
+ m_camera->unload();
+ break;
+ case QDeclarativeCamera::LoadedState:
+ m_camera->load();
+ break;
+ }
+}
+
+/*!
+ \qmlmethod Camera::start()
+ \fn QDeclarativeCamera::start()
+
+ Starts the camera.
+*/
+void QDeclarativeCamera::start()
+{
+ if (m_isValid)
+ m_camera->start();
+}
+
+/*!
+ \qmlmethod Camera::stop()
+ \fn QDeclarativeCamera::stop()
+
+ Stops the camera.
+*/
+void QDeclarativeCamera::stop()
+{
+ if (m_isValid)
+ m_camera->stop();
+}
+
+
+/*!
+ \qmlproperty enumeration Camera::lockStatus
+
+ The overall status for all the requested camera locks.
+
+ \table
+ \header \o Value \o Description
+ \row \o Unlocked
+ \o The application is not interested in camera settings value.
+ The camera may keep this parameter without changes, this is common with camera focus,
+ or adjust exposure and white balance constantly to keep the viewfinder image nice.
+
+ \row \o Searching
+ \o The application has requested the camera focus, exposure or white balance lock with
+ searchAndLock(). This state indicates the camera is focusing or calculating exposure and white balance.
+
+ \row \o Locked
+ \o The camera focus, exposure or white balance is locked.
+ The camera is ready to capture, application may check the exposure parameters.
+
+ The locked state usually means the requested parameter stays the same,
+ except in the cases when the parameter is requested to be constantly updated.
+ For example in continuous focusing mode, the focus is considered locked as long
+ and the object is in focus, even while the actual focusing distance may be constantly changing.
+ \endtable
+*/
+/*!
+ \property QDeclarativeCamera::lockStatus
+
+ The overall status for all the requested camera locks.
+
+ \table
+ \header \o Value \o Description
+ \row \o Unlocked
+ \o The application is not interested in camera settings value.
+ The camera may keep this parameter without changes, this is common with camera focus,
+ or adjust exposure and white balance constantly to keep the viewfinder image nice.
+
+ \row \o Searching
+ \o The application has requested the camera focus, exposure or white balance lock with
+ searchAndLock(). This state indicates the camera is focusing or calculating exposure and white balance.
+
+ \row \o Locked
+ \o The camera focus, exposure or white balance is locked.
+ The camera is ready to capture, application may check the exposure parameters.
+
+ The locked state usually means the requested parameter stays the same,
+ except in the cases when the parameter is requested to be constantly updated.
+ For example in continuous focusing mode, the focus is considered locked as long
+ and the object is in focus, even while the actual focusing distance may be constantly changing.
+ \endtable
+*/
+/*!
+ \enum QDeclarativeCamera::LockStatus
+ \value Unlocked
+ The application is not interested in camera settings value.
+ The camera may keep this parameter without changes, this is common with camera focus,
+ or adjust exposure and white balance constantly to keep the viewfinder image nice.
+
+ \value Searching
+ The application has requested the camera focus, exposure or white balance lock with
+ searchAndLock(). This state indicates the camera is focusing or calculating exposure and white balance.
+
+ \value Locked
+ The camera focus, exposure or white balance is locked.
+ The camera is ready to capture, application may check the exposure parameters.
+
+ The locked state usually means the requested parameter stays the same,
+ except in the cases when the parameter is requested to be constantly updated.
+ For example in continuous focusing mode, the focus is considered locked as long
+ and the object is in focus, even while the actual focusing distance may be constantly changing.
+*/
+QDeclarativeCamera::LockStatus QDeclarativeCamera::lockStatus() const
+{
+ if (!m_isValid)
+ return QDeclarativeCamera::Unlocked;
+
+ return QDeclarativeCamera::LockStatus(m_camera->lockStatus());
+}
+
+/*!
+ \qmlmethod Camera::searchAndLock()
+ \fn QDeclarativeCamera::searchAndLock()
+
+ Start focusing, exposure and white balance calculation.
+ If the camera has keyboard focus, searchAndLock() is called
+ automatically when the camera focus button is pressed.
+*/
+void QDeclarativeCamera::searchAndLock()
+{
+ if (m_isValid)
+ m_camera->searchAndLock();
+}
+
+/*!
+ \qmlmethod Camera::unlock()
+ \fn QDeclarativeCamera::unlock()
+
+ Unlock focus.
+
+ If the camera has keyboard focus, unlock() is called automatically
+ when the camera focus button is released.
+ */
+void QDeclarativeCamera::unlock()
+{
+ if (m_isValid)
+ m_camera->unlock();
+}
+
+/*!
+ \qmlmethod Camera::captureImage()
+ \fn QDeclarativeCamera::captureImage()
+
+ Start image capture. The \l onImageCaptured() and \l onImageSaved() signals will
+ be emitted when the capture is complete.
+*/
+void QDeclarativeCamera::captureImage()
+{
+ if (m_isValid)
+ m_capture->capture();
+}
+
+// XXX this doesn't seem to be used
+/*!
+ \fn QDeclarativeCamera::capturedImagePreview() const
+*/
+QImage QDeclarativeCamera::capturedImagePreview() const
+{
+ return m_capturedImagePreview;
+}
+
+/*!
+ \qmlproperty string Camera::capturedImagePath
+
+ The path to the captured image.
+*/
+/*!
+ \property QDeclarativeCamera::capturedImagePath
+
+ The path to the captured image.
+*/
+QString QDeclarativeCamera::capturedImagePath() const
+{
+ return m_capturedImagePath;
+}
+
+/*!
+ Paint method.
+*/
+void QDeclarativeCamera::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
+{
+}
+
+/*!
+ Change viewfinder size to \a newGeometry and returning the \a oldGeometry
+*/
+void QDeclarativeCamera::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ m_viewfinderItem->setSize(newGeometry.size());
+ _q_updateFocusZones();
+
+ QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+void QDeclarativeCamera::keyPressEvent(QKeyEvent * event)
+{
+ if (!m_isValid || event->isAutoRepeat())
+ return;
+
+ switch (event->key()) {
+ case Qt::Key_CameraFocus:
+ m_camera->searchAndLock();
+ event->accept();
+ break;
+ case Qt::Key_Camera:
+ if (m_camera->captureMode() == QCamera::CaptureStillImage)
+ captureImage();
+ //else
+ // m_recorder->record();
+ event->accept();
+ break;
+ default:
+ QDeclarativeItem::keyPressEvent(event);
+ }
+}
+
+/*!
+ Handle the release of a key in \a event and take action if needed.
+*/
+void QDeclarativeCamera::keyReleaseEvent(QKeyEvent * event)
+{
+ if (!m_isValid || event->isAutoRepeat())
+ return;
+
+ switch (event->key()) {
+ case Qt::Key_CameraFocus:
+ m_camera->unlock();
+ event->accept();
+ break;
+ case Qt::Key_Camera:
+ //if (m_camera->captureMode() == QCamera::CaptureVideo)
+ // m_recorder->stop();
+ event->accept();
+ break;
+ default:
+ QDeclarativeItem::keyReleaseEvent(event);
+ }
+}
+
+
+/*!
+ \qmlproperty enumeration Camera::flashMode
+
+ \table
+ \header \o Value \o Description
+ \row \o FlashOff \o Flash is Off.
+ \row \o FlashOn \o Flash is On.
+ \row \o FlashAuto \o Automatic flash.
+ \row \o FlashRedEyeReduction \o Red eye reduction flash.
+ \row \o FlashFill \o Use flash to fillin shadows.
+ \row \o FlashTorch \o Constant light source, useful for focusing and video capture.
+ \row \o FlashSlowSyncFrontCurtain
+ \o Use the flash in conjunction with a slow shutter speed.
+ This mode allows better exposure of distant objects and/or motion blur effect.
+ \row \o FlashSlowSyncRearCurtain
+ \o The similar mode to FlashSlowSyncFrontCurtain but flash is fired at the end of exposure.
+ \row \o FlashManual \o Flash power is manually set.
+ \endtable
+
+*/
+/*!
+ \property QDeclarativeCamera::flashMode
+
+ \table
+ \header \o Value \o Description
+ \row \o FlashOff \o Flash is Off.
+ \row \o FlashOn \o Flash is On.
+ \row \o FlashAuto \o Automatic flash.
+ \row \o FlashRedEyeReduction \o Red eye reduction flash.
+ \row \o FlashFill \o Use flash to fillin shadows.
+ \row \o FlashTorch \o Constant light source, useful for focusing and video capture.
+ \row \o FlashSlowSyncFrontCurtain
+ \o Use the flash in conjunction with a slow shutter speed.
+ This mode allows better exposure of distant objects and/or motion blur effect.
+ \row \o FlashSlowSyncRearCurtain
+ \o The similar mode to FlashSlowSyncFrontCurtain but flash is fired at the end of exposure.
+ \row \o FlashManual \o Flash power is manually set.
+ \endtable
+
+*/
+/*!
+ \enum QDeclarativeCamera::FlashMode
+ \value FlashOff Flash is Off.
+ \value FlashOn Flash is On.
+ \value FlashAuto Automatic flash.
+ \value FlashRedEyeReduction Red eye reduction flash.
+ \value FlashFill Use flash to fillin shadows.
+ \value FlashTorch Constant light source, useful for focusing and video capture.
+ \value FlashSlowSyncFrontCurtain
+ Use the flash in conjunction with a slow shutter speed.
+ This mode allows better exposure of distant objects and/or motion blur effect.
+ \value FlashSlowSyncRearCurtain
+ The similar mode to FlashSlowSyncFrontCurtain but flash is fired at the end of exposure.
+ \value FlashManual Flash power is manually set.
+
+*/
+int QDeclarativeCamera::flashMode() const
+{
+ if (!m_isValid)
+ return 0;
+
+ return m_exposure->flashMode();
+}
+
+void QDeclarativeCamera::setFlashMode(int mode)
+{
+ if (m_isValid && m_exposure->flashMode() != mode) {
+ m_exposure->setFlashMode(QCameraExposure::FlashModes(mode));
+ emit flashModeChanged(mode);
+ }
+}
+
+/*!
+ \qmlproperty real Camera::exposureCompensation
+
+ Adjustment for the automatically calculated exposure. The value is
+ in EV units.
+ */
+/*!
+ \property QDeclarativeCamera::exposureCompensation
+
+ Adjustment for the automatically calculated exposure. The value is
+ in EV units.
+ */
+qreal QDeclarativeCamera::exposureCompensation() const
+{
+ if (!m_isValid)
+ return 0.0;
+
+ return m_exposure->exposureCompensation();
+}
+
+void QDeclarativeCamera::setExposureCompensation(qreal ev)
+{
+ if (m_isValid)
+ m_exposure->setExposureCompensation(ev);
+}
+
+/*!
+ \qmlproperty real Camera::isoSensitivity
+
+ The sensor's ISO sensitivity.
+ */
+/*!
+ \property QDeclarativeCamera::iso
+
+ The sensor's ISO sensitivity.
+ */
+int QDeclarativeCamera::isoSensitivity() const
+{
+ if (!m_isValid)
+ return 0;
+
+ return m_exposure->isoSensitivity();
+}
+
+void QDeclarativeCamera::setManualIsoSensitivity(int iso)
+{
+ if (!m_isValid)
+ return;
+
+ m_exposure->setManualIsoSensitivity(iso);
+}
+
+/*!
+ \qmlproperty real Camera::shutterSpeed
+
+ The camera's shutter speed, in seconds.
+*/
+/*!
+ \property QDeclarativeCamera::shutterSpeed
+
+ The camera's shutter speed, in seconds.
+*/
+qreal QDeclarativeCamera::shutterSpeed() const
+{
+ if (!m_isValid)
+ return 0.0;
+
+ return m_exposure->shutterSpeed();
+}
+
+/*!
+ \qmlproperty real Camera::aperture
+
+ The lens aperture as an F number (the ratio of the focal length to effective aperture diameter).
+*/
+/*!
+ \property QDeclarativeCamera::aperture
+
+ The lens aperture as an F number (the ratio of the focal length to effective aperture diameter).
+*/
+qreal QDeclarativeCamera::aperture() const
+{
+ if (!m_isValid)
+ return 0.0;
+
+ return m_exposure->aperture();
+}
+
+/*!
+ \qmlproperty enumeration Camera::exposureMode
+
+ \table
+ \header \o Value \o Description
+ \row \o ExposureManual \o Manual mode.
+ \row \o ExposureAuto \o Automatic mode.
+ \row \o ExposureNight \o Night mode.
+ \row \o ExposureBacklight \o Backlight exposure mode.
+ \row \o ExposureSpotlight \o Spotlight exposure mode.
+ \row \o ExposureSports \o Spots exposure mode.
+ \row \o ExposureSnow \o Snow exposure mode.
+ \row \o ExposureBeach \o Beach exposure mode.
+ \row \o ExposureLargeAperture \o Use larger aperture with small depth of field.
+ \row \o ExposureSmallAperture \o Use smaller aperture.
+ \row \o ExposurePortrait \o Portrait exposure mode.
+ \row \o ExposureModeVendor \o The base value for device specific exposure modes.
+ \endtable
+
+*/
+/*!
+ \enum QDeclarativeCamera::ExposureMode
+ \value ExposureManual Manual mode.
+ \value ExposureAuto Automatic mode.
+ \value ExposureNight Night mode.
+ \value ExposureBacklight Backlight exposure mode.
+ \value ExposureSpotlight Spotlight exposure mode.
+ \value ExposureSports Spots exposure mode.
+ \value ExposureSnow Snow exposure mode.
+ \value ExposureBeach Beach exposure mode.
+ \value ExposureLargeAperture Use larger aperture with small depth of field.
+ \value ExposureSmallAperture Use smaller aperture.
+ \value ExposurePortrait Portrait exposure mode.
+ \value ExposureModeVendor The base value for device specific exposure modes.
+
+*/
+/*!
+ \property QDeclarativeCamera::exposureMode
+
+ Camera exposure modes.
+*/
+QDeclarativeCamera::ExposureMode QDeclarativeCamera::exposureMode() const
+{
+ if (!m_isValid)
+ return QDeclarativeCamera::ExposureAuto;
+
+ return ExposureMode(m_exposure->exposureMode());
+}
+
+void QDeclarativeCamera::setExposureMode(QDeclarativeCamera::ExposureMode mode)
+{
+ if (!m_isValid)
+ return;
+
+ if (exposureMode() != mode) {
+ m_exposure->setExposureMode(QCameraExposure::ExposureMode(mode));
+ emit exposureModeChanged(exposureMode());
+ }
+}
+
+/*!
+ \qmlproperty size Camera::captureResolution
+
+ The resolution to capture the image at. If empty, the system will pick
+ a good size.
+*/
+/*!
+ \property QDeclarativeCamera::captureResolution
+
+ The resolution to capture the image at. If empty, the system will pick
+ a good size.
+*/
+QSize QDeclarativeCamera::captureResolution() const
+{
+ if (!m_isValid)
+ return QSize();
+
+ return m_imageSettings.resolution();
+}
+
+void QDeclarativeCamera::setCaptureResolution(const QSize &resolution)
+{
+ if (m_isValid && m_imageSettings.resolution() != resolution) {
+ m_imageSettings.setResolution(resolution);
+
+ if (!m_imageSettingsChanged) {
+ m_imageSettingsChanged = true;
+ QMetaObject::invokeMethod(this, "_q_updateImageSettings", Qt::QueuedConnection);
+ }
+
+ emit captureResolutionChanged(resolution);
+ }
+}
+
+/*!
+ \qmlproperty real Camera::maximumOpticalZoom
+
+ The maximum optical zoom factor, or 1.0 if optical zoom is not supported.
+*/
+/*!
+ \property QDeclarativeCamera::maximumOpticalZoom
+
+ The maximum optical zoom factor, or 1.0 if optical zoom is not supported.
+*/
+qreal QDeclarativeCamera::maximumOpticalZoom() const
+{
+ if (!m_isValid)
+ return 0.0;
+
+ return m_focus->maximumOpticalZoom();
+}
+
+/*!
+ \qmlproperty real Camera::maximumDigitalZoom
+
+ The maximum digital zoom factor, or 1.0 if digital zoom is not supported.
+*/
+/*!
+ \property QDeclarativeCamera::maximumDigitalZoom
+
+ The maximum digital zoom factor, or 1.0 if digital zoom is not supported.
+*/
+qreal QDeclarativeCamera::maximumDigitalZoom() const
+{
+ if (!m_isValid)
+ return 0.0;
+
+ return m_focus->maximumDigitalZoom();
+}
+
+/*!
+ \qmlproperty real Camera::opticalZoom
+
+ The current optical zoom factor.
+*/
+/*!
+ \property QDeclarativeCamera::opticalZoom
+
+ The current optical zoom factor.
+*/
+qreal QDeclarativeCamera::opticalZoom() const
+{
+ if (!m_isValid)
+ return 0.0;
+
+ return m_focus->opticalZoom();
+}
+
+void QDeclarativeCamera::setOpticalZoom(qreal value)
+{
+ if (m_isValid)
+ m_focus->zoomTo(value, digitalZoom());
+}
+
+/*!
+ \qmlproperty real Camera::digitalZoom
+
+ The current digital zoom factor.
+*/
+/*!
+ \property QDeclarativeCamera::digitalZoom
+
+ The current digital zoom factor.
+*/
+qreal QDeclarativeCamera::digitalZoom() const
+{
+ if (!m_isValid)
+ return 0.0;
+
+ return m_focus->digitalZoom();
+}
+
+void QDeclarativeCamera::setDigitalZoom(qreal value)
+{
+ if (m_isValid)
+ m_focus->zoomTo(opticalZoom(), value);
+}
+
+/*!
+ \enum QDeclarativeCamera::WhiteBalanceMode
+ \value WhiteBalanceManual Manual white balance. In this mode the manual white balance property value is used.
+ \value WhiteBalanceAuto Auto white balance mode.
+ \value WhiteBalanceSunlight Sunlight white balance mode.
+ \value WhiteBalanceCloudy Cloudy white balance mode.
+ \value WhiteBalanceShade Shade white balance mode.
+ \value WhiteBalanceTungsten Tungsten white balance mode.
+ \value WhiteBalanceFluorescent Fluorescent white balance mode.
+ \value WhiteBalanceIncandescent Incandescent white balance mode.
+ \value WhiteBalanceFlash Flash white balance mode.
+ \value WhiteBalanceSunset Sunset white balance mode.
+ \value WhiteBalanceVendor Vendor defined white balance mode.
+*/
+/*!
+ \qmlproperty enumeration Camera::whiteBalanceMode
+
+ \table
+ \header \o Value \o Description
+ \row \o WhiteBalanceManual \o Manual white balance. In this mode the manual white balance property value is used.
+ \row \o WhiteBalanceAuto \o Auto white balance mode.
+ \row \o WhiteBalanceSunlight \o Sunlight white balance mode.
+ \row \o WhiteBalanceCloudy \o Cloudy white balance mode.
+ \row \o WhiteBalanceShade \o Shade white balance mode.
+ \row \o WhiteBalanceTungsten \o Tungsten white balance mode.
+ \row \o WhiteBalanceFluorescent \o Fluorescent white balance mode.
+ \row \o WhiteBalanceIncandescent \o Incandescent white balance mode.
+ \row \o WhiteBalanceFlash \o Flash white balance mode.
+ \row \o WhiteBalanceSunset \o Sunset white balance mode.
+ \row \o WhiteBalanceVendor \o Vendor defined white balance mode.
+ \endtable
+
+ \sa manualWhiteBalance
+*/
+/*!
+ \property QDeclarativeCamera::whiteBalanceMode
+
+ \sa WhiteBalanceMode
+*/
+QDeclarativeCamera::WhiteBalanceMode QDeclarativeCamera::whiteBalanceMode() const
+{
+ if (!m_isValid)
+ return QDeclarativeCamera::WhiteBalanceAuto;
+
+ return WhiteBalanceMode(m_camera->imageProcessing()->whiteBalanceMode());
+}
+
+void QDeclarativeCamera::setWhiteBalanceMode(QDeclarativeCamera::WhiteBalanceMode mode) const
+{
+ if (m_isValid && whiteBalanceMode() != mode) {
+ m_camera->imageProcessing()->setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode(mode));
+ emit whiteBalanceModeChanged(whiteBalanceMode());
+ }
+}
+
+/*!
+ \qmlproperty int Camera::manualWhiteBalance
+
+ The color temperature used when in manual white balance mode (WhiteBalanceManual).
+
+ \sa whiteBalanceMode
+*/
+/*!
+ \property QDeclarativeCamera::manualWhiteBalance
+
+ The color temperature used when in manual white balance mode (WhiteBalanceManual).
+
+ \sa whiteBalanceMode
+*/
+int QDeclarativeCamera::manualWhiteBalance() const
+{
+ if (!m_isValid)
+ return 0;
+
+ return m_camera->imageProcessing()->manualWhiteBalance();
+}
+
+void QDeclarativeCamera::setManualWhiteBalance(int colorTemp) const
+{
+ if (m_isValid && manualWhiteBalance() != colorTemp) {
+ m_camera->imageProcessing()->setManualWhiteBalance(colorTemp);
+ emit manualWhiteBalanceChanged(manualWhiteBalance());
+ }
+}
+
+/*!
+ \qmlsignal Camera::onError(error, errorString)
+
+
+ This handler is called when an error occurs. The enumeration value \a error is one of the
+ values defined below, and a descriptive string value is available in \a errorString.
+
+ \table
+ \header \o Value \o Description
+ \row \o NoError \o No errors have occurred.
+ \row \o CameraError \o An error has occurred.
+ \row \o InvalidRequestError \o System resource doesn't support requested functionality.
+ \row \o ServiceMissingError \o No camera service available.
+ \row \o NotSupportedFeatureError \o The feature is not supported.
+ \endtable
+*/
+/*!
+ \qmlsignal Camera::onError(error, errorString)
+
+
+ This handler is called when an error occurs. The enumeration value \a error is one of the
+ values defined below, and a descriptive string value is available in \a errorString.
+*/
+/*!
+ \enum QDeclarativeCamera::Error
+ \value NoError No errors have occurred.
+ \value CameraError An error has occurred.
+ \value InvalidRequestError System resource doesn't support requested functionality.
+ \value ServiceMissingError No camera service available.
+ \value NotSupportedFeatureError The feature is not supported.
+*/
+
+
+/*!
+ \qmlsignal Camera::onCaptureFailed(message)
+
+ This handler is called when an error occurs during capture. A descriptive message is available in \a message.
+*/
+/*!
+ \fn QDeclarativeCamera::captureFailed(const QString &message)
+
+ This handler is called when an error occurs during capture. A descriptive message is available in \a message.
+*/
+
+/*!
+ \qmlsignal Camera::onImageCaptured(preview)
+
+ This handler is called when an image has been captured but not yet saved to the filesystem. The \a preview
+ parameter can be used as the URL supplied to an Image element.
+
+ \sa onImageSaved
+*/
+/*!
+ \fn QDeclarativeCamera::imageCaptured(const QString &preview)
+
+ This handler is called when an image has been captured but not yet saved to the filesystem. The \a preview
+ parameter can be used as the URL supplied to an Image element.
+
+ \sa imageSaved()
+*/
+
+/*!
+ \qmlsignal Camera::onImageSaved(path)
+
+ This handler is called after the image has been written to the filesystem. The \a path is a local file path, not a URL.
+
+ \sa onImageCaptured
+*/
+/*!
+ \fn QDeclarativeCamera::imageSaved(const QString &path)
+
+ This handler is called after the image has been written to the filesystem. The \a path is a local file path, not a URL.
+
+ \sa imageCaptured()
+*/
+
+
+/*!
+ \fn void QDeclarativeCamera::lockStatusChanged()
+
+ \qmlsignal Camera::lockStatusChanged()
+*/
+
+/*!
+ \fn void QDeclarativeCamera::stateChanged(QDeclarativeCamera::State)
+
+ \qmlsignal Camera::stateChanged(Camera::State)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::imageCaptured(const QString &)
+
+ \qmlsignal Camera::imageCaptured(string)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::imageSaved(const QString &)
+
+ \qmlsignal Camera::imageSaved(string)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::error(QDeclarativeCamera::Error , const QString &)
+
+ \qmlsignal Camera::error(Camera::Error, string)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::errorChanged()
+
+*/
+/*!
+ \qmlsignal Camera::errorChanged()
+*/
+
+/*!
+ \fn void QDeclarativeCamera::isoSensitivityChanged(int)
+*/
+/*!
+ \qmlsignal Camera::isoSensitivityChanged(int)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::apertureChanged(qreal)
+
+ \qmlsignal Camera::apertureChanged(real)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::shutterSpeedChanged(qreal)
+
+*/
+/*!
+ \qmlsignal Camera::shutterSpeedChanged(real)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::exposureCompensationChanged(qreal)
+
+*/
+/*!
+ \qmlsignal Camera::exposureCompensationChanged(real)
+*/
+
+/*!
+ \fn void QDeclarativeCamera:opticalZoomChanged(qreal zoom)
+
+ Optical zoom changed to \a zoom.
+*/
+/*!
+ \qmlsignal Camera::opticalZoomChanged(real)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::digitalZoomChanged(qreal)
+
+ \qmlsignal Camera::digitalZoomChanged(real)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::maximumOpticalZoomChanged(qreal)
+
+ \qmlsignal Camera::maximumOpticalZoomChanged(real)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::maximumDigitalZoomChanged(qreal)
+
+ \qmlsignal Camera::maximumDigitalZoomChanged(real)
+*/
+
+
+/*!
+ \fn void QDeclarativeCamera::exposureModeChanged(QDeclarativeCamera::ExposureMode)
+
+ \qmlsignal Camera::exposureModeChanged(Camera::ExposureMode)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::flashModeChanged(int)
+*/
+/*!
+ \qmlsignal Camera::flashModeChanged(int)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::whiteBalanceModeChanged(QDeclarativeCamera::WhiteBalanceMode) const
+
+*/
+/*!
+ \qmlsignal Camera::whiteBalanceModeChanged(Camera::WhiteBalanceMode)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::manualWhiteBalanceChanged(int) const
+*/
+/*!
+ \qmlsignal Camera::manualWhiteBalanceChanged(int)
+*/
+
+/*!
+ \fn void QDeclarativeCamera::captureResolutionChanged(const QSize &)
+
+ \qmlsignal Camera::captureResolutionChanged(Item)
+*/
+
+/*!
+ \fn QDeclarativeCamera::cameraStateChanged(QDeclarativeCamera::State)
+
+*/
+
+
+QT_END_NAMESPACE
+
+#include "moc_qdeclarativecamera_p.cpp"
diff --git a/src/imports/multimedia/qdeclarativecamera_p.h b/src/imports/multimedia/qdeclarativecamera_p.h
new file mode 100644
index 000000000..e477538b2
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativecamera_p.h
@@ -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
diff --git a/src/imports/multimedia/qdeclarativecamerapreviewprovider.cpp b/src/imports/multimedia/qdeclarativecamerapreviewprovider.cpp
new file mode 100644
index 000000000..293120eda
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativecamerapreviewprovider.cpp
@@ -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
diff --git a/src/imports/multimedia/qdeclarativecamerapreviewprovider_p.h b/src/imports/multimedia/qdeclarativecamerapreviewprovider_p.h
new file mode 100644
index 000000000..44a47e781
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativecamerapreviewprovider_p.h
@@ -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
diff --git a/src/imports/multimedia/qdeclarativemediabase.cpp b/src/imports/multimedia/qdeclarativemediabase.cpp
new file mode 100644
index 000000000..68552ed6a
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativemediabase.cpp
@@ -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
+
diff --git a/src/imports/multimedia/qdeclarativemediabase_p.h b/src/imports/multimedia/qdeclarativemediabase_p.h
new file mode 100644
index 000000000..ffe091614
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativemediabase_p.h
@@ -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
diff --git a/src/imports/multimedia/qdeclarativemediametadata_p.h b/src/imports/multimedia/qdeclarativemediametadata_p.h
new file mode 100644
index 000000000..ca28e6e07
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativemediametadata_p.h
@@ -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
diff --git a/src/imports/multimedia/qdeclarativevideo.cpp b/src/imports/multimedia/qdeclarativevideo.cpp
new file mode 100644
index 000000000..af87fe1bd
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativevideo.cpp
@@ -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"
diff --git a/src/imports/multimedia/qdeclarativevideo_p.h b/src/imports/multimedia/qdeclarativevideo_p.h
new file mode 100644
index 000000000..115ef9d10
--- /dev/null
+++ b/src/imports/multimedia/qdeclarativevideo_p.h
@@ -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
diff --git a/src/imports/multimedia/qmldir b/src/imports/multimedia/qmldir
new file mode 100644
index 000000000..91caabad1
--- /dev/null
+++ b/src/imports/multimedia/qmldir
@@ -0,0 +1 @@
+plugin declarative_multimedia
diff --git a/src/imports/qimportbase.pri b/src/imports/qimportbase.pri
new file mode 100644
index 000000000..405af24ec
--- /dev/null
+++ b/src/imports/qimportbase.pri
@@ -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)
+}
diff --git a/src/meegoinstalls/Makefile b/src/meegoinstalls/Makefile
new file mode 100644
index 000000000..de0b65142
--- /dev/null
+++ b/src/meegoinstalls/Makefile
@@ -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)
diff --git a/src/meegoinstalls/README b/src/meegoinstalls/README
new file mode 100644
index 000000000..fa3fc3049
--- /dev/null
+++ b/src/meegoinstalls/README
@@ -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 )
diff --git a/src/meegoinstalls/qt-mobility.spec b/src/meegoinstalls/qt-mobility.spec
new file mode 100644
index 000000000..fab3effff
--- /dev/null
+++ b/src/meegoinstalls/qt-mobility.spec
@@ -0,0 +1,1360 @@
+#
+# Do NOT Edit the Auto-generated Part!
+# Generated by: spectacle version 0.21
+#
+# >> macros
+# << macros
+
+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
+Source0: http://get.qt.nokia.com/qt/add-ons/%{name}-opensource-src-%{version}.tar.gz
+Source100: qt-mobility.yaml
+Requires: libqtconnectivity1 = %{version}
+Requires: libqtcontacts1 = %{version}
+Requires: libqtfeedback1 = %{version}
+Requires: libqtgallery1 = %{version}
+Requires: libqtlocation1 = %{version}
+Requires: libqtmessaging1 = %{version}
+Requires: libqtmultimediakit1 = %{version}
+Requires: libqtorganizer1 = %{version}
+Requires: libqtpublishsubscribe1 = %{version}
+Requires: libqtsensors1 = %{version}
+Requires: libqtserviceframework1 = %{version}
+Requires: libqtsysteminfo1 = %{version}
+Requires: libqtversit1 = %{version}
+Requires: libqtversitorganizer1 = %{version}
+BuildRequires: pkgconfig(QtGui)
+BuildRequires: pkgconfig(QtOpenGL)
+BuildRequires: pkgconfig(alsa)
+BuildRequires: pkgconfig(blkid)
+BuildRequires: pkgconfig(bluez)
+BuildRequires: pkgconfig(connman)
+BuildRequires: pkgconfig(contextsubscriber-1.0)
+BuildRequires: pkgconfig(gconf-2.0)
+BuildRequires: pkgconfig(geoclue)
+BuildRequires: pkgconfig(gstreamer-plugins-bad-free-0.10)
+BuildRequires: pkgconfig(gstreamer-plugins-base-0.10)
+BuildRequires: pkgconfig(gypsy)
+BuildRequires: pkgconfig(libiphb)
+BuildRequires: pkgconfig(libpulse)
+BuildRequires: pkgconfig(libmkcal)
+BuildRequires: pkgconfig(meegotouch)
+BuildRequires: pkgconfig(qttracker)
+BuildRequires: pkgconfig(qmfclient)
+BuildRequires: pkgconfig(sensord)
+BuildRequires: pkgconfig(udev)
+BuildRequires: pkgconfig(x11)
+BuildRequires: pkgconfig(xext)
+BuildRequires: pkgconfig(xrandr)
+BuildRequires: pkgconfig(xrender)
+BuildRequires: pkgconfig(xv)
+BuildRequires: pkgconfig(QtSparql)
+BuildRequires: pkgconfig(QtSparqlTrackerExtensions)
+BuildRequires: qt-devel-tools
+BuildRequires: fdupes
+
+
+%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.
+
+
+
+%package devel
+Summary: APIs for mobile device functionality - development files
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires: servicefw
+
+%description devel
+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.
+
+
+%package -n libqtconnectivity1
+Summary: Qt Mobility Connectivity module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtconnectivity1
+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.
+
+
+%package -n libqtcontacts1
+Summary: Qt Mobility Contacts module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtcontacts1
+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.
+
+
+%package -n libqtfeedback1
+Summary: Qt Mobility Feedback module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtfeedback1
+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.
+
+
+%package -n libqtgallery1
+Summary: Qt Mobility Document Gallery module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtgallery1
+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.
+
+
+%package -n libqtlocation1
+Summary: Qt Mobility Location module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtlocation1
+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.
+
+
+%package -n libqtmessaging1
+Summary: Qt Mobility Messaging module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtmessaging1
+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.
+
+
+%package -n libqtmultimediakit1
+Summary: Qt Mobility MultimediaKit module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtmultimediakit1
+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.
+
+
+%package -n libqtorganizer1
+Summary: Qt Mobility Organizer module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtorganizer1
+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.
+
+
+%package -n libqtpublishsubscribe1
+Summary: Qt Mobility Publish and Subscribe module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtpublishsubscribe1
+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.
+
+
+%package -n libqtsensors1
+Summary: Qt Mobility Sensors module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires: libqtsql4-sqlite
+Requires: sensorfw
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtsensors1
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains the Sensors API. It provides access to sensors.
+
+
+%package -n libqtserviceframework1
+Summary: Qt Mobility Service Framework module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtserviceframework1
+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.
+
+
+%package -n libqtsysteminfo1
+Summary: Qt Mobility System Information module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtsysteminfo1
+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.
+
+
+%package -n libqtversit1
+Summary: Qt Mobility Versit (vCard) module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtversit1
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains an API to manage Versit documents, such as vCards.
+
+
+%package -n libqtversitorganizer1
+Summary: Qt Mobility Versit (Organizer) module
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description -n libqtversitorganizer1
+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.
+
+
+%package -n libdeclarative-contacts
+Summary: Qt Mobility Contacts QML plugin
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description -n libdeclarative-contacts
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains the Contacts QML plugin for QtDeclarative.
+
+
+%package -n libdeclarative-feedback
+Summary: Qt Mobility Feedback QML plugin
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description -n libdeclarative-feedback
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains the Feedback QML plugin for QtDeclarative.
+
+
+%package -n libdeclarative-gallery
+Summary: Qt Mobility Document Gallery QML plugin
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description -n libdeclarative-gallery
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains the Document Gallery QML plugin for QtDeclarative.
+
+
+%package -n libdeclarative-location
+Summary: Qt Mobility Location QML plugin
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description -n libdeclarative-location
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains the Location QML plugin for QtDeclarative.
+
+
+%package -n libdeclarative-messaging
+Summary: Qt Mobility Messaging QML plugin
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description -n libdeclarative-messaging
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains the Messaging QML plugin for QtDeclarative.
+
+
+%package -n libdeclarative-multimedia
+Summary: Qt Mobility Multimedia QML plugin
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description -n libdeclarative-multimedia
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains the Multimedia QML plugin for QtDeclarative.
+
+
+%package -n libdeclarative-organizer
+Summary: Qt Mobility Organizer QML plugin
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description -n libdeclarative-organizer
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains the Organizer QML plugin for QtDeclarative.
+
+
+%package -n libdeclarative-publishsubscribe
+Summary: Qt Mobility Publish and Subscribe QML plugin
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description -n libdeclarative-publishsubscribe
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains the Publish and Subscribe QML plugin for QtDeclarative.
+
+
+%package -n libdeclarative-sensors
+Summary: Qt Mobility Sensors Framework QML plugin
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description -n libdeclarative-sensors
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains the Sensors QML plugin for QtDeclarative.
+
+
+%package -n libdeclarative-serviceframework
+Summary: Qt Mobility Service Framework QML plugin
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description -n libdeclarative-serviceframework
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains the Service Framework QML plugin for QtDeclarative.
+
+
+%package -n libdeclarative-systeminfo
+Summary: Qt Mobility System Information QML plugin
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description -n libdeclarative-systeminfo
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains the System Information QML plugin for QtDeclarative.
+
+
+%package -n libdeclarative-connectivity
+Summary: Qt Mobility Connectivity QML plugin
+Group: System/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description -n libdeclarative-connectivity
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains the Connectivity QML plugin for QtDeclarative.
+
+
+%package -n servicefw
+Summary: Qt Mobility Service Framework tool
+Group: Development/Tools
+Requires: %{name} = %{version}-%{release}
+
+%description -n servicefw
+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.
+
+
+%package examples
+Summary: Qt Mobility examples
+Group: System/X11
+Requires: %{name} = %{version}-%{release}
+
+%description examples
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains Qt Mobility examples.
+
+
+%package l10n
+Summary: APIs for mobile device functionality - localization files
+Group: System/I18n
+Requires: %{name} = %{version}-%{release}
+
+%description l10n
+Qt Mobility delivers a set of new APIs for mobile device functionality.
+
+This package contains Qt Mobility translations.
+
+
+
+%prep
+%setup -q -n %{name}-opensource-src-%{version}
+
+# >> setup
+# << setup
+
+%build
+# >> build pre
+# QMF environment variables should be set
+export QMF_INCLUDEDIR=%{_includedir}/qmfclient
+export QMF_LIBDIR=%{_libdir}
+./configure \
+-prefix "%{_prefix}" \
+-headerdir "%{_includedir}" \
+-libdir "%{_libdir}" \
+-bindir "%{_bindir}" \
+-plugindir "%{_libdir}/qt4/plugins" \
+-demosdir "%{_libdir}/qtmobility/demos" \
+-examplesdir "%{_libdir}/qtmobility/examples" \
+-languages "ar cs da de es fr he hu ja pl pt ru sk sl sv zh_CN zh_TW" \
+-examples \
+-demos \
+-modules "location contacts multimedia publishsubscribe versit messaging systeminfo serviceframework sensors gallery organizer feedback connectivity" \
+-meego
+make %{?_smp_mflags}
+# << build pre
+
+
+
+# >> build post
+# << build post
+%install
+rm -rf %{buildroot}
+# >> install pre
+# << install pre
+
+# >> install post
+%qmake_install
+# Fix wrong path in pkgconfig files
+find %{buildroot}%{_libdir}/pkgconfig -type f -name '*.pc' \
+-exec perl -pi -e "s, -L%{_builddir}/%{name}-opensource-src-\Q%{version}\E/?\S+,,g" {} \;
+# Fix executable permissions
+find %{buildroot}%{_libdir}/qtmobility -type f -perm /u+x,g+x,o+x \( -false \
+-o -name \*.qml \
+-o -name \*.sci \
+-o -name qmldir \
+-o -name \*.txt \
+\) -exec chmod -x \{\} +
+# Fix duplicate files
+%fdupes %{buildroot}%{_includedir}
+%fdupes %{buildroot}%{_libdir}/qtmobility
+# << install post
+%fdupes %{buildroot}/%{_datadir}/qtmobility/translations
+
+
+
+
+
+
+
+
+
+
+%post -n libqtconnectivity1 -p /sbin/ldconfig
+
+%postun -n libqtconnectivity1 -p /sbin/ldconfig
+
+
+%post -n libqtcontacts1 -p /sbin/ldconfig
+
+%postun -n libqtcontacts1 -p /sbin/ldconfig
+
+
+%post -n libqtfeedback1 -p /sbin/ldconfig
+
+%postun -n libqtfeedback1 -p /sbin/ldconfig
+
+
+%post -n libqtgallery1 -p /sbin/ldconfig
+
+%postun -n libqtgallery1 -p /sbin/ldconfig
+
+
+%post -n libqtlocation1 -p /sbin/ldconfig
+
+%postun -n libqtlocation1 -p /sbin/ldconfig
+
+
+%post -n libqtmessaging1 -p /sbin/ldconfig
+
+%postun -n libqtmessaging1 -p /sbin/ldconfig
+
+
+%post -n libqtmultimediakit1 -p /sbin/ldconfig
+
+%postun -n libqtmultimediakit1 -p /sbin/ldconfig
+
+
+%post -n libqtorganizer1 -p /sbin/ldconfig
+
+%postun -n libqtorganizer1 -p /sbin/ldconfig
+
+
+%post -n libqtpublishsubscribe1 -p /sbin/ldconfig
+
+%postun -n libqtpublishsubscribe1 -p /sbin/ldconfig
+
+
+%post -n libqtsensors1 -p /sbin/ldconfig
+
+%postun -n libqtsensors1 -p /sbin/ldconfig
+
+
+%post -n libqtserviceframework1 -p /sbin/ldconfig
+
+%postun -n libqtserviceframework1 -p /sbin/ldconfig
+
+
+%post -n libqtsysteminfo1 -p /sbin/ldconfig
+
+%postun -n libqtsysteminfo1 -p /sbin/ldconfig
+
+
+%post -n libqtversit1 -p /sbin/ldconfig
+
+%postun -n libqtversit1 -p /sbin/ldconfig
+
+
+%post -n libqtversitorganizer1 -p /sbin/ldconfig
+
+%postun -n libqtversitorganizer1 -p /sbin/ldconfig
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+%files
+%defattr(-,root,root,-)
+# >> files
+# << files
+
+
+%files devel
+%defattr(-,root,root,-)
+# >> files devel
+%{_bindir}/icheck
+%{_bindir}/ndefhandlergen
+%{_bindir}/qcrmlgen
+%{_bindir}/servicedbgen
+%{_bindir}/servicexmlgen
+%{_bindir}/vsexplorer
+%{_includedir}/QtConnectivity/*.h
+%{_includedir}/QtConnectivity/QBluetoothAddress
+%{_includedir}/QtConnectivity/QBluetoothDeviceDiscoveryAgent
+%{_includedir}/QtConnectivity/QBluetoothDeviceInfo
+%{_includedir}/QtConnectivity/QBluetoothHostInfo
+%{_includedir}/QtConnectivity/QBluetoothLocalDevice
+%{_includedir}/QtConnectivity/QBluetoothServiceDiscoveryAgent
+%{_includedir}/QtConnectivity/QBluetoothServiceInfo
+%{_includedir}/QtConnectivity/QBluetoothSocket
+%{_includedir}/QtConnectivity/QBluetoothTransferManager
+%{_includedir}/QtConnectivity/QBluetoothTransferReply
+%{_includedir}/QtConnectivity/QBluetoothTransferRequest
+%{_includedir}/QtConnectivity/QBluetoothUuid
+%{_includedir}/QtConnectivity/QDeclarativeNdefRecord
+%{_includedir}/QtConnectivity/QL2capServer
+%{_includedir}/QtConnectivity/QL2capSocket
+%{_includedir}/QtConnectivity/QLlcpServer
+%{_includedir}/QtConnectivity/QLlcpSocket
+%{_includedir}/QtConnectivity/QNdefFilter
+%{_includedir}/QtConnectivity/QNdefMessage
+%{_includedir}/QtConnectivity/QNdefNfcTextRecord
+%{_includedir}/QtConnectivity/QNdefNfcUriRecord
+%{_includedir}/QtConnectivity/QNdefRecord
+%{_includedir}/QtConnectivity/QNearFieldManager
+%{_includedir}/QtConnectivity/QNearFieldTagType1
+%{_includedir}/QtConnectivity/QNearFieldTagType2
+%{_includedir}/QtConnectivity/QNearFieldTagType3
+%{_includedir}/QtConnectivity/QNearFieldTagType4
+%{_includedir}/QtConnectivity/QNearFieldTarget
+%{_includedir}/QtConnectivity/QRfcommServer
+%{_includedir}/QtConnectivity/QRfcommSocket
+%{_includedir}/QtContacts/*.h
+%{_includedir}/QtContacts/QContact
+%{_includedir}/QtContacts/QContactAbstractRequest
+%{_includedir}/QtContacts/QContactAction
+%{_includedir}/QtContacts/QContactActionDescriptor
+%{_includedir}/QtContacts/QContactActionFactory
+%{_includedir}/QtContacts/QContactActionFilter
+%{_includedir}/QtContacts/QContactActionTarget
+%{_includedir}/QtContacts/QContactAddress
+%{_includedir}/QtContacts/QContactAnniversary
+%{_includedir}/QtContacts/QContactAvatar
+%{_includedir}/QtContacts/QContactBirthday
+%{_includedir}/QtContacts/QContactChangeLogFilter
+%{_includedir}/QtContacts/QContactChangeSet
+%{_includedir}/QtContacts/QContactDetail
+%{_includedir}/QtContacts/QContactDetailDefinition
+%{_includedir}/QtContacts/QContactDetailDefinitionFetchRequest
+%{_includedir}/QtContacts/QContactDetailDefinitionRemoveRequest
+%{_includedir}/QtContacts/QContactDetailDefinitionSaveRequest
+%{_includedir}/QtContacts/QContactDetailFieldDefinition
+%{_includedir}/QtContacts/QContactDetailFilter
+%{_includedir}/QtContacts/QContactDetailRangeFilter
+%{_includedir}/QtContacts/QContactDisplayLabel
+%{_includedir}/QtContacts/QContactEmailAddress
+%{_includedir}/QtContacts/QContactFamily
+%{_includedir}/QtContacts/QContactFavorite
+%{_includedir}/QtContacts/QContactFetchByIdRequest
+%{_includedir}/QtContacts/QContactFetchHint
+%{_includedir}/QtContacts/QContactFetchRequest
+%{_includedir}/QtContacts/QContactFilter
+%{_includedir}/QtContacts/QContactGender
+%{_includedir}/QtContacts/QContactGeoLocation
+%{_includedir}/QtContacts/QContactGlobalPresence
+%{_includedir}/QtContacts/QContactGuid
+%{_includedir}/QtContacts/QContactHobby
+%{_includedir}/QtContacts/QContactId
+%{_includedir}/QtContacts/QContactIntersectionFilter
+%{_includedir}/QtContacts/QContactInvalidFilter
+%{_includedir}/QtContacts/QContactLocalIdFetchRequest
+%{_includedir}/QtContacts/QContactLocalIdFilter
+%{_includedir}/QtContacts/QContactManager
+%{_includedir}/QtContacts/QContactManagerEngine
+%{_includedir}/QtContacts/QContactManagerEngineFactory
+%{_includedir}/QtContacts/QContactManagerEngineV2
+%{_includedir}/QtContacts/QContactName
+%{_includedir}/QtContacts/QContactNickname
+%{_includedir}/QtContacts/QContactNote
+%{_includedir}/QtContacts/QContactObserver
+%{_includedir}/QtContacts/QContactOnlineAccount
+%{_includedir}/QtContacts/QContactOrganization
+%{_includedir}/QtContacts/QContactPhoneNumber
+%{_includedir}/QtContacts/QContactPresence
+%{_includedir}/QtContacts/QContactRelationship
+%{_includedir}/QtContacts/QContactRelationshipFetchRequest
+%{_includedir}/QtContacts/QContactRelationshipFilter
+%{_includedir}/QtContacts/QContactRelationshipRemoveRequest
+%{_includedir}/QtContacts/QContactRelationshipSaveRequest
+%{_includedir}/QtContacts/QContactRemoveRequest
+%{_includedir}/QtContacts/QContactRingtone
+%{_includedir}/QtContacts/QContactSaveRequest
+%{_includedir}/QtContacts/QContactSortOrder
+%{_includedir}/QtContacts/QContactSyncTarget
+%{_includedir}/QtContacts/QContactTag
+%{_includedir}/QtContacts/QContactThumbnail
+%{_includedir}/QtContacts/QContactTimestamp
+%{_includedir}/QtContacts/QContactType
+%{_includedir}/QtContacts/QContactUnionFilter
+%{_includedir}/QtContacts/QContactUrl
+%{_includedir}/QtFeedback/*.h
+%{_includedir}/QtFeedback/QFeedbackActuator
+%{_includedir}/QtFeedback/QFeedbackEffect
+%{_includedir}/QtFeedback/QFeedbackFileEffect
+%{_includedir}/QtFeedback/QFeedbackFileInterface
+%{_includedir}/QtFeedback/QFeedbackHapticsEffect
+%{_includedir}/QtFeedback/QFeedbackHapticsInterface
+%{_includedir}/QtFeedback/QFeedbackInterface
+%{_includedir}/QtFeedback/QFeedbackThemeInterface
+%{_includedir}/QtGallery/*.h
+%{_includedir}/QtGallery/QAbstractGallery
+%{_includedir}/QtGallery/QDocumentGallery
+%{_includedir}/QtGallery/QGalleryAbstractRequest
+%{_includedir}/QtGallery/QGalleryAbstractResponse
+%{_includedir}/QtGallery/QGalleryFilter
+%{_includedir}/QtGallery/QGalleryIntersectionFilter
+%{_includedir}/QtGallery/QGalleryItemRequest
+%{_includedir}/QtGallery/QGalleryMetaDataFilter
+%{_includedir}/QtGallery/QGalleryQueryModel
+%{_includedir}/QtGallery/QGalleryQueryRequest
+%{_includedir}/QtGallery/QGalleryResource
+%{_includedir}/QtGallery/QGalleryResultSet
+%{_includedir}/QtGallery/QGalleryTypeRequest
+%{_includedir}/QtGallery/QGalleryUnionFilter
+%{_includedir}/QtLocation/*.h
+%{_includedir}/QtLocation/QGeoAddress
+%{_includedir}/QtLocation/QGeoAreaMonitor
+%{_includedir}/QtLocation/QGeoBoundingArea
+%{_includedir}/QtLocation/QGeoBoundingBox
+%{_includedir}/QtLocation/QGeoBoundingCircle
+%{_includedir}/QtLocation/QGeoCoordinate
+%{_includedir}/QtLocation/QGeoManeuver
+%{_includedir}/QtLocation/QGeoMapCircleObject
+%{_includedir}/QtLocation/QGeoMapCustomObject
+%{_includedir}/QtLocation/QGeoMapData
+%{_includedir}/QtLocation/QGeoMapGroupObject
+%{_includedir}/QtLocation/QGeoMapObject
+%{_includedir}/QtLocation/QGeoMapObjectInfo
+%{_includedir}/QtLocation/QGeoMapOverlay
+%{_includedir}/QtLocation/QGeoMapPixmapObject
+%{_includedir}/QtLocation/QGeoMapPolygonObject
+%{_includedir}/QtLocation/QGeoMapPolylineObject
+%{_includedir}/QtLocation/QGeoMapRectangleObject
+%{_includedir}/QtLocation/QGeoMapRouteObject
+%{_includedir}/QtLocation/QGeoMapTextObject
+%{_includedir}/QtLocation/QGeoMappingManager
+%{_includedir}/QtLocation/QGeoMappingManagerEngine
+%{_includedir}/QtLocation/QGeoPlace
+%{_includedir}/QtLocation/QGeoPositionInfo
+%{_includedir}/QtLocation/QGeoPositionInfoSource
+%{_includedir}/QtLocation/QGeoPositionInfoSourceFactory
+%{_includedir}/QtLocation/QGeoRoute
+%{_includedir}/QtLocation/QGeoRouteReply
+%{_includedir}/QtLocation/QGeoRouteRequest
+%{_includedir}/QtLocation/QGeoRouteSegment
+%{_includedir}/QtLocation/QGeoRoutingManager
+%{_includedir}/QtLocation/QGeoRoutingManagerEngine
+%{_includedir}/QtLocation/QGeoSatelliteInfo
+%{_includedir}/QtLocation/QGeoSatelliteInfoSource
+%{_includedir}/QtLocation/QGeoSearchManager
+%{_includedir}/QtLocation/QGeoSearchManagerEngine
+%{_includedir}/QtLocation/QGeoSearchReply
+%{_includedir}/QtLocation/QGeoServiceProvider
+%{_includedir}/QtLocation/QGeoServiceProviderFactory
+%{_includedir}/QtLocation/QGeoTiledMapData
+%{_includedir}/QtLocation/QGeoTiledMapReply
+%{_includedir}/QtLocation/QGeoTiledMapRequest
+%{_includedir}/QtLocation/QGeoTiledMappingManagerEngine
+%{_includedir}/QtLocation/QGraphicsGeoMap
+%{_includedir}/QtLocation/QLandmark
+%{_includedir}/QtLocation/QLandmarkAbstractRequest
+%{_includedir}/QtLocation/QLandmarkAttributeFilter
+%{_includedir}/QtLocation/QLandmarkBoxFilter
+%{_includedir}/QtLocation/QLandmarkCategory
+%{_includedir}/QtLocation/QLandmarkCategoryFetchByIdRequest
+%{_includedir}/QtLocation/QLandmarkCategoryFetchRequest
+%{_includedir}/QtLocation/QLandmarkCategoryFilter
+%{_includedir}/QtLocation/QLandmarkCategoryId
+%{_includedir}/QtLocation/QLandmarkCategoryIdFetchRequest
+%{_includedir}/QtLocation/QLandmarkCategoryRemoveRequest
+%{_includedir}/QtLocation/QLandmarkCategorySaveRequest
+%{_includedir}/QtLocation/QLandmarkExportRequest
+%{_includedir}/QtLocation/QLandmarkFetchByIdRequest
+%{_includedir}/QtLocation/QLandmarkFetchRequest
+%{_includedir}/QtLocation/QLandmarkFilter
+%{_includedir}/QtLocation/QLandmarkId
+%{_includedir}/QtLocation/QLandmarkIdFetchRequest
+%{_includedir}/QtLocation/QLandmarkIdFilter
+%{_includedir}/QtLocation/QLandmarkImportRequest
+%{_includedir}/QtLocation/QLandmarkIntersectionFilter
+%{_includedir}/QtLocation/QLandmarkManager
+%{_includedir}/QtLocation/QLandmarkManagerEngine
+%{_includedir}/QtLocation/QLandmarkManagerEngineFactory
+%{_includedir}/QtLocation/QLandmarkNameFilter
+%{_includedir}/QtLocation/QLandmarkNameSort
+%{_includedir}/QtLocation/QLandmarkProximityFilter
+%{_includedir}/QtLocation/QLandmarkRemoveRequest
+%{_includedir}/QtLocation/QLandmarkSaveRequest
+%{_includedir}/QtLocation/QLandmarkSortOrder
+%{_includedir}/QtLocation/QLandmarkUnionFilter
+%{_includedir}/QtLocation/QNmeaPositionInfoSource
+%{_includedir}/QtMessaging/*.h
+%{_includedir}/QtMessaging/QMessage
+%{_includedir}/QtMessaging/QMessageAccount
+%{_includedir}/QtMessaging/QMessageAccountFilter
+%{_includedir}/QtMessaging/QMessageAccountId
+%{_includedir}/QtMessaging/QMessageAccountSortOrder
+%{_includedir}/QtMessaging/QMessageAddress
+%{_includedir}/QtMessaging/QMessageContentContainer
+%{_includedir}/QtMessaging/QMessageContentContainerId
+%{_includedir}/QtMessaging/QMessageDataComparator
+%{_includedir}/QtMessaging/QMessageFilter
+%{_includedir}/QtMessaging/QMessageFolder
+%{_includedir}/QtMessaging/QMessageFolderFilter
+%{_includedir}/QtMessaging/QMessageFolderId
+%{_includedir}/QtMessaging/QMessageFolderSortOrder
+%{_includedir}/QtMessaging/QMessageId
+%{_includedir}/QtMessaging/QMessageManager
+%{_includedir}/QtMessaging/QMessageService
+%{_includedir}/QtMessaging/QMessageSortOrder
+%{_includedir}/QtMobility/*.h
+%{_includedir}/QtMobility/QLatin1Constant
+%{_includedir}/QtMultimediaKit/*.h
+%{_includedir}/QtMultimediaKit/QAbstractAudioDeviceInfo
+%{_includedir}/QtMultimediaKit/QAbstractAudioInput
+%{_includedir}/QtMultimediaKit/QAbstractAudioOutput
+%{_includedir}/QtMultimediaKit/QAbstractVideoBuffer
+%{_includedir}/QtMultimediaKit/QAbstractVideoSurface
+%{_includedir}/QtMultimediaKit/QAudio
+%{_includedir}/QtMultimediaKit/QAudioCaptureSource
+%{_includedir}/QtMultimediaKit/QAudioDeviceInfo
+%{_includedir}/QtMultimediaKit/QAudioEncoderControl
+%{_includedir}/QtMultimediaKit/QAudioEncoderSettings
+%{_includedir}/QtMultimediaKit/QAudioEndpointSelector
+%{_includedir}/QtMultimediaKit/QAudioFormat
+%{_includedir}/QtMultimediaKit/QAudioInput
+%{_includedir}/QtMultimediaKit/QAudioOutput
+%{_includedir}/QtMultimediaKit/QAudioSystemPlugin
+%{_includedir}/QtMultimediaKit/QCamera
+%{_includedir}/QtMultimediaKit/QCameraControl
+%{_includedir}/QtMultimediaKit/QCameraExposure
+%{_includedir}/QtMultimediaKit/QCameraExposureControl
+%{_includedir}/QtMultimediaKit/QCameraFlashControl
+%{_includedir}/QtMultimediaKit/QCameraFocus
+%{_includedir}/QtMultimediaKit/QCameraFocusControl
+%{_includedir}/QtMultimediaKit/QCameraFocusZone
+%{_includedir}/QtMultimediaKit/QCameraImageCapture
+%{_includedir}/QtMultimediaKit/QCameraImageCaptureControl
+%{_includedir}/QtMultimediaKit/QCameraImageProcessing
+%{_includedir}/QtMultimediaKit/QCameraImageProcessingControl
+%{_includedir}/QtMultimediaKit/QCameraCaptureBufferFormatControl
+%{_includedir}/QtMultimediaKit/QCameraCaptureDestinationControl
+%{_includedir}/QtMultimediaKit/QCameraLocksControl
+%{_includedir}/QtMultimediaKit/QCameraViewfinder
+%{_includedir}/QtMultimediaKit/QGraphicsVideoItem
+%{_includedir}/QtMultimediaKit/QImageEncoderControl
+%{_includedir}/QtMultimediaKit/QImageEncoderSettings
+%{_includedir}/QtMultimediaKit/QLocalMediaPlaylistProvider
+%{_includedir}/QtMultimediaKit/QMediaBindableInterface
+%{_includedir}/QtMultimediaKit/QMediaContainerControl
+%{_includedir}/QtMultimediaKit/QMediaContent
+%{_includedir}/QtMultimediaKit/QMediaControl
+%{_includedir}/QtMultimediaKit/QMediaImageViewer
+%{_includedir}/QtMultimediaKit/QMediaObject
+%{_includedir}/QtMultimediaKit/QMediaPlayer
+%{_includedir}/QtMultimediaKit/QMediaPlayerControl
+%{_includedir}/QtMultimediaKit/QMediaPlaylist
+%{_includedir}/QtMultimediaKit/QMediaPlaylistControl
+%{_includedir}/QtMultimediaKit/QMediaPlaylistIOPlugin
+%{_includedir}/QtMultimediaKit/QMediaPlaylistNavigator
+%{_includedir}/QtMultimediaKit/QMediaPlaylistProvider
+%{_includedir}/QtMultimediaKit/QMediaPlaylistReader
+%{_includedir}/QtMultimediaKit/QMediaPlaylistSourceControl
+%{_includedir}/QtMultimediaKit/QMediaPlaylistWriter
+%{_includedir}/QtMultimediaKit/QMediaRecorder
+%{_includedir}/QtMultimediaKit/QMediaRecorderControl
+%{_includedir}/QtMultimediaKit/QMediaResource
+%{_includedir}/QtMultimediaKit/QMediaService
+%{_includedir}/QtMultimediaKit/QMediaServiceProvider
+%{_includedir}/QtMultimediaKit/QMediaServiceProviderHint
+%{_includedir}/QtMultimediaKit/QMediaServiceProviderPlugin
+%{_includedir}/QtMultimediaKit/QMediaStreamsControl
+%{_includedir}/QtMultimediaKit/QMediaTimeInterval
+%{_includedir}/QtMultimediaKit/QMediaTimeRange
+%{_includedir}/QtMultimediaKit/QMetaDataReaderControl
+%{_includedir}/QtMultimediaKit/QMetaDataWriterControl
+%{_includedir}/QtMultimediaKit/QRadioTuner
+%{_includedir}/QtMultimediaKit/QRadioTunerControl
+%{_includedir}/QtMultimediaKit/QVideoDeviceControl
+%{_includedir}/QtMultimediaKit/QVideoEncoderControl
+%{_includedir}/QtMultimediaKit/QVideoEncoderSettings
+%{_includedir}/QtMultimediaKit/QVideoFrame
+%{_includedir}/QtMultimediaKit/QVideoRendererControl
+%{_includedir}/QtMultimediaKit/QVideoSurfaceFormat
+%{_includedir}/QtMultimediaKit/QVideoWidget
+%{_includedir}/QtMultimediaKit/QVideoWidgetControl
+%{_includedir}/QtMultimediaKit/QVideoWindowControl
+%{_includedir}/QtMultimediaKit/QMediaNetworkAccessControl
+%{_includedir}/QtOrganizer/*.h
+%{_includedir}/QtOrganizer/QOrganizerAbstractRequest
+%{_includedir}/QtOrganizer/QOrganizerCollection
+%{_includedir}/QtOrganizer/QOrganizerCollectionChangeSet
+%{_includedir}/QtOrganizer/QOrganizerCollectionEngineId
+%{_includedir}/QtOrganizer/QOrganizerCollectionFetchRequest
+%{_includedir}/QtOrganizer/QOrganizerCollectionId
+%{_includedir}/QtOrganizer/QOrganizerCollectionRemoveRequest
+%{_includedir}/QtOrganizer/QOrganizerCollectionSaveRequest
+%{_includedir}/QtOrganizer/QOrganizerEvent
+%{_includedir}/QtOrganizer/QOrganizerEventOccurrence
+%{_includedir}/QtOrganizer/QOrganizerEventTime
+%{_includedir}/QtOrganizer/QOrganizerItem
+%{_includedir}/QtOrganizer/QOrganizerItemAudibleReminder
+%{_includedir}/QtOrganizer/QOrganizerItemChangeLogFilter
+%{_includedir}/QtOrganizer/QOrganizerItemChangeSet
+%{_includedir}/QtOrganizer/QOrganizerItemCollectionFilter
+%{_includedir}/QtOrganizer/QOrganizerItemComment
+%{_includedir}/QtOrganizer/QOrganizerItemDescription
+%{_includedir}/QtOrganizer/QOrganizerItemDetail
+%{_includedir}/QtOrganizer/QOrganizerItemDetailDefinition
+%{_includedir}/QtOrganizer/QOrganizerItemDetailDefinitionFetchRequest
+%{_includedir}/QtOrganizer/QOrganizerItemDetailDefinitionRemoveRequest
+%{_includedir}/QtOrganizer/QOrganizerItemDetailDefinitionSaveRequest
+%{_includedir}/QtOrganizer/QOrganizerItemDetailFieldDefinition
+%{_includedir}/QtOrganizer/QOrganizerItemDetailFilter
+%{_includedir}/QtOrganizer/QOrganizerItemDetailRangeFilter
+%{_includedir}/QtOrganizer/QOrganizerItemDisplayLabel
+%{_includedir}/QtOrganizer/QOrganizerItemEmailReminder
+%{_includedir}/QtOrganizer/QOrganizerItemEngineId
+%{_includedir}/QtOrganizer/QOrganizerItemFetchByIdRequest
+%{_includedir}/QtOrganizer/QOrganizerItemFetchForExportRequest
+%{_includedir}/QtOrganizer/QOrganizerItemFetchHint
+%{_includedir}/QtOrganizer/QOrganizerItemFetchRequest
+%{_includedir}/QtOrganizer/QOrganizerItemFilter
+%{_includedir}/QtOrganizer/QOrganizerItemGuid
+%{_includedir}/QtOrganizer/QOrganizerItemId
+%{_includedir}/QtOrganizer/QOrganizerItemIdFetchRequest
+%{_includedir}/QtOrganizer/QOrganizerItemIdFilter
+%{_includedir}/QtOrganizer/QOrganizerItemIntersectionFilter
+%{_includedir}/QtOrganizer/QOrganizerItemInvalidFilter
+%{_includedir}/QtOrganizer/QOrganizerItemLocation
+%{_includedir}/QtOrganizer/QOrganizerItemObserver
+%{_includedir}/QtOrganizer/QOrganizerItemOccurrenceFetchRequest
+%{_includedir}/QtOrganizer/QOrganizerItemParent
+%{_includedir}/QtOrganizer/QOrganizerItemPriority
+%{_includedir}/QtOrganizer/QOrganizerItemRecurrence
+%{_includedir}/QtOrganizer/QOrganizerItemReminder
+%{_includedir}/QtOrganizer/QOrganizerItemRemoveRequest
+%{_includedir}/QtOrganizer/QOrganizerItemSaveRequest
+%{_includedir}/QtOrganizer/QOrganizerItemSortOrder
+%{_includedir}/QtOrganizer/QOrganizerItemTag
+%{_includedir}/QtOrganizer/QOrganizerItemTimestamp
+%{_includedir}/QtOrganizer/QOrganizerItemType
+%{_includedir}/QtOrganizer/QOrganizerItemUnionFilter
+%{_includedir}/QtOrganizer/QOrganizerItemVisualReminder
+%{_includedir}/QtOrganizer/QOrganizerJournal
+%{_includedir}/QtOrganizer/QOrganizerJournalTime
+%{_includedir}/QtOrganizer/QOrganizerManager
+%{_includedir}/QtOrganizer/QOrganizerManagerEngine
+%{_includedir}/QtOrganizer/QOrganizerManagerEngineFactory
+%{_includedir}/QtOrganizer/QOrganizerManagerEngineV2
+%{_includedir}/QtOrganizer/QOrganizerNote
+%{_includedir}/QtOrganizer/QOrganizerRecurrenceRule
+%{_includedir}/QtOrganizer/QOrganizerTodo
+%{_includedir}/QtOrganizer/QOrganizerTodoOccurrence
+%{_includedir}/QtOrganizer/QOrganizerTodoProgress
+%{_includedir}/QtOrganizer/QOrganizerTodoTime
+%{_includedir}/QtPublishSubscribe/*.h
+%{_includedir}/QtPublishSubscribe/QValueSpace
+%{_includedir}/QtPublishSubscribe/QValueSpacePublisher
+%{_includedir}/QtPublishSubscribe/QValueSpaceSubscriber
+%{_includedir}/QtSensors/*.h
+%{_includedir}/QtSensors/QAccelerometer
+%{_includedir}/QtSensors/QAccelerometerFilter
+%{_includedir}/QtSensors/QAccelerometerReading
+%{_includedir}/QtSensors/QAmbientLightFilter
+%{_includedir}/QtSensors/QAmbientLightReading
+%{_includedir}/QtSensors/QAmbientLightSensor
+%{_includedir}/QtSensors/QCompass
+%{_includedir}/QtSensors/QCompassFilter
+%{_includedir}/QtSensors/QCompassReading
+%{_includedir}/QtSensors/QGyroscope
+%{_includedir}/QtSensors/QGyroscopeFilter
+%{_includedir}/QtSensors/QGyroscopeReading
+%{_includedir}/QtSensors/QLightFilter
+%{_includedir}/QtSensors/QLightReading
+%{_includedir}/QtSensors/QLightSensor
+%{_includedir}/QtSensors/QMagnetometer
+%{_includedir}/QtSensors/QMagnetometerFilter
+%{_includedir}/QtSensors/QMagnetometerReading
+%{_includedir}/QtSensors/QOrientationFilter
+%{_includedir}/QtSensors/QOrientationReading
+%{_includedir}/QtSensors/QOrientationSensor
+%{_includedir}/QtSensors/QProximityFilter
+%{_includedir}/QtSensors/QProximityReading
+%{_includedir}/QtSensors/QProximitySensor
+%{_includedir}/QtSensors/QRotationFilter
+%{_includedir}/QtSensors/QRotationReading
+%{_includedir}/QtSensors/QRotationSensor
+%{_includedir}/QtSensors/QSensor
+%{_includedir}/QtSensors/QSensorBackend
+%{_includedir}/QtSensors/QSensorBackendFactory
+%{_includedir}/QtSensors/QSensorChangesInterface
+%{_includedir}/QtSensors/QSensorFilter
+%{_includedir}/QtSensors/QSensorManager
+%{_includedir}/QtSensors/QSensorPluginInterface
+%{_includedir}/QtSensors/QSensorReading
+%{_includedir}/QtSensors/QTapFilter
+%{_includedir}/QtSensors/QTapReading
+%{_includedir}/QtSensors/QTapSensor
+%{_includedir}/QtServiceFramework/*.h
+%{_includedir}/QtServiceFramework/QAbstractSecuritySession
+%{_includedir}/QtServiceFramework/QRemoteServiceRegister
+%{_includedir}/QtServiceFramework/QService
+%{_includedir}/QtServiceFramework/QServiceContext
+%{_includedir}/QtServiceFramework/QServiceFilter
+%{_includedir}/QtServiceFramework/QServiceInterfaceDescriptor
+%{_includedir}/QtServiceFramework/QServiceManager
+%{_includedir}/QtServiceFramework/QServicePluginInterface
+%{_includedir}/QtSystemInfo/*.h
+%{_includedir}/QtSystemInfo/QSystemAlignedTimer
+%{_includedir}/QtSystemInfo/QSystemBatteryInfo
+%{_includedir}/QtSystemInfo/QSystemDeviceInfo
+%{_includedir}/QtSystemInfo/QSystemDisplayInfo
+%{_includedir}/QtSystemInfo/QSystemInfo
+%{_includedir}/QtSystemInfo/QSystemNetworkInfo
+%{_includedir}/QtSystemInfo/QSystemScreenSaver
+%{_includedir}/QtSystemInfo/QSystemStorageInfo
+%{_includedir}/QtVersit/*.h
+%{_includedir}/QtVersit/QVersitContactExporter
+%{_includedir}/QtVersit/QVersitContactExporterDetailHandler
+%{_includedir}/QtVersit/QVersitContactExporterDetailHandlerV2
+%{_includedir}/QtVersit/QVersitContactHandler
+%{_includedir}/QtVersit/QVersitContactHandlerFactory
+%{_includedir}/QtVersit/QVersitContactImporter
+%{_includedir}/QtVersit/QVersitContactImporterPropertyHandler
+%{_includedir}/QtVersit/QVersitContactImporterPropertyHandlerV2
+%{_includedir}/QtVersit/QVersitDefaultResourceHandler
+%{_includedir}/QtVersit/QVersitDocument
+%{_includedir}/QtVersit/QVersitProperty
+%{_includedir}/QtVersit/QVersitReader
+%{_includedir}/QtVersit/QVersitResourceHandler
+%{_includedir}/QtVersit/QVersitWriter
+%{_includedir}/QtVersitOrganizer/*.h
+%{_includedir}/QtVersitOrganizer/QVersitOrganizerExporter
+%{_includedir}/QtVersitOrganizer/QVersitOrganizerExporterDetailHandler
+%{_includedir}/QtVersitOrganizer/QVersitOrganizerHandler
+%{_includedir}/QtVersitOrganizer/QVersitOrganizerHandlerFactory
+%{_includedir}/QtVersitOrganizer/QVersitOrganizerImporter
+%{_includedir}/QtVersitOrganizer/QVersitOrganizerImporterPropertyHandler
+%{_includedir}/QtVersitOrganizer/QVersitTimeZoneHandler
+%{_libdir}/libQtConnectivity.prl
+%{_libdir}/libQtConnectivity.so
+%{_libdir}/libQtContacts.prl
+%{_libdir}/libQtContacts.so
+%{_libdir}/libQtFeedback.prl
+%{_libdir}/libQtFeedback.so
+%{_libdir}/libQtGallery.prl
+%{_libdir}/libQtGallery.so
+%{_libdir}/libQtLocation.prl
+%{_libdir}/libQtLocation.so
+%{_libdir}/libQtMessaging.prl
+%{_libdir}/libQtMessaging.so
+%{_libdir}/libQtMultimediaKit.prl
+%{_libdir}/libQtMultimediaKit.so
+%{_libdir}/libQtOrganizer.prl
+%{_libdir}/libQtOrganizer.so
+%{_libdir}/libQtPublishSubscribe.prl
+%{_libdir}/libQtPublishSubscribe.so
+%{_libdir}/libQtSensors.prl
+%{_libdir}/libQtSensors.so
+%{_libdir}/libQtServiceFramework.prl
+%{_libdir}/libQtServiceFramework.so
+%{_libdir}/libQtSystemInfo.prl
+%{_libdir}/libQtSystemInfo.so
+%{_libdir}/libQtVersit.prl
+%{_libdir}/libQtVersit.so
+%{_libdir}/libQtVersitOrganizer.prl
+%{_libdir}/libQtVersitOrganizer.so
+%{_libdir}/pkgconfig/QtConnectivity.pc
+%{_libdir}/pkgconfig/QtContacts.pc
+%{_libdir}/pkgconfig/QtFeedback.pc
+%{_libdir}/pkgconfig/QtGallery.pc
+%{_libdir}/pkgconfig/QtLocation.pc
+%{_libdir}/pkgconfig/QtMessaging.pc
+%{_libdir}/pkgconfig/QtMultimediaKit.pc
+%{_libdir}/pkgconfig/QtOrganizer.pc
+%{_libdir}/pkgconfig/QtPublishSubscribe.pc
+%{_libdir}/pkgconfig/QtSensors.pc
+%{_libdir}/pkgconfig/QtServiceFramework.pc
+%{_libdir}/pkgconfig/QtSystemInfo.pc
+%{_libdir}/pkgconfig/QtVersit.pc
+%{_libdir}/pkgconfig/QtVersitOrganizer.pc
+%{_datadir}/qt4/mkspecs/features/mobility.prf
+%{_datadir}/qt4/mkspecs/features/mobilityconfig.prf
+# << files devel
+
+%files -n libqtconnectivity1
+%defattr(-,root,root,-)
+# >> files libqtconnectivity1
+%{_libdir}/libQtConnectivity.so.*
+# << files libqtconnectivity1
+
+%files -n libqtcontacts1
+%defattr(-,root,root,-)
+# >> files libqtcontacts1
+%{_libdir}/libQtContacts.so.*
+%{_libdir}/qt4/plugins/contacts/libqtcontacts_serviceactionmanager.so
+# << files libqtcontacts1
+
+%files -n libqtfeedback1
+%defattr(-,root,root,-)
+# >> files libqtfeedback1
+%{_libdir}/libQtFeedback.so.*
+%{_libdir}/qt4/plugins/feedback/libqtfeedback_meegotouch.so
+%{_libdir}/qt4/plugins/feedback/libqtfeedback_mmk.so
+# << files libqtfeedback1
+
+%files -n libqtgallery1
+%defattr(-,root,root,-)
+# >> files libqtgallery1
+%{_libdir}/libQtGallery.so.*
+# << files libqtgallery1
+
+%files -n libqtlocation1
+%defattr(-,root,root,-)
+# >> files libqtlocation1
+%{_libdir}/libQtLocation.so.*
+%{_libdir}/qt4/plugins/geoservices/libqtgeoservices_nokia.so
+%{_libdir}/qt4/plugins/landmarks/libqtlandmarks_qsparql.so
+# << files libqtlocation1
+
+%files -n libqtmessaging1
+%defattr(-,root,root,-)
+# >> files libqtmessaging1
+%{_libdir}/libQtMessaging.so.*
+# << files libqtmessaging1
+
+%files -n libqtmultimediakit1
+%defattr(-,root,root,-)
+# >> files libqtmultimediakit1
+%{_libdir}/libQtMultimediaKit.so.*
+%{_libdir}/qt4/plugins/mediaservice/libqgstengine.so
+%{_libdir}/qt4/plugins/mediaservice/libqtmedia_v4lengine.so
+%{_libdir}/qt4/plugins/playlistformats/libqtmultimediakit_m3u.so
+%{_libdir}/qt4/plugins/audio/libqtmedia_pulse.so
+# << files libqtmultimediakit1
+
+%files -n libqtorganizer1
+%defattr(-,root,root,-)
+# >> files libqtorganizer1
+%{_libdir}/libQtOrganizer.so.*
+%{_libdir}/qt4/plugins/organizer/libqtorganizer_mkcal.so
+# << files libqtorganizer1
+
+%files -n libqtpublishsubscribe1
+%defattr(-,root,root,-)
+# >> files libqtpublishsubscribe1
+%{_libdir}/libQtPublishSubscribe.so.*
+# << files libqtpublishsubscribe1
+
+%files -n libqtsensors1
+%defattr(-,root,root,-)
+# >> files libqtsensors1
+%config %{_sysconfdir}/xdg/Nokia/Sensors.conf
+%{_libdir}/libQtSensors.so.*
+%{_libdir}/qt4/plugins/sensors/libqtsensors_generic.so
+%{_libdir}/qt4/plugins/sensors/libqtsensors_meego.so
+# << files libqtsensors1
+
+%files -n libqtserviceframework1
+%defattr(-,root,root,-)
+# >> files libqtserviceframework1
+%{_libdir}/libQtServiceFramework.so.*
+# << files libqtserviceframework1
+
+%files -n libqtsysteminfo1
+%defattr(-,root,root,-)
+# >> files libqtsysteminfo1
+%{_libdir}/libQtSystemInfo.so.*
+# << files libqtsysteminfo1
+
+%files -n libqtversit1
+%defattr(-,root,root,-)
+# >> files libqtversit1
+%{_libdir}/libQtVersit.so.*
+%{_libdir}/qt4/plugins/versit/libqtversit_backuphandler.so
+%{_libdir}/qt4/plugins/versit/libqtversit_vcardpreserver.so
+# << files libqtversit1
+
+%files -n libqtversitorganizer1
+%defattr(-,root,root,-)
+# >> files libqtversitorganizer1
+%{_libdir}/libQtVersitOrganizer.so.*
+# << files libqtversitorganizer1
+
+%files -n libdeclarative-contacts
+%defattr(-,root,root,-)
+# >> files libdeclarative-contacts
+%{_libdir}/qt4/imports/QtMobility/contacts/libdeclarative_contacts.so
+%{_libdir}/qt4/imports/QtMobility/contacts/qmldir
+# << files libdeclarative-contacts
+
+%files -n libdeclarative-feedback
+%defattr(-,root,root,-)
+# >> files libdeclarative-feedback
+%{_libdir}/qt4/imports/QtMobility/feedback/libdeclarative_feedback.so
+%{_libdir}/qt4/imports/QtMobility/feedback/qmldir
+# << files libdeclarative-feedback
+
+%files -n libdeclarative-gallery
+%defattr(-,root,root,-)
+# >> files libdeclarative-gallery
+%{_libdir}/qt4/imports/QtMobility/gallery/libdeclarative_gallery.so
+%{_libdir}/qt4/imports/QtMobility/gallery/qmldir
+# << files libdeclarative-gallery
+
+%files -n libdeclarative-location
+%defattr(-,root,root,-)
+# >> files libdeclarative-location
+%{_libdir}/qt4/imports/QtMobility/location/libdeclarative_location.so
+%{_libdir}/qt4/imports/QtMobility/location/qmldir
+# << files libdeclarative-location
+
+%files -n libdeclarative-messaging
+%defattr(-,root,root,-)
+# >> files libdeclarative-messaging
+%{_libdir}/qt4/imports/QtMobility/messaging/libdeclarative_messaging.so
+%{_libdir}/qt4/imports/QtMobility/messaging/qmldir
+# << files libdeclarative-messaging
+
+%files -n libdeclarative-multimedia
+%defattr(-,root,root,-)
+# >> files libdeclarative-multimedia
+%{_libdir}/qt4/imports/QtMultimediaKit/libdeclarative_multimedia.so
+%{_libdir}/qt4/imports/QtMultimediaKit/qmldir
+# << files libdeclarative-multimedia
+
+%files -n libdeclarative-organizer
+%defattr(-,root,root,-)
+# >> files libdeclarative-organizer
+%{_libdir}/qt4/imports/QtMobility/organizer/libdeclarative_organizer.so
+%{_libdir}/qt4/imports/QtMobility/organizer/qmldir
+# << files libdeclarative-organizer
+
+%files -n libdeclarative-publishsubscribe
+%defattr(-,root,root,-)
+# >> files libdeclarative-publishsubscribe
+%{_libdir}/qt4/imports/QtMobility/publishsubscribe/libdeclarative_publishsubscribe.so
+%{_libdir}/qt4/imports/QtMobility/publishsubscribe/qmldir
+# << files libdeclarative-publishsubscribe
+
+%files -n libdeclarative-sensors
+%defattr(-,root,root,-)
+# >> files libdeclarative-sensors
+%{_libdir}/qt4/imports/QtMobility/sensors/libdeclarative_sensors.so
+%{_libdir}/qt4/imports/QtMobility/sensors/qmldir
+# << files libdeclarative-sensors
+
+%files -n libdeclarative-serviceframework
+%defattr(-,root,root,-)
+# >> files libdeclarative-serviceframework
+%{_libdir}/qt4/imports/QtMobility/serviceframework/libdeclarative_serviceframework.so
+%{_libdir}/qt4/imports/QtMobility/serviceframework/qmldir
+# << files libdeclarative-serviceframework
+
+%files -n libdeclarative-systeminfo
+%defattr(-,root,root,-)
+# >> files libdeclarative-systeminfo
+%{_libdir}/qt4/imports/QtMobility/systeminfo/libdeclarative_systeminfo.so
+%{_libdir}/qt4/imports/QtMobility/systeminfo/qmldir
+# << files libdeclarative-systeminfo
+
+%files -n libdeclarative-connectivity
+%defattr(-,root,root,-)
+# >> files libdeclarative-connectivity
+%{_libdir}/qt4/imports/QtMobility/connectivity/libdeclarative_connectivity.so
+%{_libdir}/qt4/imports/QtMobility/connectivity/qmldir
+# << files libdeclarative-connectivity
+
+%files -n servicefw
+%defattr(-,root,root,-)
+# >> files servicefw
+%{_bindir}/servicefw
+# << files servicefw
+
+%files examples
+%defattr(-,root,root,-)
+# >> files examples
+%{_libdir}/qt4/plugins/sensors/libqtsensors_grueplugin.so
+%{_libdir}/qt4/plugins/serviceframework/libserviceframework_bluetoothtransferplugin.so
+%{_libdir}/qt4/plugins/serviceframework/libserviceframework_filemanagerplugin.so
+%{_libdir}/qt4/plugins/serviceframework/libserviceframework_landlinedialerservice.so
+%{_libdir}/qt4/plugins/serviceframework/libserviceframework_notesmanagerplugin.so
+%{_libdir}/qt4/plugins/serviceframework/libserviceframework_voipdialerservice.so
+%{_libdir}/qtmobility/demos/
+%{_libdir}/qtmobility/examples/
+# << files examples
+
+%files l10n
+%defattr(-,root,root,-)
+# >> files l10n
+%{_datadir}/qtmobility/translations/qtmobility_ar.qm
+%{_datadir}/qtmobility/translations/qtmobility_cs.qm
+%{_datadir}/qtmobility/translations/qtmobility_da.qm
+%{_datadir}/qtmobility/translations/qtmobility_de.qm
+%{_datadir}/qtmobility/translations/qtmobility_es.qm
+%{_datadir}/qtmobility/translations/qtmobility_fr.qm
+%{_datadir}/qtmobility/translations/qtmobility_he.qm
+%{_datadir}/qtmobility/translations/qtmobility_hu.qm
+%{_datadir}/qtmobility/translations/qtmobility_ja.qm
+%{_datadir}/qtmobility/translations/qtmobility_pl.qm
+%{_datadir}/qtmobility/translations/qtmobility_pt.qm
+%{_datadir}/qtmobility/translations/qtmobility_ru.qm
+%{_datadir}/qtmobility/translations/qtmobility_sk.qm
+%{_datadir}/qtmobility/translations/qtmobility_sl.qm
+%{_datadir}/qtmobility/translations/qtmobility_sv.qm
+#%{_datadir}/qtmobility/translations/qtmobility_uk.qm
+%{_datadir}/qtmobility/translations/qtmobility_zh_CN.qm
+%{_datadir}/qtmobility/translations/qtmobility_zh_TW.qm
+# << files l10n
+
diff --git a/src/meegoinstalls/qt-mobility.yaml b/src/meegoinstalls/qt-mobility.yaml
new file mode 100644
index 000000000..99c84c16c
--- /dev/null
+++ b/src/meegoinstalls/qt-mobility.yaml
@@ -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.
diff --git a/src/multimediakit/audio/audio.pri b/src/multimediakit/audio/audio.pri
new file mode 100644
index 000000000..19163d4fc
--- /dev/null
+++ b/src/multimediakit/audio/audio.pri
@@ -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
+ }
+ }
+}
diff --git a/src/multimediakit/audio/qaudio.cpp b/src/multimediakit/audio/qaudio.cpp
new file mode 100644
index 000000000..e823283f3
--- /dev/null
+++ b/src/multimediakit/audio/qaudio.cpp
@@ -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
+
diff --git a/src/multimediakit/audio/qaudio.h b/src/multimediakit/audio/qaudio.h
new file mode 100644
index 000000000..b8b585b69
--- /dev/null
+++ b/src/multimediakit/audio/qaudio.h
@@ -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
diff --git a/src/multimediakit/audio/qaudio_mac.cpp b/src/multimediakit/audio/qaudio_mac.cpp
new file mode 100644
index 000000000..a13b54c39
--- /dev/null
+++ b/src/multimediakit/audio/qaudio_mac.cpp
@@ -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
+
+
diff --git a/src/multimediakit/audio/qaudio_mac_p.h b/src/multimediakit/audio/qaudio_mac_p.h
new file mode 100644
index 000000000..bbd63e485
--- /dev/null
+++ b/src/multimediakit/audio/qaudio_mac_p.h
@@ -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
+
+
diff --git a/src/multimediakit/audio/qaudio_symbian_p.cpp b/src/multimediakit/audio/qaudio_symbian_p.cpp
new file mode 100644
index 000000000..08f329790
--- /dev/null
+++ b/src/multimediakit/audio/qaudio_symbian_p.cpp
@@ -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
+
+
diff --git a/src/multimediakit/audio/qaudio_symbian_p.h b/src/multimediakit/audio/qaudio_symbian_p.h
new file mode 100644
index 000000000..26f1a3f44
--- /dev/null
+++ b/src/multimediakit/audio/qaudio_symbian_p.h
@@ -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
diff --git a/src/multimediakit/audio/qaudiodevicefactory.cpp b/src/multimediakit/audio/qaudiodevicefactory.cpp
new file mode 100644
index 000000000..221b327dc
--- /dev/null
+++ b/src/multimediakit/audio/qaudiodevicefactory.cpp
@@ -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
+
diff --git a/src/multimediakit/audio/qaudiodevicefactory_p.h b/src/multimediakit/audio/qaudiodevicefactory_p.h
new file mode 100644
index 000000000..e162e04d6
--- /dev/null
+++ b/src/multimediakit/audio/qaudiodevicefactory_p.h
@@ -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
+
diff --git a/src/multimediakit/audio/qaudiodeviceinfo.cpp b/src/multimediakit/audio/qaudiodeviceinfo.cpp
new file mode 100644
index 000000000..44cc8fe79
--- /dev/null
+++ b/src/multimediakit/audio/qaudiodeviceinfo.cpp
@@ -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
+
diff --git a/src/multimediakit/audio/qaudiodeviceinfo.h b/src/multimediakit/audio/qaudiodeviceinfo.h
new file mode 100644
index 000000000..547093238
--- /dev/null
+++ b/src/multimediakit/audio/qaudiodeviceinfo.h
@@ -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
diff --git a/src/multimediakit/audio/qaudiodeviceinfo_alsa_p.cpp b/src/multimediakit/audio/qaudiodeviceinfo_alsa_p.cpp
new file mode 100644
index 000000000..bce7039ab
--- /dev/null
+++ b/src/multimediakit/audio/qaudiodeviceinfo_alsa_p.cpp
@@ -0,0 +1,535 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// INTERNAL USE ONLY: Do NOT use for any other purpose.
+//
+
+#include "qaudiodeviceinfo_alsa_p.h"
+
+#include <alsa/version.h>
+
+QT_BEGIN_NAMESPACE
+
+QAudioDeviceInfoInternal::QAudioDeviceInfoInternal(QByteArray dev, QAudio::Mode mode)
+{
+ handle = 0;
+
+ device = QLatin1String(dev);
+ this->mode = mode;
+
+ checkSurround();
+}
+
+QAudioDeviceInfoInternal::~QAudioDeviceInfoInternal()
+{
+ close();
+}
+
+bool QAudioDeviceInfoInternal::isFormatSupported(const QAudioFormat& format) const
+{
+ return testSettings(format);
+}
+
+QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const
+{
+ QAudioFormat nearest;
+ if(mode == QAudio::AudioOutput) {
+ nearest.setFrequency(44100);
+ nearest.setChannels(2);
+ nearest.setByteOrder(QAudioFormat::LittleEndian);
+ nearest.setSampleType(QAudioFormat::SignedInt);
+ nearest.setSampleSize(16);
+ nearest.setCodec(QLatin1String("audio/pcm"));
+ } else {
+ nearest.setFrequency(8000);
+ nearest.setChannels(1);
+ nearest.setSampleType(QAudioFormat::UnSignedInt);
+ nearest.setSampleSize(8);
+ nearest.setCodec(QLatin1String("audio/pcm"));
+ if(!testSettings(nearest)) {
+ nearest.setChannels(2);
+ nearest.setSampleSize(16);
+ nearest.setSampleType(QAudioFormat::SignedInt);
+ }
+ }
+ return nearest;
+}
+
+QString QAudioDeviceInfoInternal::deviceName() const
+{
+ return device;
+}
+
+QStringList QAudioDeviceInfoInternal::supportedCodecs()
+{
+ updateLists();
+ return codecz;
+}
+
+QList<int> QAudioDeviceInfoInternal::supportedSampleRates()
+{
+ updateLists();
+ return freqz;
+}
+
+QList<int> QAudioDeviceInfoInternal::supportedChannelCounts()
+{
+ updateLists();
+ return channelz;
+}
+
+QList<int> QAudioDeviceInfoInternal::supportedSampleSizes()
+{
+ updateLists();
+ return sizez;
+}
+
+QList<QAudioFormat::Endian> QAudioDeviceInfoInternal::supportedByteOrders()
+{
+ updateLists();
+ return byteOrderz;
+}
+
+QList<QAudioFormat::SampleType> QAudioDeviceInfoInternal::supportedSampleTypes()
+{
+ updateLists();
+ return typez;
+}
+
+bool QAudioDeviceInfoInternal::open()
+{
+ int err = 0;
+ QString dev = device;
+ QList<QByteArray> devices = availableDevices(mode);
+
+ if(dev.compare(QLatin1String("default")) == 0) {
+#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
+ if (devices.size() > 0)
+ dev = QLatin1String(devices.first().constData());
+ else
+ return false;
+#else
+ dev = QLatin1String("hw:0,0");
+#endif
+ } else {
+#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
+ dev = device;
+#else
+ int idx = 0;
+ char *name;
+
+ QString shortName = device.mid(device.indexOf(QLatin1String("="),0)+1);
+
+ while(snd_card_get_name(idx,&name) == 0) {
+ if(dev.contains(QLatin1String(name)))
+ break;
+ idx++;
+ }
+ dev = QString(QLatin1String("hw:%1,0")).arg(idx);
+#endif
+ }
+ if(mode == QAudio::AudioOutput) {
+ err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0);
+ } else {
+ err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0);
+ }
+ if(err < 0) {
+ handle = 0;
+ return false;
+ }
+ return true;
+}
+
+void QAudioDeviceInfoInternal::close()
+{
+ if(handle)
+ snd_pcm_close(handle);
+ handle = 0;
+}
+
+bool QAudioDeviceInfoInternal::testSettings(const QAudioFormat& format) const
+{
+ // Set nearest to closest settings that do work.
+ // See if what is in settings will work (return value).
+ int err = 0;
+ snd_pcm_t* handle;
+ snd_pcm_hw_params_t *params;
+ QString dev = device;
+
+ QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput);
+
+ if(dev.compare(QLatin1String("default")) == 0) {
+#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
+ dev = QLatin1String(devices.first().constData());
+#else
+ dev = QLatin1String("hw:0,0");
+#endif
+ } else {
+#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
+ dev = device;
+#else
+ int idx = 0;
+ char *name;
+
+ QString shortName = device.mid(device.indexOf(QLatin1String("="),0)+1);
+
+ while(snd_card_get_name(idx,&name) == 0) {
+ if(shortName.compare(QLatin1String(name)) == 0)
+ break;
+ idx++;
+ }
+ dev = QString(QLatin1String("hw:%1,0")).arg(idx);
+#endif
+ }
+ if(mode == QAudio::AudioOutput) {
+ err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0);
+ } else {
+ err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0);
+ }
+ if(err < 0) {
+ handle = 0;
+ return false;
+ }
+
+ bool testChannel = false;
+ bool testCodec = false;
+ bool testFreq = false;
+ bool testType = false;
+ bool testSize = false;
+
+ int dir = 0;
+
+ snd_pcm_nonblock( handle, 0 );
+ snd_pcm_hw_params_alloca( &params );
+ snd_pcm_hw_params_any( handle, params );
+
+ // set the values!
+ snd_pcm_hw_params_set_channels(handle,params,format.channels());
+ snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir);
+
+ err = -1;
+
+ switch(format.sampleSize()) {
+ case 8:
+ if(format.sampleType() == QAudioFormat::SignedInt)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8);
+ else if(format.sampleType() == QAudioFormat::UnSignedInt)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8);
+ break;
+ case 16:
+ if(format.sampleType() == QAudioFormat::SignedInt) {
+ if(format.byteOrder() == QAudioFormat::LittleEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
+ else if(format.byteOrder() == QAudioFormat::BigEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE);
+ } else if(format.sampleType() == QAudioFormat::UnSignedInt) {
+ if(format.byteOrder() == QAudioFormat::LittleEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE);
+ else if(format.byteOrder() == QAudioFormat::BigEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE);
+ }
+ break;
+ case 32:
+ if(format.sampleType() == QAudioFormat::SignedInt) {
+ if(format.byteOrder() == QAudioFormat::LittleEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE);
+ else if(format.byteOrder() == QAudioFormat::BigEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE);
+ } else if(format.sampleType() == QAudioFormat::UnSignedInt) {
+ if(format.byteOrder() == QAudioFormat::LittleEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE);
+ else if(format.byteOrder() == QAudioFormat::BigEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE);
+ }
+ }
+
+ // For now, just accept only audio/pcm codec
+ if(!format.codec().startsWith(QLatin1String("audio/pcm"))) {
+ err=-1;
+ } else
+ testCodec = true;
+
+ if(err>=0 && format.channels() != -1) {
+ err = snd_pcm_hw_params_test_channels(handle,params,format.channels());
+ if(err>=0)
+ err = snd_pcm_hw_params_set_channels(handle,params,format.channels());
+ if(err>=0)
+ testChannel = true;
+ }
+
+ if(err>=0 && format.frequency() != -1) {
+ err = snd_pcm_hw_params_test_rate(handle,params,format.frequency(),0);
+ if(err>=0)
+ err = snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir);
+ if(err>=0)
+ testFreq = true;
+ }
+
+ if((err>=0 && format.sampleSize() != -1) &&
+ (format.sampleType() != QAudioFormat::Unknown)) {
+ switch(format.sampleSize()) {
+ case 8:
+ if(format.sampleType() == QAudioFormat::SignedInt)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8);
+ else if(format.sampleType() == QAudioFormat::UnSignedInt)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8);
+ break;
+ case 16:
+ if(format.sampleType() == QAudioFormat::SignedInt) {
+ if(format.byteOrder() == QAudioFormat::LittleEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
+ else if(format.byteOrder() == QAudioFormat::BigEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE);
+ } else if(format.sampleType() == QAudioFormat::UnSignedInt) {
+ if(format.byteOrder() == QAudioFormat::LittleEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE);
+ else if(format.byteOrder() == QAudioFormat::BigEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE);
+ }
+ break;
+ case 32:
+ if(format.sampleType() == QAudioFormat::SignedInt) {
+ if(format.byteOrder() == QAudioFormat::LittleEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE);
+ else if(format.byteOrder() == QAudioFormat::BigEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE);
+ } else if(format.sampleType() == QAudioFormat::UnSignedInt) {
+ if(format.byteOrder() == QAudioFormat::LittleEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE);
+ else if(format.byteOrder() == QAudioFormat::BigEndian)
+ err = snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE);
+ }
+ }
+ if(err>=0) {
+ testSize = true;
+ testType = true;
+ }
+ }
+ if(err>=0)
+ err = snd_pcm_hw_params(handle, params);
+
+ if(err == 0) {
+ // settings work
+ // close()
+ if(handle)
+ snd_pcm_close(handle);
+ return true;
+ }
+ if(handle)
+ snd_pcm_close(handle);
+
+ return false;
+}
+
+void QAudioDeviceInfoInternal::updateLists()
+{
+ // redo all lists based on current settings
+ freqz.clear();
+ channelz.clear();
+ sizez.clear();
+ byteOrderz.clear();
+ typez.clear();
+ codecz.clear();
+
+ if(!handle)
+ open();
+
+ if(!handle)
+ return;
+
+ for(int i=0; i<(int)MAX_SAMPLE_RATES; i++) {
+ //if(snd_pcm_hw_params_test_rate(handle, params, SAMPLE_RATES[i], dir) == 0)
+ freqz.append(SAMPLE_RATES[i]);
+ }
+ channelz.append(1);
+ channelz.append(2);
+ if (surround40) channelz.append(4);
+ if (surround51) channelz.append(6);
+ if (surround71) channelz.append(8);
+ sizez.append(8);
+ sizez.append(16);
+ sizez.append(32);
+ byteOrderz.append(QAudioFormat::LittleEndian);
+ byteOrderz.append(QAudioFormat::BigEndian);
+ typez.append(QAudioFormat::SignedInt);
+ typez.append(QAudioFormat::UnSignedInt);
+ typez.append(QAudioFormat::Float);
+ codecz.append(QLatin1String("audio/pcm"));
+ close();
+}
+
+QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode)
+{
+ QList<QByteArray> allDevices;
+ QList<QByteArray> devices;
+ QByteArray filter;
+
+#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
+ // Create a list of all current audio devices that support mode
+ void **hints, **n;
+ char *name, *descr, *io;
+
+ if(snd_device_name_hint(-1, "pcm", &hints) < 0) {
+ qWarning() << "no alsa devices available";
+ return devices;
+ }
+ n = hints;
+
+ if(mode == QAudio::AudioInput) {
+ filter = "Input";
+ } else {
+ filter = "Output";
+ }
+
+ while (*n != NULL) {
+ name = snd_device_name_get_hint(*n, "NAME");
+ if (name != 0 && qstrcmp(name, "null") != 0) {
+ descr = snd_device_name_get_hint(*n, "DESC");
+ io = snd_device_name_get_hint(*n, "IOID");
+
+ if ((descr != NULL) && ((io == NULL) || (io == filter))) {
+ QString deviceName = QLatin1String(name);
+ QString deviceDescription = QLatin1String(descr);
+ allDevices.append(deviceName.toLocal8Bit().constData());
+ if (deviceDescription.contains(QLatin1String("Default Audio Device")))
+ devices.append(deviceName.toLocal8Bit().constData());
+ }
+
+ free(name);
+ if (descr != NULL)
+ free(descr);
+ if (io != NULL)
+ free(io);
+ }
+ ++n;
+ }
+ snd_device_name_free_hint(hints);
+
+ if(devices.size() > 0) {
+ devices.append("default");
+ }
+#else
+ int idx = 0;
+ char* name;
+
+ while(snd_card_get_name(idx,&name) == 0) {
+ devices.append(name);
+ idx++;
+ }
+ if (idx > 0)
+ devices.append("default");
+#endif
+#if (!defined(Q_WS_MAEMO_5) && !defined(Q_WS_MAEMO_6))
+ if (devices.size() == 0 && allDevices.size() > 0)
+ return allDevices;
+#endif
+
+ return devices;
+}
+
+QByteArray QAudioDeviceInfoInternal::defaultInputDevice()
+{
+ QList<QByteArray> devices = availableDevices(QAudio::AudioInput);
+ if(devices.size() == 0)
+ return QByteArray();
+
+ return devices.first();
+}
+
+QByteArray QAudioDeviceInfoInternal::defaultOutputDevice()
+{
+ QList<QByteArray> devices = availableDevices(QAudio::AudioOutput);
+ if(devices.size() == 0)
+ return QByteArray();
+
+ return devices.first();
+}
+
+void QAudioDeviceInfoInternal::checkSurround()
+{
+ QList<QByteArray> devices;
+ surround40 = false;
+ surround51 = false;
+ surround71 = false;
+
+ void **hints, **n;
+ char *name, *descr, *io;
+
+ if(snd_device_name_hint(-1, "pcm", &hints) < 0)
+ return;
+
+ n = hints;
+
+ while (*n != NULL) {
+ name = snd_device_name_get_hint(*n, "NAME");
+ descr = snd_device_name_get_hint(*n, "DESC");
+ io = snd_device_name_get_hint(*n, "IOID");
+ if((name != NULL) && (descr != NULL)) {
+ QString deviceName = QLatin1String(name);
+ if (mode == QAudio::AudioOutput) {
+ if(deviceName.contains(QLatin1String("surround40")))
+ surround40 = true;
+ if(deviceName.contains(QLatin1String("surround51")))
+ surround51 = true;
+ if(deviceName.contains(QLatin1String("surround71")))
+ surround71 = true;
+ }
+ }
+ if(name != NULL)
+ free(name);
+ if(descr != NULL)
+ free(descr);
+ if(io != NULL)
+ free(io);
+ ++n;
+ }
+ snd_device_name_free_hint(hints);
+}
+
+QT_END_NAMESPACE
diff --git a/src/multimediakit/audio/qaudiodeviceinfo_alsa_p.h b/src/multimediakit/audio/qaudiodeviceinfo_alsa_p.h
new file mode 100644
index 000000000..02a633bea
--- /dev/null
+++ b/src/multimediakit/audio/qaudiodeviceinfo_alsa_p.h
@@ -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
+
diff --git a/src/multimediakit/audio/qaudiodeviceinfo_mac_p.cpp b/src/multimediakit/audio/qaudiodeviceinfo_mac_p.cpp
new file mode 100644
index 000000000..ee6660c6e
--- /dev/null
+++ b/src/multimediakit/audio/qaudiodeviceinfo_mac_p.cpp
@@ -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
+
diff --git a/src/multimediakit/audio/qaudiodeviceinfo_mac_p.h b/src/multimediakit/audio/qaudiodeviceinfo_mac_p.h
new file mode 100644
index 000000000..5cd5deae3
--- /dev/null
+++ b/src/multimediakit/audio/qaudiodeviceinfo_mac_p.h
@@ -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
diff --git a/src/multimediakit/audio/qaudiodeviceinfo_symbian_p.cpp b/src/multimediakit/audio/qaudiodeviceinfo_symbian_p.cpp
new file mode 100644
index 000000000..a4cec57ed
--- /dev/null
+++ b/src/multimediakit/audio/qaudiodeviceinfo_symbian_p.cpp
@@ -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"
+
diff --git a/src/multimediakit/audio/qaudiodeviceinfo_symbian_p.h b/src/multimediakit/audio/qaudiodeviceinfo_symbian_p.h
new file mode 100644
index 000000000..487afd50e
--- /dev/null
+++ b/src/multimediakit/audio/qaudiodeviceinfo_symbian_p.h
@@ -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
diff --git a/src/multimediakit/audio/qaudiodeviceinfo_win32_p.cpp b/src/multimediakit/audio/qaudiodeviceinfo_win32_p.cpp
new file mode 100644
index 000000000..0f29bf5bc
--- /dev/null
+++ b/src/multimediakit/audio/qaudiodeviceinfo_win32_p.cpp
@@ -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
diff --git a/src/multimediakit/audio/qaudiodeviceinfo_win32_p.h b/src/multimediakit/audio/qaudiodeviceinfo_win32_p.h
new file mode 100644
index 000000000..78f3d7fad
--- /dev/null
+++ b/src/multimediakit/audio/qaudiodeviceinfo_win32_p.h
@@ -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
diff --git a/src/multimediakit/audio/qaudioformat.cpp b/src/multimediakit/audio/qaudioformat.cpp
new file mode 100644
index 000000000..3afba7ee4
--- /dev/null
+++ b/src/multimediakit/audio/qaudioformat.cpp
@@ -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
+
diff --git a/src/multimediakit/audio/qaudioformat.h b/src/multimediakit/audio/qaudioformat.h
new file mode 100644
index 000000000..b7d0a4027
--- /dev/null
+++ b/src/multimediakit/audio/qaudioformat.h
@@ -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
diff --git a/src/multimediakit/audio/qaudioinput.cpp b/src/multimediakit/audio/qaudioinput.cpp
new file mode 100644
index 000000000..c20ea41c2
--- /dev/null
+++ b/src/multimediakit/audio/qaudioinput.cpp
@@ -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"
+
diff --git a/src/multimediakit/audio/qaudioinput.h b/src/multimediakit/audio/qaudioinput.h
new file mode 100644
index 000000000..c1b866eb6
--- /dev/null
+++ b/src/multimediakit/audio/qaudioinput.h
@@ -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
diff --git a/src/multimediakit/audio/qaudioinput_alsa_p.cpp b/src/multimediakit/audio/qaudioinput_alsa_p.cpp
new file mode 100644
index 000000000..e7a04599f
--- /dev/null
+++ b/src/multimediakit/audio/qaudioinput_alsa_p.cpp
@@ -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"
diff --git a/src/multimediakit/audio/qaudioinput_alsa_p.h b/src/multimediakit/audio/qaudioinput_alsa_p.h
new file mode 100644
index 000000000..a6f371642
--- /dev/null
+++ b/src/multimediakit/audio/qaudioinput_alsa_p.h
@@ -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
diff --git a/src/multimediakit/audio/qaudioinput_mac_p.cpp b/src/multimediakit/audio/qaudioinput_mac_p.cpp
new file mode 100644
index 000000000..8c3bbe600
--- /dev/null
+++ b/src/multimediakit/audio/qaudioinput_mac_p.cpp
@@ -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"
diff --git a/src/multimediakit/audio/qaudioinput_mac_p.h b/src/multimediakit/audio/qaudioinput_mac_p.h
new file mode 100644
index 000000000..61b6edf75
--- /dev/null
+++ b/src/multimediakit/audio/qaudioinput_mac_p.h
@@ -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
diff --git a/src/multimediakit/audio/qaudioinput_symbian_p.cpp b/src/multimediakit/audio/qaudioinput_symbian_p.cpp
new file mode 100644
index 000000000..fe250cf32
--- /dev/null
+++ b/src/multimediakit/audio/qaudioinput_symbian_p.cpp
@@ -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"
diff --git a/src/multimediakit/audio/qaudioinput_symbian_p.h b/src/multimediakit/audio/qaudioinput_symbian_p.h
new file mode 100644
index 000000000..9f6128390
--- /dev/null
+++ b/src/multimediakit/audio/qaudioinput_symbian_p.h
@@ -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
diff --git a/src/multimediakit/audio/qaudioinput_win32_p.cpp b/src/multimediakit/audio/qaudioinput_win32_p.cpp
new file mode 100644
index 000000000..c258a2cbf
--- /dev/null
+++ b/src/multimediakit/audio/qaudioinput_win32_p.cpp
@@ -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"
+
diff --git a/src/multimediakit/audio/qaudioinput_win32_p.h b/src/multimediakit/audio/qaudioinput_win32_p.h
new file mode 100644
index 000000000..e1972cd66
--- /dev/null
+++ b/src/multimediakit/audio/qaudioinput_win32_p.h
@@ -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
diff --git a/src/multimediakit/audio/qaudiooutput.cpp b/src/multimediakit/audio/qaudiooutput.cpp
new file mode 100644
index 000000000..afde7ff14
--- /dev/null
+++ b/src/multimediakit/audio/qaudiooutput.cpp
@@ -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"
diff --git a/src/multimediakit/audio/qaudiooutput.h b/src/multimediakit/audio/qaudiooutput.h
new file mode 100644
index 000000000..68b0eb2d6
--- /dev/null
+++ b/src/multimediakit/audio/qaudiooutput.h
@@ -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
diff --git a/src/multimediakit/audio/qaudiooutput_alsa_p.cpp b/src/multimediakit/audio/qaudiooutput_alsa_p.cpp
new file mode 100644
index 000000000..3a0c7e344
--- /dev/null
+++ b/src/multimediakit/audio/qaudiooutput_alsa_p.cpp
@@ -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"
diff --git a/src/multimediakit/audio/qaudiooutput_alsa_p.h b/src/multimediakit/audio/qaudiooutput_alsa_p.h
new file mode 100644
index 000000000..51f3fee5e
--- /dev/null
+++ b/src/multimediakit/audio/qaudiooutput_alsa_p.h
@@ -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
diff --git a/src/multimediakit/audio/qaudiooutput_mac_p.cpp b/src/multimediakit/audio/qaudiooutput_mac_p.cpp
new file mode 100644
index 000000000..fcaa3cbd2
--- /dev/null
+++ b/src/multimediakit/audio/qaudiooutput_mac_p.cpp
@@ -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"
diff --git a/src/multimediakit/audio/qaudiooutput_mac_p.h b/src/multimediakit/audio/qaudiooutput_mac_p.h
new file mode 100644
index 000000000..5524621f9
--- /dev/null
+++ b/src/multimediakit/audio/qaudiooutput_mac_p.h
@@ -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
diff --git a/src/multimediakit/audio/qaudiooutput_symbian_p.cpp b/src/multimediakit/audio/qaudiooutput_symbian_p.cpp
new file mode 100644
index 000000000..3a1bc2424
--- /dev/null
+++ b/src/multimediakit/audio/qaudiooutput_symbian_p.cpp
@@ -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"
diff --git a/src/multimediakit/audio/qaudiooutput_symbian_p.h b/src/multimediakit/audio/qaudiooutput_symbian_p.h
new file mode 100644
index 000000000..2e2fd5db2
--- /dev/null
+++ b/src/multimediakit/audio/qaudiooutput_symbian_p.h
@@ -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
diff --git a/src/multimediakit/audio/qaudiooutput_win32_p.cpp b/src/multimediakit/audio/qaudiooutput_win32_p.cpp
new file mode 100644
index 000000000..3f465de37
--- /dev/null
+++ b/src/multimediakit/audio/qaudiooutput_win32_p.cpp
@@ -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"
diff --git a/src/multimediakit/audio/qaudiooutput_win32_p.h b/src/multimediakit/audio/qaudiooutput_win32_p.h
new file mode 100644
index 000000000..53cfe71f7
--- /dev/null
+++ b/src/multimediakit/audio/qaudiooutput_win32_p.h
@@ -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
diff --git a/src/multimediakit/audio/qaudiopluginloader.cpp b/src/multimediakit/audio/qaudiopluginloader.cpp
new file mode 100644
index 000000000..fc83f7a63
--- /dev/null
+++ b/src/multimediakit/audio/qaudiopluginloader.cpp
@@ -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
+
diff --git a/src/multimediakit/audio/qaudiopluginloader_p.h b/src/multimediakit/audio/qaudiopluginloader_p.h
new file mode 100644
index 000000000..6d5fef313
--- /dev/null
+++ b/src/multimediakit/audio/qaudiopluginloader_p.h
@@ -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
diff --git a/src/multimediakit/audio/qaudiosystem.cpp b/src/multimediakit/audio/qaudiosystem.cpp
new file mode 100644
index 000000000..5b2b0c3be
--- /dev/null
+++ b/src/multimediakit/audio/qaudiosystem.cpp
@@ -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"
diff --git a/src/multimediakit/audio/qaudiosystem.h b/src/multimediakit/audio/qaudiosystem.h
new file mode 100644
index 000000000..f2875a5cd
--- /dev/null
+++ b/src/multimediakit/audio/qaudiosystem.h
@@ -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
diff --git a/src/multimediakit/audio/qaudiosystemplugin.cpp b/src/multimediakit/audio/qaudiosystemplugin.cpp
new file mode 100644
index 000000000..3744b6f88
--- /dev/null
+++ b/src/multimediakit/audio/qaudiosystemplugin.cpp
@@ -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"
diff --git a/src/multimediakit/audio/qaudiosystemplugin.h b/src/multimediakit/audio/qaudiosystemplugin.h
new file mode 100644
index 000000000..740e1e427
--- /dev/null
+++ b/src/multimediakit/audio/qaudiosystemplugin.h
@@ -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
diff --git a/src/multimediakit/effects/effects.pri b/src/multimediakit/effects/effects.pri
new file mode 100644
index 000000000..911bd9b62
--- /dev/null
+++ b/src/multimediakit/effects/effects.pri
@@ -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 +=
diff --git a/src/multimediakit/effects/qsamplecache_p.cpp b/src/multimediakit/effects/qsamplecache_p.cpp
new file mode 100644
index 000000000..d86aa2493
--- /dev/null
+++ b/src/multimediakit/effects/qsamplecache_p.cpp
@@ -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"
diff --git a/src/multimediakit/effects/qsamplecache_p.h b/src/multimediakit/effects/qsamplecache_p.h
new file mode 100644
index 000000000..327f3bd8e
--- /dev/null
+++ b/src/multimediakit/effects/qsamplecache_p.h
@@ -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
diff --git a/src/multimediakit/effects/qsoundeffect.cpp b/src/multimediakit/effects/qsoundeffect.cpp
new file mode 100644
index 000000000..4d489871d
--- /dev/null
+++ b/src/multimediakit/effects/qsoundeffect.cpp
@@ -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"
diff --git a/src/multimediakit/effects/qsoundeffect_p.h b/src/multimediakit/effects/qsoundeffect_p.h
new file mode 100644
index 000000000..7f6b24a00
--- /dev/null
+++ b/src/multimediakit/effects/qsoundeffect_p.h
@@ -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
diff --git a/src/multimediakit/effects/qsoundeffect_pulse_p.cpp b/src/multimediakit/effects/qsoundeffect_pulse_p.cpp
new file mode 100644
index 000000000..f6abf140e
--- /dev/null
+++ b/src/multimediakit/effects/qsoundeffect_pulse_p.cpp
@@ -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"
diff --git a/src/multimediakit/effects/qsoundeffect_pulse_p.h b/src/multimediakit/effects/qsoundeffect_pulse_p.h
new file mode 100644
index 000000000..d07e9b184
--- /dev/null
+++ b/src/multimediakit/effects/qsoundeffect_pulse_p.h
@@ -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
diff --git a/src/multimediakit/effects/qsoundeffect_qmedia_p.cpp b/src/multimediakit/effects/qsoundeffect_qmedia_p.cpp
new file mode 100644
index 000000000..242997191
--- /dev/null
+++ b/src/multimediakit/effects/qsoundeffect_qmedia_p.cpp
@@ -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"
diff --git a/src/multimediakit/effects/qsoundeffect_qmedia_p.h b/src/multimediakit/effects/qsoundeffect_qmedia_p.h
new file mode 100644
index 000000000..7351350e6
--- /dev/null
+++ b/src/multimediakit/effects/qsoundeffect_qmedia_p.h
@@ -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
diff --git a/src/multimediakit/effects/qsoundeffect_qsound_p.cpp b/src/multimediakit/effects/qsoundeffect_qsound_p.cpp
new file mode 100644
index 000000000..7a753d18c
--- /dev/null
+++ b/src/multimediakit/effects/qsoundeffect_qsound_p.cpp
@@ -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"
diff --git a/src/multimediakit/effects/qsoundeffect_qsound_p.h b/src/multimediakit/effects/qsoundeffect_qsound_p.h
new file mode 100644
index 000000000..2a7691b23
--- /dev/null
+++ b/src/multimediakit/effects/qsoundeffect_qsound_p.h
@@ -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
diff --git a/src/multimediakit/effects/qwavedecoder_p.cpp b/src/multimediakit/effects/qwavedecoder_p.cpp
new file mode 100644
index 000000000..992bb0996
--- /dev/null
+++ b/src/multimediakit/effects/qwavedecoder_p.cpp
@@ -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"
diff --git a/src/multimediakit/effects/qwavedecoder_p.h b/src/multimediakit/effects/qwavedecoder_p.h
new file mode 100644
index 000000000..90dfda811
--- /dev/null
+++ b/src/multimediakit/effects/qwavedecoder_p.h
@@ -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
diff --git a/src/multimediakit/multimediakit.pro b/src/multimediakit/multimediakit.pro
new file mode 100644
index 000000000..57d5af5f2
--- /dev/null
+++ b/src/multimediakit/multimediakit.pro
@@ -0,0 +1,217 @@
+load(qt_module)
+
+# distinct from QtMultimedia
+TARGET = QtMultimediaKit
+QPRO_PWD = $$PWD
+QT = core network
+
+CONFIG += module
+MODULE_PRI += ../../modules/qt_multimediakit.pri
+
+contains(QT_CONFIG, opengl) | contains(QT_CONFIG, opengles2): !symbian {
+ QT += opengl
+} else {
+ DEFINES += QT_NO_OPENGL
+}
+
+!static:DEFINES += QT_MAKEDLL
+DEFINES += QT_BUILD_MULTIMEDIA_LIB
+
+load(qt_module_config)
+
+HEADERS += qtmultimediakitversion.h
+
+PRIVATE_HEADERS += \
+ qmediacontrol_p.h \
+ qmediaobject_p.h \
+ qmediaservice_p.h \
+ qmediaplaylist_p.h \
+ qmediaplaylistprovider_p.h \
+ qmediaimageviewerservice_p.h \
+ qvideowidget_p.h \
+ qmediapluginloader_p.h \
+ qpaintervideosurface_p.h \
+ qvideosurfaceoutput_p.h
+
+PUBLIC_HEADERS += \
+ qmediacontrol.h \
+ qmediaobject.h \
+ qmediaservice.h \
+ qmediabindableinterface.h \
+ qlocalmediaplaylistprovider.h \
+ qmediaimageviewer.h \
+ qmediaplayer.h \
+ qmediaplayercontrol.h \
+ qmediaplaylist.h \
+ qmediaplaylistnavigator.h \
+ qmediaplaylistprovider.h \
+ qmediaplaylistioplugin.h \
+ qmediacontent.h \
+ qmediaresource.h \
+ qmediarecorder.h \
+ qmediaencodersettings.h \
+ qmediarecordercontrol.h \
+ qmediaserviceprovider.h \
+ qmediaserviceproviderplugin.h \
+ qmetadatareadercontrol.h \
+ qmetadatawritercontrol.h \
+ qmediastreamscontrol.h \
+ qradiotuner.h \
+ qradiotunercontrol.h \
+ qtmedianamespace.h \
+ qvideowidget.h \
+ qvideowindowcontrol.h \
+ qvideowidgetcontrol.h \
+ qaudioencodercontrol.h \
+ qvideoencodercontrol.h \
+ qimageencodercontrol.h \
+ qaudiocapturesource.h \
+ qmediacontainercontrol.h \
+ qmediaplaylistcontrol.h \
+ qmediaplaylistsourcecontrol.h \
+ qaudioendpointselector.h \
+ qvideodevicecontrol.h \
+ qgraphicsvideoitem.h \
+ qvideorenderercontrol.h \
+ qmediatimerange.h \
+ qmedianetworkaccesscontrol.h \
+ qmediaenumdebug.h
+
+SOURCES += qmediacontrol.cpp \
+ qmediaobject.cpp \
+ qmediaservice.cpp \
+ qmediabindableinterface.cpp \
+ qlocalmediaplaylistprovider.cpp \
+ qmediaimageviewer.cpp \
+ qmediaimageviewerservice.cpp \
+ qmediaplayer.cpp \
+ qmediaplayercontrol.cpp \
+ qmediaplaylist.cpp \
+ qmediaplaylistioplugin.cpp \
+ qmediaplaylistnavigator.cpp \
+ qmediaplaylistprovider.cpp \
+ qmediarecorder.cpp \
+ qmediaencodersettings.cpp \
+ qmediarecordercontrol.cpp \
+ qmediacontent.cpp \
+ qmediaresource.cpp \
+ qmediaserviceprovider.cpp \
+ qmetadatareadercontrol.cpp \
+ qmetadatawritercontrol.cpp \
+ qmediastreamscontrol.cpp \
+ qradiotuner.cpp \
+ qradiotunercontrol.cpp \
+ qvideowidget.cpp \
+ qvideowindowcontrol.cpp \
+ qvideowidgetcontrol.cpp \
+ qaudioencodercontrol.cpp \
+ qvideoencodercontrol.cpp \
+ qimageencodercontrol.cpp \
+ qaudiocapturesource.cpp \
+ qmediacontainercontrol.cpp \
+ qmediaplaylistcontrol.cpp \
+ qmediaplaylistsourcecontrol.cpp \
+ qaudioendpointselector.cpp \
+ qvideodevicecontrol.cpp \
+ qmediapluginloader.cpp \
+ qpaintervideosurface.cpp \
+ qvideorenderercontrol.cpp \
+ qmediatimerange.cpp \
+ qmedianetworkaccesscontrol.cpp \
+ qvideosurfaceoutput.cpp
+
+#Camera
+PUBLIC_HEADERS += \
+ qcamera.h \
+ qcameraviewfinder.h \
+ qcameraimagecapture.h \
+ qcameraimagecapturecontrol.h \
+ qcameraexposure.h \
+ qcamerafocus.h \
+ qcameraimageprocessing.h \
+ qcameracontrol.h \
+ qcameralockscontrol.h \
+ qcameraexposurecontrol.h \
+ qcamerafocuscontrol.h \
+ qcameraflashcontrol.h \
+ qcameraimageprocessingcontrol.h \
+ qcameracapturedestinationcontrol.h \
+ qcameracapturebufferformatcontrol.h
+
+SOURCES += \
+ qcamera.cpp \
+ qcameraviewfinder.cpp \
+ qcameraexposure.cpp \
+ qcamerafocus.cpp \
+ qcameraimageprocessing.cpp \
+ qcameraimagecapture.cpp \
+ qcameraimagecapturecontrol.cpp \
+ qcameracontrol.cpp \
+ qcameralockscontrol.cpp \
+ qcameraexposurecontrol.cpp \
+ qcamerafocuscontrol.cpp \
+ qcameraflashcontrol.cpp \
+ qcameraimageprocessingcontrol.cpp \
+ qcameracapturedestinationcontrol.cpp \
+ qcameracapturebufferformatcontrol.cpp
+
+include(audio/audio.pri)
+include(video/video.pri)
+include(effects/effects.pri)
+
+mac {
+!simulator {
+ HEADERS += qpaintervideosurface_mac_p.h
+ OBJECTIVE_SOURCES += qpaintervideosurface_mac.mm
+}
+ LIBS += -framework AppKit -framework QuartzCore -framework QTKit
+}
+
+maemo5 {
+ isEqual(QT_ARCH,armv6):QMAKE_CXXFLAGS += -march=armv7a -mcpu=cortex-a8 -mfloat-abi=softfp -mfpu=neon
+ HEADERS += qxvideosurface_maemo5_p.h
+ SOURCES += qxvideosurface_maemo5.cpp
+ SOURCES += qgraphicsvideoitem_maemo5.cpp
+ LIBS += -lXv -lX11 -lXext
+}
+
+maemo6 {
+ isEqual(QT_ARCH,armv6) {
+ HEADERS += qeglimagetexturesurface_p.h
+ SOURCES += qeglimagetexturesurface.cpp
+
+ SOURCES += qgraphicsvideoitem_maemo6.cpp
+
+ LIBS += -lX11
+ } else {
+ SOURCES += qgraphicsvideoitem.cpp
+ }
+}
+
+symbian {
+ contains(surfaces_s60_enabled, yes) {
+ SOURCES += qgraphicsvideoitem_symbian.cpp
+ } else {
+ SOURCES += qgraphicsvideoitem_overlay.cpp
+ }
+}
+
+!maemo*:!symbian {
+ SOURCES += qgraphicsvideoitem.cpp
+}
+
+HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
+
+symbian {
+ contains(S60_VERSION, 5.1) |contains (S60_VERSION, 3.2) | contains(S60_VERSION, 3.1): DEFINES += PRE_S60_52_PLATFORM
+ load(data_caging_paths)
+ QtMediaDeployment.sources = QtMultimediaKit.dll
+ QtMediaDeployment.path = /sys/bin
+ DEPLOYMENT += QtMediaDeployment
+ TARGET.UID3=0x2002AC77
+ TARGET.CAPABILITY = ALL -TCB
+ LIBS += -lefsrv
+}
+
+# CONFIG += middleware
+# include(../../features/deploy.pri)
diff --git a/src/multimediakit/qaudiocapturesource.cpp b/src/multimediakit/qaudiocapturesource.cpp
new file mode 100644
index 000000000..55adda15d
--- /dev/null
+++ b/src/multimediakit/qaudiocapturesource.cpp
@@ -0,0 +1,275 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qmediaobject_p.h"
+#include <qaudiocapturesource.h>
+#include "qaudioendpointselector.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAudioCaptureSource
+ \brief The QAudioCaptureSource class provides an interface to query and select an audio input endpoint.
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ QAudioCaptureSource provides access to the audio inputs available on your system.
+
+ You can query these inputs and select one to use.
+
+ A typical implementation example:
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Audio capture source
+
+ The audiocapturesource interface is then used to:
+
+ - Get and Set the audio input to use.
+
+ The capture interface is then used to:
+
+ - Set the destination using setOutputLocation()
+
+ - Set the format parameters using setAudioCodec(),
+
+ - Control the recording using record(),stop()
+
+ \sa QMediaRecorder
+*/
+
+class QAudioCaptureSourcePrivate : public QMediaObjectPrivate
+{
+public:
+ Q_DECLARE_PUBLIC(QAudioCaptureSource)
+
+ void initControls()
+ {
+ Q_Q(QAudioCaptureSource);
+
+ if (service != 0)
+ audioEndpointSelector = qobject_cast<QAudioEndpointSelector*>(service->requestControl(QAudioEndpointSelector_iid));
+
+ if (audioEndpointSelector) {
+ q->connect(audioEndpointSelector, SIGNAL(activeEndpointChanged(const QString&)),
+ SIGNAL(activeAudioInputChanged(const QString&)));
+ q->connect(audioEndpointSelector, SIGNAL(availableEndpointsChanged()),
+ SIGNAL(availableAudioInputsChanged()));
+ q->connect(audioEndpointSelector, SIGNAL(availableEndpointsChanged()),
+ SLOT(statusChanged()));
+ errorState = QtMultimediaKit::NoError;
+ }
+ }
+
+ QAudioCaptureSourcePrivate():provider(0), audioEndpointSelector(0), errorState(QtMultimediaKit::ServiceMissingError) {}
+ QMediaServiceProvider *provider;
+ QAudioEndpointSelector *audioEndpointSelector;
+ QtMultimediaKit::AvailabilityError errorState;
+};
+
+/*!
+ Construct a QAudioCaptureSource using the QMediaService from \a provider, with \a parent.
+ \since 1.0
+*/
+
+QAudioCaptureSource::QAudioCaptureSource(QObject *parent, QMediaServiceProvider *provider):
+ QMediaObject(*new QAudioCaptureSourcePrivate, parent, provider->requestService(Q_MEDIASERVICE_AUDIOSOURCE))
+{
+ Q_D(QAudioCaptureSource);
+
+ d->provider = provider;
+ d->initControls();
+}
+
+/*!
+ Destroys the audiocapturesource object.
+*/
+
+QAudioCaptureSource::~QAudioCaptureSource()
+{
+ Q_D(QAudioCaptureSource);
+
+ if (d->service && d->audioEndpointSelector)
+ d->service->releaseControl(d->audioEndpointSelector);
+
+ if (d->provider)
+ d->provider->releaseService(d->service);
+}
+
+/*!
+ Returns the error state of the audio capture service.
+ \since 1.0
+*/
+
+QtMultimediaKit::AvailabilityError QAudioCaptureSource::availabilityError() const
+{
+ Q_D(const QAudioCaptureSource);
+
+ return d->errorState;
+}
+
+/*!
+ Returns true if the audio capture service is available, otherwise returns false.
+ \since 1.0
+*/
+bool QAudioCaptureSource::isAvailable() const
+{
+ Q_D(const QAudioCaptureSource);
+
+ if (d->service != NULL) {
+ if (d->audioEndpointSelector && d->audioEndpointSelector->availableEndpoints().size() > 0)
+ return true;
+ }
+ return false;
+}
+
+
+/*!
+ Returns a list of available audio inputs
+ \since 1.0
+*/
+
+QList<QString> QAudioCaptureSource::audioInputs() const
+{
+ Q_D(const QAudioCaptureSource);
+
+ QList<QString> list;
+ if (d && d->audioEndpointSelector)
+ list <<d->audioEndpointSelector->availableEndpoints();
+
+ return list;
+}
+
+/*!
+ Returns the description of the audio input device with \a name.
+ \since 1.0
+*/
+
+QString QAudioCaptureSource::audioDescription(const QString& name) const
+{
+ Q_D(const QAudioCaptureSource);
+
+ if(d->audioEndpointSelector)
+ return d->audioEndpointSelector->endpointDescription(name);
+ else
+ return QString();
+}
+
+/*!
+ Returns the default audio input name.
+ \since 1.0
+*/
+
+QString QAudioCaptureSource::defaultAudioInput() const
+{
+ Q_D(const QAudioCaptureSource);
+
+ if(d->audioEndpointSelector)
+ return d->audioEndpointSelector->defaultEndpoint();
+ else
+ return QString();
+}
+
+/*!
+ Returns the active audio input name.
+ \since 1.0
+*/
+
+QString QAudioCaptureSource::activeAudioInput() const
+{
+ Q_D(const QAudioCaptureSource);
+
+ if(d->audioEndpointSelector)
+ return d->audioEndpointSelector->activeEndpoint();
+ else
+ return QString();
+}
+
+/*!
+ Set the active audio input to \a name.
+ \since 1.0
+*/
+
+void QAudioCaptureSource::setAudioInput(const QString& name)
+{
+ Q_D(const QAudioCaptureSource);
+
+ if(d->audioEndpointSelector)
+ return d->audioEndpointSelector->setActiveEndpoint(name);
+}
+
+/*!
+ \fn QAudioCaptureSource::activeAudioInputChanged(const QString& name)
+
+ Signal emitted when active audio input changes to \a name.
+ \since 1.0
+*/
+
+/*!
+ \fn QAudioCaptureSource::availableAudioInputsChanged()
+
+ Signal is emitted when the available audio inputs change.
+ \since 1.0
+*/
+
+/*!
+ \internal
+ \since 1.0
+*/
+void QAudioCaptureSource::statusChanged()
+{
+ Q_D(QAudioCaptureSource);
+
+ if (d->audioEndpointSelector) {
+ if (d->audioEndpointSelector->availableEndpoints().size() > 0) {
+ d->errorState = QtMultimediaKit::NoError;
+ emit availabilityChanged(true);
+ } else {
+ d->errorState = QtMultimediaKit::BusyError;
+ emit availabilityChanged(false);
+ }
+ } else {
+ d->errorState = QtMultimediaKit::ServiceMissingError;
+ emit availabilityChanged(false);
+ }
+}
+
+#include "moc_qaudiocapturesource.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qaudiocapturesource.h b/src/multimediakit/qaudiocapturesource.h
new file mode 100644
index 000000000..0ef75552a
--- /dev/null
+++ b/src/multimediakit/qaudiocapturesource.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QAUDIOCAPTURESOURCE_H
+#define QAUDIOCAPTURESOURCE_H
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qsize.h>
+
+#include <qaudioformat.h>
+
+#include "qmediarecorder.h"
+#include "qmediacontrol.h"
+#include "qmediaobject.h"
+#include "qmediaservice.h"
+
+#include "qmediaserviceprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAudioCaptureSourcePrivate;
+
+class Q_MULTIMEDIA_EXPORT QAudioCaptureSource : public QMediaObject
+{
+ Q_OBJECT
+
+public:
+ QAudioCaptureSource(QObject *parent = 0, QMediaServiceProvider *service = QMediaServiceProvider::defaultServiceProvider());
+ ~QAudioCaptureSource();
+
+ bool isAvailable() const;
+ QtMultimediaKit::AvailabilityError availabilityError() const;
+
+ QList<QString> audioInputs() const;
+
+ QString audioDescription(const QString& name) const;
+ QString defaultAudioInput() const;
+ QString activeAudioInput() const;
+
+public Q_SLOTS:
+ void setAudioInput(const QString& name);
+
+Q_SIGNALS:
+ void activeAudioInputChanged(const QString& name);
+ void availableAudioInputsChanged();
+
+private Q_SLOTS:
+ void statusChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QAudioCaptureSource)
+};
+
+QT_END_NAMESPACE
+
+#endif // QAUDIOCAPTURESOURCE_H
diff --git a/src/multimediakit/qaudioencodercontrol.cpp b/src/multimediakit/qaudioencodercontrol.cpp
new file mode 100644
index 000000000..d836da94a
--- /dev/null
+++ b/src/multimediakit/qaudioencodercontrol.cpp
@@ -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$
+**
+****************************************************************************/
+
+#include "qaudioencodercontrol.h"
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ \class QAudioEncoderControl
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ \brief The QAudioEncoderControl class provides access to the settings of a
+ media service that performs audio encoding.
+
+ If a QMediaService supports encoding audio data it will implement
+ QAudioEncoderControl. This control provides information about the limits
+ of restricted audio encoder options and allows the selection of a set of
+ audio encoder settings as specified in a QAudioEncoderSettings object.
+
+ The functionality provided by this control is exposed to application code through the
+ QMediaRecorder class.
+
+ The interface name of QAudioEncoderControl is \c com.nokia.Qt.QAudioEncoderControl/1.0 as
+ defined in QAudioEncoderControl_iid.
+
+ \sa QMediaService::requestControl(), QMediaRecorder
+*/
+
+/*!
+ \macro QAudioEncoderControl_iid
+
+ \c com.nokia.Qt.AudioEncoderControl/1.0
+
+ Defines the interface name of the QAudioEncoderControl class.
+
+ \relates QAudioEncoderControl
+*/
+
+/*!
+ Create a new audio encode control object with the given \a parent.
+*/
+QAudioEncoderControl::QAudioEncoderControl(QObject *parent)
+ :QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys the audio encode control.
+*/
+QAudioEncoderControl::~QAudioEncoderControl()
+{
+}
+
+/*!
+ \fn QAudioEncoderControl::supportedAudioCodecs() const
+
+ Returns the list of supported audio codec names.
+ \since 1.0
+*/
+
+/*!
+ \fn QAudioEncoderControl::codecDescription(const QString &codec) const
+
+ Returns description of audio \a codec.
+ \since 1.0
+*/
+
+/*!
+ \fn QAudioEncoderControl::supportedSampleRates(const QAudioEncoderSettings &settings = QAudioEncoderSettings(),
+ bool *continuous) const
+
+ Returns the list of supported audio sample rates, if known.
+
+ If non null audio \a settings parameter is passed,
+ the returned list is reduced to sample rates supported with partial settings applied.
+
+ It can be used for example to query the list of sample rates, supported by specific audio codec.
+
+ If the encoder supports arbitrary sample rates within the supported rates range,
+ *\a continuous is set to true, otherwise *\a continuous is set to false.
+ \since 1.0
+*/
+
+/*!
+ \fn QAudioEncoderControl::supportedEncodingOptions(const QString &codec) const
+
+ Returns the list of \a codec specific audio encoding options.
+ \since 1.0
+*/
+
+/*!
+ \fn QAudioEncoderControl::encodingOption(const QString &codec, const QString &option) const
+
+ Returns the value of audio encoding \a option for \a codec.
+ \since 1.0
+*/
+
+/*!
+ \fn QAudioEncoderControl::setEncodingOption(const QString &codec, const QString &option, const QVariant &value)
+
+ Set the \a codec specific \a option to \a value.
+ \since 1.0
+*/
+
+/*!
+ \fn QAudioEncoderControl::audioSettings() const
+
+ Returns the audio encoder settings.
+
+ The returned value may be different tha passed to QAudioEncoderControl::setAudioSettings()
+ if the settings contains the default or undefined parameters.
+ In this case if the undefined parameters are already resolved, they should be returned.
+ \since 1.0
+*/
+
+/*!
+ \fn QAudioEncoderControl::setAudioSettings(const QAudioEncoderSettings &settings)
+
+ Sets the selected audio \a settings.
+ \since 1.0
+*/
+
+#include "moc_qaudioencodercontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qaudioencodercontrol.h b/src/multimediakit/qaudioencodercontrol.h
new file mode 100644
index 000000000..06cff617e
--- /dev/null
+++ b/src/multimediakit/qaudioencodercontrol.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QAUDIOENCODERCONTROL_H
+#define QAUDIOENCODERCONTROL_H
+
+#include "qmediacontrol.h"
+#include "qmediarecorder.h"
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+
+QT_BEGIN_NAMESPACE
+class QStringList;
+class QAudioFormat;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QAudioEncoderControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ virtual ~QAudioEncoderControl();
+
+ virtual QStringList supportedAudioCodecs() const = 0;
+ virtual QString codecDescription(const QString &codecName) const = 0;
+
+ virtual QList<int> supportedSampleRates(const QAudioEncoderSettings &settings,
+ bool *continuous = 0) const = 0;
+
+ virtual QAudioEncoderSettings audioSettings() const = 0;
+ virtual void setAudioSettings(const QAudioEncoderSettings&) = 0;
+
+ virtual QStringList supportedEncodingOptions(const QString &codec) const = 0;
+ virtual QVariant encodingOption(const QString &codec, const QString &name) const = 0;
+ virtual void setEncodingOption(
+ const QString &codec, const QString &name, const QVariant &value) = 0;
+
+protected:
+ QAudioEncoderControl(QObject *parent = 0);
+};
+
+#define QAudioEncoderControl_iid "com.nokia.Qt.QAudioEncoderControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QAudioEncoderControl, QAudioEncoderControl_iid)
+
+QT_END_NAMESPACE
+
+#endif // QAUDIOCAPTUREPROPERTIESCONTROL_H
diff --git a/src/multimediakit/qaudioendpointselector.cpp b/src/multimediakit/qaudioendpointselector.cpp
new file mode 100644
index 000000000..1a09f3546
--- /dev/null
+++ b/src/multimediakit/qaudioendpointselector.cpp
@@ -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$
+**
+****************************************************************************/
+
+#include "qaudioendpointselector.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAudioEndpointSelector
+
+ \brief The QAudioEndpointSelector class provides an audio endpoint selector media control.
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ The QAudioEndpointSelector class provides descriptions of the audio
+ endpoints available on a system and allows one to be selected as the audio
+ of a media service.
+
+ XXX why do I care
+
+ The interface name of QAudioEndpointSelector is \c com.nokia.Qt.QAudioEndpointSelector/1.0 as
+ defined in QAudioEndpointSelector_iid.
+
+ \sa QMediaService::requestControl()
+*/
+
+/*!
+ \macro QAudioEndpointSelector_iid
+
+ \c com.nokia.Qt.QAudioEndpointSelector/1.0
+
+ Defines the interface name of the QAudioEndpointSelector class.
+
+ \relates QAudioEndpointSelector
+*/
+
+/*!
+ Constructs a new audio endpoint selector with the given \a parent.
+*/
+QAudioEndpointSelector::QAudioEndpointSelector(QObject *parent)
+ :QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys an audio endpoint selector.
+*/
+QAudioEndpointSelector::~QAudioEndpointSelector()
+{
+}
+
+/*!
+ \fn QList<QString> QAudioEndpointSelector::availableEndpoints() const
+
+ Returns a list of the names of the available audio endpoints.
+ \since 1.0
+*/
+
+/*!
+ \fn QString QAudioEndpointSelector::endpointDescription(const QString& name) const
+
+ Returns the description of the endpoint \a name.
+ \since 1.0
+*/
+
+/*!
+ \fn QString QAudioEndpointSelector::defaultEndpoint() const
+
+ Returns the name of the default audio endpoint.
+ \since 1.0
+*/
+
+/*!
+ \fn QString QAudioEndpointSelector::activeEndpoint() const
+
+ Returns the name of the currently selected audio endpoint.
+ \since 1.0
+*/
+
+/*!
+ \fn QAudioEndpointSelector::setActiveEndpoint(const QString& name)
+
+ Set the active audio endpoint to \a name.
+ \since 1.0
+*/
+
+/*!
+ \fn QAudioEndpointSelector::activeEndpointChanged(const QString& name)
+
+ Signals that the audio endpoint has changed to \a name.
+ \since 1.0
+*/
+
+/*!
+ \fn QAudioEndpointSelector::availableEndpointsChanged()
+
+ Signals that list of available endpoints has changed.
+ \since 1.0
+*/
+
+#include "moc_qaudioendpointselector.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qaudioendpointselector.h b/src/multimediakit/qaudioendpointselector.h
new file mode 100644
index 000000000..e28010c65
--- /dev/null
+++ b/src/multimediakit/qaudioendpointselector.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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 QAUDIOENDPOINTSELECTOR_H
+#define QAUDIOENDPOINTSELECTOR_H
+
+#include <qaudio.h>
+#include <qmediacontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QAudioEndpointSelector : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ virtual ~QAudioEndpointSelector();
+
+ virtual QList<QString> availableEndpoints() const = 0;
+ virtual QString endpointDescription(const QString& name) const = 0;
+ virtual QString defaultEndpoint() const = 0;
+ virtual QString activeEndpoint() const = 0;
+
+public Q_SLOTS:
+ virtual void setActiveEndpoint(const QString& name) = 0;
+
+Q_SIGNALS:
+ void activeEndpointChanged(const QString& name);
+ void availableEndpointsChanged();
+
+protected:
+ QAudioEndpointSelector(QObject *parent = 0);
+};
+
+#define QAudioEndpointSelector_iid "com.nokia.Qt.QAudioEndpointSelector/1.0"
+Q_MEDIA_DECLARE_CONTROL(QAudioEndpointSelector, QAudioEndpointSelector_iid)
+
+QT_END_NAMESPACE
+
+#endif // QAUDIOENDPOINTSELECTOR_H
diff --git a/src/multimediakit/qaudionamespace.qdoc b/src/multimediakit/qaudionamespace.qdoc
new file mode 100644
index 000000000..32ceb5c6c
--- /dev/null
+++ b/src/multimediakit/qaudionamespace.qdoc
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+
+/*!
+ \namespace QAudio
+ \brief The QAudio namespace contains enums used by the audio classes.
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+*/
+
+/*
+ \enum QAudio::Error
+
+ Error states
+
+ \value NoError No errors have occurred
+ \value OpenError An error opening the audio device
+ \value IOError An error occurred during read/write of audio device
+ \value UnderrunError Audio data is not being fed to the audio device at a fast enough rate
+ \value FatalError A non-recoverable error has occurred, the audio device is not usable at this time.
+*/
+
+/*
+ \enum QAudio::State
+
+ Audio processing states
+
+ \value ActiveState Audio data is being processed, this state is set after start() is called
+ and while audio data is available to be processed.
+ \value SuspendedState The audio device is in a suspended state, this state will only be entered
+ after suspend() is called.
+ \value StoppedState The audio device is closed, not processing any audio data
+ \value IdleState The QIODevice passed in has no data and audio system's buffer is empty, this state
+ is set after start() is called and while no audio data is available to be processed.
+*/
+
+/*
+ \enum QAudio::Mode
+
+ Audio I/O modes
+
+ \value AudioOutput audio output device
+ \value AudioInput audio input device
+*/
diff --git a/src/multimediakit/qcamera.cpp b/src/multimediakit/qcamera.cpp
new file mode 100644
index 000000000..94b7ac0a2
--- /dev/null
+++ b/src/multimediakit/qcamera.cpp
@@ -0,0 +1,1027 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+
+#include <qcamera.h>
+
+#include <qmediaobject_p.h>
+#include <qcameracontrol.h>
+#include <qcameralockscontrol.h>
+#include <qcameraexposurecontrol.h>
+#include <qcamerafocuscontrol.h>
+#include <qmediarecordercontrol.h>
+#include <qcameraimageprocessingcontrol.h>
+#include <qcameraimagecapturecontrol.h>
+#include <qvideodevicecontrol.h>
+#include <qvideowidget.h>
+#include <qgraphicsvideoitem.h>
+#include <qvideosurfaceoutput_p.h>
+
+QT_USE_NAMESPACE
+
+namespace
+{
+class CameraRegisterMetaTypes
+{
+public:
+ CameraRegisterMetaTypes()
+ {
+ qRegisterMetaType<QCamera::Error>("QCamera::Error");
+ qRegisterMetaType<QCamera::State>("QCamera::State");
+ qRegisterMetaType<QCamera::Status>("QCamera::Status");
+ qRegisterMetaType<QCamera::CaptureMode>("QCamera::CaptureMode");
+ qRegisterMetaType<QCamera::LockType>("QCamera::LockType");
+ qRegisterMetaType<QCamera::LockStatus>("QCamera::LockStatus");
+ qRegisterMetaType<QCamera::LockChangeReason>("QCamera::LockChangeReason");
+ }
+} _registerCameraMetaTypes;
+}
+
+
+/*!
+ \class QCamera
+
+
+ \brief The QCamera class provides interface for system camera devices.
+
+ \inmodule QtMultimediaKit
+ \ingroup camera
+ \since 1.1
+
+ QCamera can be used with QVideoWidget for viewfinder display,
+ QMediaRecorder for video recording and QCameraImageCapture for image taking.
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Request control
+
+*/
+
+
+class QCameraPrivate : public QMediaObjectPrivate
+{
+ Q_DECLARE_NON_CONST_PUBLIC(QCamera)
+public:
+ QCameraPrivate():
+ QMediaObjectPrivate(),
+ provider(0),
+ control(0),
+ deviceControl(0),
+ viewfinder(0),
+ capture(0),
+ state(QCamera::UnloadedState),
+ error(QCamera::NoError),
+ supportedLocks(QCamera::NoLock),
+ requestedLocks(QCamera::NoLock),
+ lockStatus(QCamera::Unlocked),
+ lockChangeReason(QCamera::UserRequest),
+ supressLockChangedSignal(false),
+ restartPending(false)
+ {
+ }
+
+ void initControls();
+
+ QMediaServiceProvider *provider;
+
+ QCameraControl *control;
+ QVideoDeviceControl *deviceControl;
+ QCameraLocksControl *locksControl;
+
+ QCameraExposure *cameraExposure;
+ QCameraFocus *cameraFocus;
+ QCameraImageProcessing *imageProcessing;
+
+ QObject *viewfinder;
+ QObject *capture;
+
+ QCamera::State state;
+
+ QCamera::Error error;
+ QString errorString;
+
+ QCamera::LockTypes supportedLocks;
+ QCamera::LockTypes requestedLocks;
+
+ QCamera::LockStatus lockStatus;
+ QCamera::LockChangeReason lockChangeReason;
+ bool supressLockChangedSignal;
+
+ bool restartPending;
+
+ QVideoSurfaceOutput surfaceViewfinder;
+
+ void _q_error(int error, const QString &errorString);
+ void unsetError() { error = QCamera::NoError; errorString.clear(); }
+
+ void setState(QCamera::State);
+
+ void _q_updateLockStatus(QCamera::LockType, QCamera::LockStatus, QCamera::LockChangeReason);
+ void _q_updateState(QCamera::State newState);
+ void _q_preparePropertyChange(int changeType);
+ void _q_restartCamera();
+ void updateLockStatus();
+};
+
+
+void QCameraPrivate::_q_error(int error, const QString &errorString)
+{
+ Q_Q(QCamera);
+
+ this->error = QCamera::Error(error);
+ this->errorString = errorString;
+
+ qWarning() << "Camera error:" << errorString;
+
+ emit q->error(this->error);
+}
+
+void QCameraPrivate::setState(QCamera::State newState)
+{
+ Q_Q(QCamera);
+
+ unsetError();
+
+ if (!control) {
+ _q_error(QCamera::ServiceMissingError, q_ptr->tr("The camera service is missing"));
+ return;
+ }
+
+ if (state == newState)
+ return;
+
+ restartPending = false;
+ state = newState;
+ control->setState(state);
+ emit q->stateChanged(state);
+}
+
+void QCameraPrivate::_q_updateState(QCamera::State newState)
+{
+ Q_Q(QCamera);
+
+ //omit changins state to Loaded when the camera is temporarily
+ //stopped to apply shanges
+ if (restartPending)
+ return;
+
+ if (newState != state) {
+ qDebug() << "Camera state changed:" << newState;
+ state = newState;
+ emit q->stateChanged(state);
+ }
+}
+
+void QCameraPrivate::_q_preparePropertyChange(int changeType)
+{
+ if (!control)
+ return;
+
+ QCamera::Status status = control->status();
+
+ //all the changes are allowed until the camera is starting
+ if (control->state() != QCamera::ActiveState)
+ return;
+
+ if (control->canChangeProperty(QCameraControl::PropertyChangeType(changeType), status))
+ return;
+
+ restartPending = true;
+ control->setState(QCamera::LoadedState);
+ QMetaObject::invokeMethod(q_ptr, "_q_restartCamera", Qt::QueuedConnection);
+}
+
+void QCameraPrivate::_q_restartCamera()
+{
+ if (restartPending) {
+ restartPending = false;
+ control->setState(QCamera::ActiveState);
+ }
+}
+
+void QCameraPrivate::initControls()
+{
+ Q_Q(QCamera);
+
+ supportedLocks = 0;
+
+ if (service) {
+ control = qobject_cast<QCameraControl *>(service->requestControl(QCameraControl_iid));
+ locksControl = qobject_cast<QCameraLocksControl *>(service->requestControl(QCameraLocksControl_iid));
+ deviceControl = qobject_cast<QVideoDeviceControl*>(service->requestControl(QVideoDeviceControl_iid));
+
+ if (control) {
+ q->connect(control, SIGNAL(stateChanged(QCamera::State)), q, SLOT(_q_updateState(QCamera::State)));
+ q->connect(control, SIGNAL(statusChanged(QCamera::Status)), q, SIGNAL(statusChanged(QCamera::Status)));
+ q->connect(control, SIGNAL(captureModeChanged(QCamera::CaptureMode)),
+ q, SIGNAL(captureModeChanged(QCamera::CaptureMode)));
+ q->connect(control, SIGNAL(error(int,QString)), q, SLOT(_q_error(int,QString)));
+
+ }
+
+ if (locksControl) {
+ q->connect(locksControl, SIGNAL(lockStatusChanged(QCamera::LockType,QCamera::LockStatus,QCamera::LockChangeReason)),
+ q, SLOT(_q_updateLockStatus(QCamera::LockType,QCamera::LockStatus,QCamera::LockChangeReason)));
+ supportedLocks = locksControl->supportedLocks();
+ }
+
+ error = QCamera::NoError;
+ } else {
+ control = 0;
+ locksControl = 0;
+ deviceControl = 0;
+
+ error = QCamera::ServiceMissingError;
+ errorString = QCamera::tr("The camera service is missing");
+ }
+}
+
+void QCameraPrivate::updateLockStatus()
+{
+ Q_Q(QCamera);
+
+ QCamera::LockStatus oldStatus = lockStatus;
+
+ QMap<QCamera::LockStatus, int> lockStatusPriority;
+ lockStatusPriority.insert(QCamera::Locked, 1);
+ lockStatusPriority.insert(QCamera::Searching, 2);
+ lockStatusPriority.insert(QCamera::Unlocked, 3);
+
+ lockStatus = requestedLocks ? QCamera::Locked : QCamera::Unlocked;
+ int priority = 0;
+
+ QList<QCamera::LockStatus> lockStatuses;
+
+ if (requestedLocks & QCamera::LockFocus)
+ lockStatuses << q->lockStatus(QCamera::LockFocus);
+
+ if (requestedLocks & QCamera::LockExposure)
+ lockStatuses << q->lockStatus(QCamera::LockExposure);
+
+ if (requestedLocks & QCamera::LockWhiteBalance)
+ lockStatuses << q->lockStatus(QCamera::LockWhiteBalance);
+
+
+ foreach (QCamera::LockStatus currentStatus, lockStatuses) {
+ int currentPriority = lockStatusPriority.value(currentStatus, -1);
+ if (currentPriority > priority) {
+ priority = currentPriority;
+ lockStatus = currentStatus;
+ }
+ }
+
+ if (!supressLockChangedSignal && oldStatus != lockStatus) {
+ emit q->lockStatusChanged(lockStatus, lockChangeReason);
+
+ if (lockStatus == QCamera::Locked)
+ emit q->locked();
+ else if (lockStatus == QCamera::Unlocked && lockChangeReason == QCamera::LockFailed)
+ emit q->lockFailed();
+ }
+/*
+ qDebug() << "Requested locks:" << (requestedLocks & QCamera::LockExposure ? 'e' : ' ')
+ << (requestedLocks & QCamera::LockFocus ? 'f' : ' ')
+ << (requestedLocks & QCamera::LockWhiteBalance ? 'w' : ' ');
+ qDebug() << "Lock status: f:" << q->lockStatus(QCamera::LockFocus)
+ << " e:" << q->lockStatus(QCamera::LockExposure)
+ << " w:" << q->lockStatus(QCamera::LockWhiteBalance)
+ << " composite:" << lockStatus;
+*/
+}
+
+void QCameraPrivate::_q_updateLockStatus(QCamera::LockType type, QCamera::LockStatus status, QCamera::LockChangeReason reason)
+{
+ Q_Q(QCamera);
+ lockChangeReason = reason;
+ updateLockStatus();
+ emit q->lockStatusChanged(type, status, reason);
+}
+
+
+/*!
+ Construct a QCamera from service \a provider and \a parent.
+*/
+
+QCamera::QCamera(QObject *parent, QMediaServiceProvider *provider):
+ QMediaObject(*new QCameraPrivate, parent, provider->requestService(Q_MEDIASERVICE_CAMERA))
+{
+ Q_D(QCamera);
+ d->provider = provider;
+ d->initControls();
+ d->cameraExposure = new QCameraExposure(this);
+ d->cameraFocus = new QCameraFocus(this);
+ d->imageProcessing = new QCameraImageProcessing(this);
+}
+
+/*!
+ Construct a QCamera from device name \a device and \a parent.
+*/
+
+QCamera::QCamera(const QByteArray& device, QObject *parent):
+ QMediaObject(*new QCameraPrivate, parent,
+ QMediaServiceProvider::defaultServiceProvider()->requestService(Q_MEDIASERVICE_CAMERA, QMediaServiceProviderHint(device)))
+{
+ Q_D(QCamera);
+ d->provider = QMediaServiceProvider::defaultServiceProvider();
+ d->initControls();
+
+ if (d->service != 0) {
+ //pass device name to service
+ if (d->deviceControl) {
+ QString deviceName(device);
+
+ for (int i=0; i<d->deviceControl->deviceCount(); i++) {
+ if (d->deviceControl->deviceName(i) == deviceName) {
+ d->deviceControl->setSelectedDevice(i);
+ break;
+ }
+ }
+ }
+ }
+
+ d->cameraExposure = new QCameraExposure(this);
+ d->cameraFocus = new QCameraFocus(this);
+ d->imageProcessing = new QCameraImageProcessing(this);
+}
+
+/*!
+ Destroys the camera object.
+*/
+
+QCamera::~QCamera()
+{
+ Q_D(QCamera);
+ delete d->cameraExposure;
+ d->cameraExposure = 0;
+ delete d->cameraFocus;
+ d->cameraFocus = 0;
+ delete d->imageProcessing;
+ d->imageProcessing = 0;
+
+ if (d->service) {
+ if (d->control)
+ d->service->releaseControl(d->control);
+ if (d->locksControl)
+ d->service->releaseControl(d->locksControl);
+ if (d->deviceControl)
+ d->service->releaseControl(d->deviceControl);
+
+ d->provider->releaseService(d->service);
+ }
+}
+
+
+/*!
+ Return true if the camera service is ready to use.
+ \since 1.1
+*/
+bool QCamera::isAvailable() const
+{
+ return availabilityError() == QtMultimediaKit::NoError;
+}
+
+/*!
+ Returns the error state of the camera service.
+ \since 1.1
+*/
+
+QtMultimediaKit::AvailabilityError QCamera::availabilityError() const
+{
+ Q_D(const QCamera);
+ if (d->control == NULL)
+ return QtMultimediaKit::ServiceMissingError;
+
+ if (d->deviceControl && d->deviceControl->deviceCount() == 0)
+ return QtMultimediaKit::ResourceError;
+
+ if (d->error != QCamera::NoError)
+ return QtMultimediaKit::ResourceError;
+
+ return QtMultimediaKit::NoError;
+}
+
+
+/*!
+ Returns the camera exposure control object.
+ \since 1.1
+*/
+QCameraExposure *QCamera::exposure() const
+{
+ return d_func()->cameraExposure;
+}
+
+/*!
+ Returns the camera focus control object.
+ \since 1.1
+*/
+QCameraFocus *QCamera::focus() const
+{
+ return d_func()->cameraFocus;
+}
+
+/*!
+ Returns the camera image processing control object.
+ \since 1.1
+*/
+QCameraImageProcessing *QCamera::imageProcessing() const
+{
+ return d_func()->imageProcessing;
+}
+
+/*!
+ Sets the QVideoWidget based camera \a viewfinder.
+ The previously set viewfinder is detached.
+ \since 1.1
+*/
+void QCamera::setViewfinder(QVideoWidget *viewfinder)
+{
+ Q_D(QCamera);
+ d->_q_preparePropertyChange(QCameraControl::Viewfinder);
+
+ if (d->viewfinder)
+ unbind(d->viewfinder);
+
+ d->viewfinder = viewfinder && bind(viewfinder) ? viewfinder : 0;
+}
+
+/*!
+ Sets the QGraphicsVideoItem based camera \a viewfinder.
+ The previously set viewfinder is detached.
+ \since 1.1
+*/
+void QCamera::setViewfinder(QGraphicsVideoItem *viewfinder)
+{
+ Q_D(QCamera);
+ d->_q_preparePropertyChange(QCameraControl::Viewfinder);
+
+ if (d->viewfinder)
+ unbind(d->viewfinder);
+
+ d->viewfinder = viewfinder && bind(viewfinder) ? viewfinder : 0;
+}
+
+/*!
+ Sets a video \a surface as the viewfinder of a camera.
+
+ If a viewfinder has already been set on the camera the new surface
+ will replace it.
+ \since 1.2
+*/
+
+void QCamera::setViewfinder(QAbstractVideoSurface *surface)
+{
+ Q_D(QCamera);
+
+ d->surfaceViewfinder.setVideoSurface(surface);
+
+ if (d->viewfinder != &d->surfaceViewfinder) {
+ if (d->viewfinder)
+ unbind(d->viewfinder);
+
+ d->viewfinder = bind(&d->surfaceViewfinder) ? &d->surfaceViewfinder : 0;
+ }
+}
+
+/*!
+ Returns the error state of the object.
+ \since 1.1
+*/
+
+QCamera::Error QCamera::error() const
+{
+ return d_func()->error;
+}
+
+/*!
+ Returns a string describing a camera's error state.
+ \since 1.1
+*/
+QString QCamera::errorString() const
+{
+ return d_func()->errorString;
+}
+
+
+/*!
+ Returns true if the capture \a mode is suported.
+ \since 1.1
+*/
+bool QCamera::isCaptureModeSupported(QCamera::CaptureMode mode) const
+{
+ return d_func()->control ? d_func()->control->isCaptureModeSupported(mode) : false;
+}
+
+/*!
+ \property QCamera::captureMode
+
+ The type of media (video or still images),
+ the camera is configured to capture.
+
+ It's allowed to change capture mode in any camera state,
+ but if the camera is currently active,
+ chaging capture mode is likely to lead to camera status
+ chaged to QCamera::LoadedStatus, QCamera::LoadingStatus,
+ and when the camera is ready to QCamera::ActiveStatus.
+ \since 1.1
+*/
+
+QCamera::CaptureMode QCamera::captureMode() const
+{
+ return d_func()->control ? d_func()->control->captureMode() : QCamera::CaptureStillImage;
+}
+
+void QCamera::setCaptureMode(QCamera::CaptureMode mode)
+{
+ Q_D(QCamera);
+
+ if (mode != captureMode()) {
+ if (d->control) {
+ d->_q_preparePropertyChange(QCameraControl::CaptureMode);
+ d->control->setCaptureMode(mode);
+ }
+ }
+}
+
+
+/*!
+ Starts the camera.
+
+ State is changed to QCamera::ActiveState if camera is started
+ successfully, otherwise error() signal is emitted.
+
+ While the camera state is changed to QCamera::ActiveState,
+ starting the camera service can be asynchronous with the actual
+ status reported with QCamera::status property.
+ \since 1.1
+*/
+void QCamera::start()
+{
+ Q_D(QCamera);
+ d->setState(QCamera::ActiveState);
+}
+
+/*!
+ Stops the camera.
+ The camera state is changed from QCamera::ActiveState to QCamera::LoadedState.
+ \since 1.1
+*/
+void QCamera::stop()
+{
+ Q_D(QCamera);
+ d->setState(QCamera::LoadedState);
+}
+
+/*!
+ Open the camera device.
+ The camera state is changed to QCamera::LoadedStatus.
+
+ It's not necessary to explcitly load the camera,
+ unless unless the application have to read the supported camera
+ settings and change the default depending on the camera capabilities.
+
+ In all the other cases it's possible to start the camera directly
+ from unloaded state.
+ \since 1.1
+*/
+void QCamera::load()
+{
+ Q_D(QCamera);
+ d->setState(QCamera::LoadedState);
+}
+
+/*!
+ Close the camera device and deallocate the related resources.
+ The camera state is changed to QCamera::UnloadedStatus.
+ \since 1.1
+*/
+void QCamera::unload()
+{
+ Q_D(QCamera);
+ d->setState(QCamera::UnloadedState);
+}
+
+
+/*!
+ Returns a list of camera device's available from the default service provider.
+ \since 1.1
+*/
+
+QList<QByteArray> QCamera::availableDevices()
+{
+ return QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA));
+}
+
+/*!
+ Returns the description of the \a device.
+ \since 1.1
+*/
+
+QString QCamera::deviceDescription(const QByteArray &device)
+{
+ return QMediaServiceProvider::defaultServiceProvider()->deviceDescription(QByteArray(Q_MEDIASERVICE_CAMERA), device);
+}
+
+QCamera::State QCamera::state() const
+{
+ return d_func()->state;
+}
+
+QCamera::Status QCamera::status() const
+{
+ if(d_func()->control)
+ return (QCamera::Status)d_func()->control->status();
+
+ return QCamera::UnavailableStatus;
+}
+
+
+/*!
+ Returns the lock types, camera supports.
+ \since 1.1
+*/
+QCamera::LockTypes QCamera::supportedLocks() const
+{
+ return d_func()->supportedLocks;
+}
+
+/*!
+ Returns the requested lock types.
+ \since 1.1
+*/
+QCamera::LockTypes QCamera::requestedLocks() const
+{
+ return d_func()->requestedLocks;
+}
+
+/*!
+ Returns the status of requested camera settings locks.
+ \since 1.1
+*/
+QCamera::LockStatus QCamera::lockStatus() const
+{
+ return d_func()->lockStatus;
+}
+
+/*!
+ Returns the status of camera settings \a lock.
+ \since 1.1
+*/
+QCamera::LockStatus QCamera::lockStatus(QCamera::LockType lockType) const
+{
+ const QCameraPrivate *d = d_func();
+
+ if (!(lockType & d->supportedLocks))
+ return lockType & d->requestedLocks ? QCamera::Locked : QCamera::Unlocked;
+
+ if (!(lockType & d->requestedLocks))
+ return QCamera::Unlocked;
+
+ if (d->locksControl)
+ return d->locksControl->lockStatus(lockType);
+
+ return QCamera::Unlocked;
+}
+
+/*!
+ \fn void QCamera::searchAndLock(QCamera::LockTypes locks)
+
+ Locks the camera settings with the requested \a locks, including focusing in the single autofocus mode,
+ exposure and white balance if the exposure and white balance modes are not manual.
+
+ The camera settings are usually locked before taking one or multiple still images,
+ in responce to the shutter button being half pressed.
+
+ The QCamera::locked() signal is emitted when camera settings are successfully locked,
+ otherwise QCamera::lockFailed() is emitted.
+
+ QCamera also emits lockStatusChanged(QCamera::LockType, QCamera::LockStatus)
+ on individual lock status changes and lockStatusChanged(QCamera::LockStatus) signal on composite status changes.
+
+ Locking serves two roles: it initializes calculation of automatic parameter
+ (focusing, calculating the correct exposure and white balance) and allows
+ to keep some or all of those parameters during number of shots.
+
+ If the camera doesn't support keeping one of parameters between shots, the related
+ lock state changes to QCamera::Unlocked.
+
+ It's also acceptable to relock already locked settings,
+ depending on the lock parameter this initiates new focusing, exposure or white balance calculation.
+ \since 1.1
+ */
+void QCamera::searchAndLock(QCamera::LockTypes locks)
+{
+ Q_D(QCamera);
+
+ QCamera::LockStatus oldStatus = d->lockStatus;
+ d->supressLockChangedSignal = true;
+
+ d->requestedLocks |= locks;
+
+ locks &= d->supportedLocks;
+
+ if (d->locksControl)
+ d->locksControl->searchAndLock(locks);
+
+ d->supressLockChangedSignal = false;
+
+ d->lockStatus = oldStatus;
+ d->updateLockStatus();
+}
+
+/*!
+ Lock all the supported camera settings.
+ \since 1.1
+ */
+void QCamera::searchAndLock()
+{
+ searchAndLock(LockExposure | LockWhiteBalance | LockFocus);
+}
+
+/*!
+ Unlocks the camera settings specified with \a locks or cancel the current locking if one is active.
+ \since 1.1
+ */
+void QCamera::unlock(QCamera::LockTypes locks)
+{
+ Q_D(QCamera);
+
+ QCamera::LockStatus oldStatus = d->lockStatus;
+ d->supressLockChangedSignal = true;
+
+ d->requestedLocks &= ~locks;
+
+ locks &= d->supportedLocks;
+
+ if (d->locksControl)
+ d->locksControl->unlock(locks);
+
+ d->supressLockChangedSignal = false;
+
+ d->lockStatus = oldStatus;
+ d->updateLockStatus();
+}
+
+/*!
+ Unlock all the requested camera locks.
+ \since 1.1
+ */
+void QCamera::unlock()
+{
+ unlock(d_func()->requestedLocks);
+}
+
+
+/*!
+ \enum QCamera::State
+ \value UnloadedState
+ The initial camera state, with camera not loaded,
+ the camera capabilities except of supported capture modes
+ are unknown.
+
+ While the supported settings are unknown in this state,
+ it's allowed to set the camera capture settings like codec,
+ resolution, or frame rate.
+
+ \value LoadedState
+ The camera is loaded and ready to be configured.
+
+ In the Idle state it's allowed to query camera capabilities,
+ set capture resolution, codecs, etc.
+
+ The viewfinder is not active in the loaded state.
+
+ \value ActiveState
+ In the active state as soon as camera is started
+ the viewfinder displays video frames and the
+ camera is ready for capture.
+*/
+
+
+/*!
+ \property QCamera::state
+ \brief The current state of the camera object.
+ \since 1.1
+*/
+
+/*!
+ \enum QCamera::Status
+ \value ActiveStatus
+ The camera has been started and can produce data.
+ The viewfinder displays video frames in active state.
+
+ Depending on backend, changing some camera settings like
+ capture mode, codecs or resolution in ActiveState may lead
+ to changing the camera status to LoadedStatus and StartingStatus while
+ the settings are applied and back to ActiveStatus when the camera is ready.
+
+ \value StartingStatus
+ The camera is starting in result of state transition to QCamera::ActiveState.
+ The camera service is not ready to capture yet.
+
+ \value StandbyStatus
+ The camera is in the power saving standby mode.
+ The camera may come to the standby mode after some time of inactivity
+ in the QCamera::LoadedState state.
+
+ \value LoadedStatus
+ The camera is loaded and ready to be configured.
+ This status indicates the camera device is opened and
+ it's possible to query for supported image and video capture settings,
+ like resolution, framerate and codecs.
+
+ \value LoadingStatus
+ The camera device loading in result of state transition from
+ QCamera::UnloadedState to QCamera::LoadedState or QCamera::ActiveState.
+
+ \value UnloadedStatus
+ The initial camera status, with camera not loaded.
+ The camera capabilities including supported capture settings may be unknown.
+
+ \value UnavailableStatus
+ The camera or camera backend is not available.
+*/
+
+
+/*!
+ \property QCamera::status
+ \brief The current status of the camera object.
+ \since 1.1
+*/
+
+
+/*!
+ \enum QCamera::CaptureMode
+ \value CaptureStillImage Camera is configured for still frames capture.
+ \value CaptureVideo Camera is configured for video capture.
+ \since 1.1
+*/
+
+/*!
+ \enum QCamera::LockType
+
+ \value NoLock
+ \value LockExposure
+ Lock camera exposure.
+ \value LockWhiteBalance
+ Lock the white balance.
+ \value LockFocus
+ Lock camera focus.
+*/
+
+
+/*!
+ \property QCamera::lockStatus
+ \brief The overall status for all the requested camera locks.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCamera::locked()
+
+ Signals all the requested camera settings are locked.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCamera::lockFailed()
+
+ Signals locking of at least one requested camera settings failed.
+ \since 1.1
+*/
+
+/*!
+ \fn QCamera::lockStatusChanged(QCamera::LockStatus status, QCamera::LockChangeReason reason)
+
+ Signals the overall \a status for all the requested camera locks was changed with specified \a reason.
+ \since 1.1
+*/
+
+/*!
+ \fn QCamera::lockStatusChanged(QCamera::LockType lock, QCamera::LockStatus status, QCamera::LockChangeReason reason)
+ Signals the \a lock \a status was changed with specified \a reason.
+ \since 1.1
+*/
+
+/*!
+ \enum QCamera::LockStatus
+ \value Unlocked
+ The application is not interested in camera settings value.
+ The camera may keep this parameter without changes, this is common with camera focus,
+ or adjust exposure and white balance constantly to keep the viewfinder image nice.
+
+ \value Searching
+ The application has requested the camera focus, exposure or white balance lock with
+ QCamera::searchAndLock(). This state indicates the camera is focusing or calculating exposure and white balance.
+
+ \value Locked
+ The camera focus, exposure or white balance is locked.
+ The camera is ready to capture, application may check the exposure parameters.
+
+ The locked state usually means the requested parameter stays the same,
+ except of the cases when the parameter is requested to be constantly updated.
+ For example in continuous focusing mode, the focus is considered locked as long
+ and the object is in focus, even while the actual focusing distance may be constantly changing.
+*/
+
+/*!
+ \enum QCamera::LockChangeReason
+
+ \value UserRequest
+ The lock status changed in result of user request, usually to unlock camera settings.
+ \value LockAcquired
+ The lock status successfuly changed to QCamera::Locked.
+ \value LockFailed
+ The camera failed to acquire the requested lock in result of
+ autofocus failure, exposure out of supported range, etc.
+ \value LockLost
+ The camera is not able to maintain the requested lock any more.
+ Lock status is changed to QCamera::Unlocked.
+ \value LockTemporaryLost
+ The lock is lost, but the camera is working hard to reacquire it.
+ This value may be used in continuous focusing mode,
+ when the camera loses the focus, the focus lock state is changed to Qcamera::Searching
+ with LockTemporaryLost reason.
+*/
+
+/*!
+ \enum QCamera::Error
+
+ \value NoError No errors have occurred.
+ \value CameraError An error has occurred.
+ \value InvalidRequestError System resource doesn't support requested functionality.
+ \value ServiceMissingError No camera service available.
+ \value NotSupportedFeatureError The feature is not supported.
+*/
+
+/*!
+ \fn void QCamera::error(QCamera::Error value)
+
+ Signal emitted when error state changes to \a value.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCamera::captureModeChanged(QCamera::CaptureMode mode)
+
+ Signals the capture \a mode has changed.
+ \since 1.1
+*/
+
+/*!
+ \fn QCamera::stateChanged(QCamera::State state)
+
+ Signals the camera \a state has changed.
+
+ Usually the state changes is caused by calling
+ load(), unload(), start() and stop(),
+ but the state can also be changed change as a result of camera error.
+ \since 1.1
+*/
+
+/*!
+ \fn QCamera::statusChanged(QCamera::Status status)
+
+ Signals the camera \a status has changed.
+
+ \since 1.1
+*/
+
+
+#include "moc_qcamera.cpp"
diff --git a/src/multimediakit/qcamera.h b/src/multimediakit/qcamera.h
new file mode 100644
index 000000000..b6fd163a5
--- /dev/null
+++ b/src/multimediakit/qcamera.h
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCAMERA_H
+#define QCAMERA_H
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+
+#include <qmediacontrol.h>
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+
+#include <qcameraexposure.h>
+#include <qcamerafocus.h>
+#include <qcameraimageprocessing.h>
+
+#include <qmediaserviceprovider.h>
+#include <qmediaenumdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractVideoSurface;
+class QVideoWidget;
+class QGraphicsVideoItem;
+
+class QCameraPrivate;
+class Q_MULTIMEDIA_EXPORT QCamera : public QMediaObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QCamera::State state READ state NOTIFY stateChanged)
+ Q_PROPERTY(QCamera::Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QCamera::CaptureMode captureMode READ captureMode WRITE setCaptureMode NOTIFY captureModeChanged)
+ Q_PROPERTY(QCamera::LockStatus lockStatus READ lockStatus NOTIFY lockStatusChanged)
+
+ Q_ENUMS(Status)
+ Q_ENUMS(State)
+ Q_ENUMS(CaptureMode)
+ Q_ENUMS(Error)
+ Q_ENUMS(LockStatus)
+ Q_ENUMS(LockChangeReason)
+ Q_ENUMS(LockType)
+public:
+ enum Status {
+ UnavailableStatus,
+ UnloadedStatus,
+ LoadingStatus,
+ LoadedStatus,
+ StandbyStatus,
+ StartingStatus,
+ ActiveStatus
+ };
+
+ enum State {
+ UnloadedState,
+ LoadedState,
+ ActiveState
+ };
+
+ enum CaptureMode
+ {
+ CaptureStillImage,
+ CaptureVideo
+ };
+
+ enum Error
+ {
+ NoError,
+ CameraError,
+ InvalidRequestError,
+ ServiceMissingError,
+ NotSupportedFeatureError
+ };
+
+ enum LockStatus
+ {
+ Unlocked,
+ Searching,
+ Locked
+ };
+
+ enum LockChangeReason {
+ UserRequest,
+ LockAcquired,
+ LockFailed,
+ LockLost,
+ LockTemporaryLost
+ };
+
+ enum LockType
+ {
+ NoLock = 0,
+ LockExposure = 0x01,
+ LockWhiteBalance = 0x02,
+ LockFocus = 0x04
+ };
+ Q_DECLARE_FLAGS(LockTypes, LockType)
+
+ QCamera(QObject *parent = 0, QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider());
+ QCamera(const QByteArray& device, QObject *parent = 0);
+ ~QCamera();
+
+ static QList<QByteArray> availableDevices();
+ static QString deviceDescription(const QByteArray &device);
+
+ bool isAvailable() const;
+ QtMultimediaKit::AvailabilityError availabilityError() const;
+
+ State state() const;
+ Status status() const;
+
+ CaptureMode captureMode() const;
+ bool isCaptureModeSupported(CaptureMode mode) const;
+
+ QCameraExposure *exposure() const;
+ QCameraFocus *focus() const;
+ QCameraImageProcessing *imageProcessing() const;
+
+ void setViewfinder(QVideoWidget *viewfinder);
+ void setViewfinder(QGraphicsVideoItem *viewfinder);
+ void setViewfinder(QAbstractVideoSurface *surface);
+
+ Error error() const;
+ QString errorString() const;
+
+ QCamera::LockTypes supportedLocks() const;
+ QCamera::LockTypes requestedLocks() const;
+
+ QCamera::LockStatus lockStatus() const;
+ QCamera::LockStatus lockStatus(QCamera::LockType lock) const;
+
+public Q_SLOTS:
+ void setCaptureMode(QCamera::CaptureMode mode);
+
+ void load();
+ void unload();
+
+ void start();
+ void stop();
+
+ void searchAndLock();
+ void unlock();
+
+ void searchAndLock(QCamera::LockTypes locks);
+ void unlock(QCamera::LockTypes locks);
+
+Q_SIGNALS:
+ void stateChanged(QCamera::State);
+ void captureModeChanged(QCamera::CaptureMode);
+ void statusChanged(QCamera::Status);
+
+ void locked();
+ void lockFailed();
+
+ void lockStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason);
+ void lockStatusChanged(QCamera::LockType, QCamera::LockStatus, QCamera::LockChangeReason);
+
+ void error(QCamera::Error);
+
+private:
+ Q_DISABLE_COPY(QCamera)
+ Q_DECLARE_PRIVATE(QCamera)
+ Q_PRIVATE_SLOT(d_func(), void _q_preparePropertyChange(int))
+ Q_PRIVATE_SLOT(d_func(), void _q_restartCamera())
+ Q_PRIVATE_SLOT(d_func(), void _q_error(int, const QString &))
+ Q_PRIVATE_SLOT(d_func(), void _q_updateLockStatus(QCamera::LockType, QCamera::LockStatus, QCamera::LockChangeReason))
+ Q_PRIVATE_SLOT(d_func(), void _q_updateState(QCamera::State))
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QCamera::LockTypes)
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QCamera::State)
+Q_DECLARE_METATYPE(QCamera::Status)
+Q_DECLARE_METATYPE(QCamera::Error)
+Q_DECLARE_METATYPE(QCamera::CaptureMode)
+Q_DECLARE_METATYPE(QCamera::LockType)
+Q_DECLARE_METATYPE(QCamera::LockStatus)
+Q_DECLARE_METATYPE(QCamera::LockChangeReason)
+
+Q_MEDIA_ENUM_DEBUG(QCamera, State)
+Q_MEDIA_ENUM_DEBUG(QCamera, Status)
+Q_MEDIA_ENUM_DEBUG(QCamera, Error)
+Q_MEDIA_ENUM_DEBUG(QCamera, CaptureMode)
+Q_MEDIA_ENUM_DEBUG(QCamera, LockType)
+Q_MEDIA_ENUM_DEBUG(QCamera, LockStatus)
+Q_MEDIA_ENUM_DEBUG(QCamera, LockChangeReason)
+
+#endif // QCAMERA_H
diff --git a/src/multimediakit/qcameracapturebufferformatcontrol.cpp b/src/multimediakit/qcameracapturebufferformatcontrol.cpp
new file mode 100644
index 000000000..06602abe8
--- /dev/null
+++ b/src/multimediakit/qcameracapturebufferformatcontrol.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** 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 <qcameracapturebufferformatcontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCameraCaptureBufferFormatControl
+
+ \brief The QCameraCaptureBufferFormatControl class provides a control for setting the capture buffer format.
+
+ The format is of type QVideoFrame::PixelFormat.
+
+ \inmodule QtMultimediaKit
+ \ingroup camera
+
+ The interface name of QCameraCaptureBufferFormatControl is \c com.nokia.Qt.QCameraCaptureBufferFormatControl/1.0 as
+ defined in QCameraCaptureBufferFormatControl_iid.
+
+ \sa QMediaService::requestControl()
+ \since QtMobility 1.2
+*/
+
+/*!
+ \macro QCameraCaptureBufferFormatControl_iid
+
+ \c com.nokia.Qt.QCameraCaptureBufferFormatControl/1.0
+
+ Defines the interface name of the QCameraCaptureBufferFormatControl class.
+
+ \relates QCameraCaptureBufferFormatControl
+*/
+
+/*!
+ Constructs a new image buffer capture format control object with the given \a parent
+*/
+QCameraCaptureBufferFormatControl::QCameraCaptureBufferFormatControl(QObject *parent)
+ :QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys an image buffer capture format control.
+*/
+QCameraCaptureBufferFormatControl::~QCameraCaptureBufferFormatControl()
+{
+}
+
+/*!
+ \fn QCameraCaptureBufferFormatControl::supportedBufferFormats() const
+
+ Returns the list of the supported buffer capture formats.
+ \since 1.2
+*/
+
+/*!
+ \fn QCameraCaptureBufferFormatControl::bufferFormat() const
+
+ Returns the current buffer capture format.
+ \since 1.2
+*/
+
+/*!
+ \fn QCameraCaptureBufferFormatControl::setBufferFormat(QVideoFrame::PixelFormat format)
+
+ Sets the buffer capture \a format.
+ \since 1.2
+*/
+
+/*!
+ \fn QCameraCaptureBufferFormatControl::bufferFormatChanged(QVideoFrame::PixelFormat format)
+
+ Signals the buffer image capture format changed to \a format.
+ \since 1.2
+*/
+
+#include "moc_qcameracapturebufferformatcontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qcameracapturebufferformatcontrol.h b/src/multimediakit/qcameracapturebufferformatcontrol.h
new file mode 100644
index 000000000..27835b35f
--- /dev/null
+++ b/src/multimediakit/qcameracapturebufferformatcontrol.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** 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 QCAMERACAPTUREBUFFERFORMATCONTROL_H
+#define QCAMERACAPTUREBUFFERFORMATCONTROL_H
+
+#include <qmediacontrol.h>
+#include <qcameraimagecapture.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QCameraCaptureBufferFormatControl : public QMediaControl
+{
+ Q_OBJECT
+public:
+ ~QCameraCaptureBufferFormatControl();
+
+ virtual QList<QVideoFrame::PixelFormat> supportedBufferFormats() const = 0;
+ virtual QVideoFrame::PixelFormat bufferFormat() const = 0;
+ virtual void setBufferFormat(QVideoFrame::PixelFormat format) = 0;
+
+Q_SIGNALS:
+ void bufferFormatChanged(QVideoFrame::PixelFormat);
+
+protected:
+ QCameraCaptureBufferFormatControl(QObject* parent = 0);
+};
+
+#define QCameraCaptureBufferFormatControl_iid "com.nokia.Qt.QCameraCaptureBufferFormatControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QCameraCaptureBufferFormatControl, QCameraCaptureBufferFormatControl_iid)
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/multimediakit/qcameracapturedestinationcontrol.cpp b/src/multimediakit/qcameracapturedestinationcontrol.cpp
new file mode 100644
index 000000000..3899d8d8c
--- /dev/null
+++ b/src/multimediakit/qcameracapturedestinationcontrol.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** 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 <qcameracapturedestinationcontrol.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCameraCaptureDestinationControl
+
+ \brief The QCameraCaptureDestinationControl class provides a control for setting capture destination.
+
+ Depending on backend capabilities capture to file, buffer or both can be supported.
+
+ \inmodule QtMultimediaKit
+ \ingroup camera
+
+
+
+ The interface name of QCameraCaptureDestinationControl is \c com.nokia.Qt.QCameraCaptureDestinationControl/1.0 as
+ defined in QCameraCaptureDestinationControl_iid.
+
+
+ \sa QMediaService::requestControl()
+ \since QtMobility 1.2
+*/
+
+/*!
+ \macro QCameraCaptureDestinationControl_iid
+
+ \c com.nokia.Qt.QCameraCaptureDestinationControl/1.0
+
+ Defines the interface name of the QCameraCaptureDestinationControl class.
+
+ \relates QCameraCaptureDestinationControl
+*/
+
+/*!
+ Constructs a new image capture destination control object with the given \a parent
+*/
+QCameraCaptureDestinationControl::QCameraCaptureDestinationControl(QObject *parent)
+ :QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys an image capture destination control.
+*/
+QCameraCaptureDestinationControl::~QCameraCaptureDestinationControl()
+{
+}
+
+/*!
+ \fn QCameraCaptureDestinationControl::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const
+
+ Returns true if the capture \a destination is supported; and false if it is not.
+ \since 1.2
+*/
+
+/*!
+ \fn QCameraCaptureDestinationControl::captureDestination() const
+
+ Returns the current capture \a destination. The default destination is QCameraImageCapture::CaptureToFile.
+ \since 1.2
+*/
+
+/*!
+ \fn QCameraCaptureDestinationControl::setCaptureDestination(QCameraImageCapture::CaptureDestinations destination)
+
+ Sets the capture \a destination.
+ \since 1.2
+*/
+
+/*!
+ \fn QCameraCaptureDestinationControl::captureDestinationChanged(QCameraImageCapture::CaptureDestinations destination)
+
+ Signals the image capture \a destination changed.
+ \since 1.2
+*/
+
+#include "moc_qcameracapturedestinationcontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qcameracapturedestinationcontrol.h b/src/multimediakit/qcameracapturedestinationcontrol.h
new file mode 100644
index 000000000..f53fad5e6
--- /dev/null
+++ b/src/multimediakit/qcameracapturedestinationcontrol.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** 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 QCAMERACAPTUREDESTINATIONCONTROL_H
+#define QCAMERACAPTUREDESTINATIONCONTROL_H
+
+#include <qmediacontrol.h>
+#include <qcameraimagecapture.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QCameraCaptureDestinationControl : public QMediaControl
+{
+ Q_OBJECT
+public:
+ ~QCameraCaptureDestinationControl();
+
+ virtual bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const = 0;
+ virtual QCameraImageCapture::CaptureDestinations captureDestination() const = 0;
+ virtual void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination) = 0;
+
+Q_SIGNALS:
+ void captureDestinationChanged(QCameraImageCapture::CaptureDestinations);
+
+protected:
+ QCameraCaptureDestinationControl(QObject* parent = 0);
+};
+
+#define QCameraCaptureDestinationControl_iid "com.nokia.Qt.QCameraCaptureDestinationControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QCameraCaptureDestinationControl, QCameraCaptureDestinationControl_iid)
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/multimediakit/qcameracontrol.cpp b/src/multimediakit/qcameracontrol.cpp
new file mode 100644
index 000000000..fdeb1d29a
--- /dev/null
+++ b/src/multimediakit/qcameracontrol.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <qcameracontrol.h>
+#include "qmediacontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCameraControl
+
+
+
+ \brief The QCameraControl class is an abstract base class for
+ classes that control still cameras or video cameras.
+
+ \inmodule QtMultimediaKit
+ \ingroup camera
+ \since 1.1
+
+ This service is provided by a QMediaService object via
+ QMediaService::control(). It is used by QCamera.
+
+ The interface name of QCameraControl is \c com.nokia.Qt.QCameraControl/1.0 as
+ defined in QCameraControl_iid.
+
+
+
+ \sa QMediaService::requestControl(), QCamera
+*/
+
+/*!
+ \macro QCameraControl_iid
+
+ \c com.nokia.Qt.QCameraControl/1.0
+
+ Defines the interface name of the QCameraControl class.
+
+ \relates QCameraControl
+*/
+
+/*!
+ Constructs a camera control object with \a parent.
+*/
+
+QCameraControl::QCameraControl(QObject *parent):
+ QMediaControl(*new QMediaControlPrivate, parent)
+{
+}
+
+/*!
+ Destruct the camera control object.
+*/
+
+QCameraControl::~QCameraControl()
+{
+}
+
+/*!
+ \fn QCameraControl::state() const
+
+ Returns the state of the camera service.
+
+ \since 1.1
+ \sa QCamera::state
+*/
+
+/*!
+ \fn QCameraControl::setState(QCamera::State state)
+
+ Sets the camera \a state.
+
+ State changes are synchronous and indicate user intention,
+ while camera status is used as a feedback mechanism to inform application about backend status.
+ Status changes are reported asynchronously with QCameraControl::statusChanged() signal.
+
+ \since 1.1
+ \sa QCamera::State
+*/
+
+/*!
+ \fn void QCameraControl::stateChanged(QCamera::State state)
+
+ Signal emitted when the camera \a state changes.
+
+ In most cases the state chage is caused by QCameraControl::setState(),
+ but if critical error has occurred the state changes to QCamera::UnloadedState.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraControl::status() const
+
+ Returns the status of the camera service.
+
+ \since 1.1
+ \sa QCamera::state
+*/
+
+/*!
+ \fn void QCameraControl::statusChanged(QCamera::Status status)
+
+ Signal emitted when the camera \a status changes.
+ \since 1.1
+*/
+
+
+/*!
+ \fn void QCameraControl::error(int error, const QString &errorString)
+
+ Signal emitted when an error occurs with error code \a error and
+ a description of the error \a errorString.
+ \since 1.1
+*/
+
+/*!
+ \fn Camera::CaptureMode QCameraControl::captureMode() const = 0
+
+ Returns the current capture mode.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraControl::setCaptureMode(QCamera::CaptureMode mode) = 0;
+
+ Sets the current capture \a mode.
+
+ The capture mode changes are synchronous and allowed in any camera state.
+
+ If the capture mode is changed while camera is active,
+ it's recommended to change status to QCamera::LoadedStatus
+ and start activating the camera in the next event loop
+ with the status changed to QCamera::StartingStatus.
+ This allows the capture settings to be applied before camera is started.
+ Than change the status to QCamera::StartedStatus when the capture mode change is done.
+ \since 1.1
+*/
+
+/*!
+ \fn bool QCameraControl::isCaptureModeSupported(QCamera::CaptureMode mode) const = 0;
+
+ Returns true if the capture \a mode is suported.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraControl::captureModeChanged(QCamera::CaptureMode mode)
+
+ Signal emitted when the camera capture \a mode changes.
+ \since 1.1
+ */
+
+/*!
+ \fn bool QCameraControl::canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const
+
+ Returns true if backend can effectively apply changing camera properties of \a changeType type
+ while the camera state is QCamera::Active and camera status matches \a status parameter.
+
+ If backend doesn't support applying this change in the active state, it will be stopped
+ before the settings are changed and restarted after.
+ Otherwise the backend should apply the change in the current state,
+ with the camera status indicating the progress, if necessary.
+ \since 1.1
+*/
+
+/*!
+ \enum QCameraControl::PropertyChangeType
+
+ \value CaptureMode Indicates the capture mode is changed.
+ \value ImageEncodingSettings Image encoder settings are changed, including resolution.
+ \value VideoEncodingSettings
+ Video encoder settings are changed, including audio, video and container settings.
+ \value Viewfinder Viewfinder is changed.
+*/
+
+#include "moc_qcameracontrol.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediakit/qcameracontrol.h b/src/multimediakit/qcameracontrol.h
new file mode 100644
index 000000000..a1830a5a3
--- /dev/null
+++ b/src/multimediakit/qcameracontrol.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCAMERACONTROL_H
+#define QCAMERACONTROL_H
+
+#include <qmediacontrol.h>
+#include <qmediaobject.h>
+
+#include <qcamera.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QCameraControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ enum PropertyChangeType {
+ CaptureMode = 1,
+ ImageEncodingSettings = 2,
+ VideoEncodingSettings = 3,
+ Viewfinder = 4
+ };
+
+ ~QCameraControl();
+
+ virtual QCamera::State state() const = 0;
+ virtual void setState(QCamera::State state) = 0;
+
+ virtual QCamera::Status status() const = 0;
+
+ virtual QCamera::CaptureMode captureMode() const = 0;
+ virtual void setCaptureMode(QCamera::CaptureMode) = 0;
+ virtual bool isCaptureModeSupported(QCamera::CaptureMode mode) const = 0;
+
+ virtual bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const = 0;
+
+Q_SIGNALS:
+ void stateChanged(QCamera::State);
+ void statusChanged(QCamera::Status);
+ void error(int error, const QString &errorString);
+ void captureModeChanged(QCamera::CaptureMode);
+
+protected:
+ QCameraControl(QObject* parent = 0);
+};
+
+#define QCameraControl_iid "com.nokia.Qt.QCameraControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QCameraControl, QCameraControl_iid)
+
+QT_END_NAMESPACE
+
+#endif // QCAMERACONTROL_H
+
diff --git a/src/multimediakit/qcameraexposure.cpp b/src/multimediakit/qcameraexposure.cpp
new file mode 100644
index 000000000..73266b5c1
--- /dev/null
+++ b/src/multimediakit/qcameraexposure.cpp
@@ -0,0 +1,646 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <qcameraexposure.h>
+#include <qcamera.h>
+
+#include <qmediaobject_p.h>
+#include <qcameraexposurecontrol.h>
+#include <qcameraflashcontrol.h>
+#include <qmetaobject.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCameraExposure
+
+
+ \brief The QCameraExposure class provides interface for exposure related camera settings.
+
+ \inmodule QtMultimediaKit
+ \ingroup camera
+ \since 1.1
+
+*/
+
+//#define DEBUG_EXPOSURE_CHANGES 1
+
+#ifdef DEBUG_EXPOSURE_CHANGES
+#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
+#endif
+
+namespace
+{
+class CameraExposureRegisterMetaTypes
+{
+public:
+ CameraExposureRegisterMetaTypes()
+ {
+ qRegisterMetaType<QCameraExposure::ExposureMode>("QCameraExposure::ExposureMode");
+ qRegisterMetaType<QCameraExposure::FlashModes>("QCameraExposure::FlashModes");
+ qRegisterMetaType<QCameraExposure::MeteringMode>("QCameraExposure::MeteringMode");
+ }
+} _registerCameraExposureMetaTypes;
+}
+
+
+
+class QCameraExposurePrivate
+{
+ Q_DECLARE_NON_CONST_PUBLIC(QCameraExposure)
+public:
+ void initControls();
+ QCameraExposure *q_ptr;
+
+ QCamera *camera;
+ QCameraExposureControl *exposureControl;
+ QCameraFlashControl *flashControl;
+
+ void _q_exposureParameterChanged(int parameter);
+ void _q_exposureParameterRangeChanged(int parameter);
+};
+
+void QCameraExposurePrivate::initControls()
+{
+ Q_Q(QCameraExposure);
+
+ QMediaService *service = camera->service();
+ exposureControl = 0;
+ flashControl = 0;
+ if (service) {
+ exposureControl = qobject_cast<QCameraExposureControl *>(service->requestControl(QCameraExposureControl_iid));
+ flashControl = qobject_cast<QCameraFlashControl *>(service->requestControl(QCameraFlashControl_iid));
+ }
+ if (exposureControl) {
+ q->connect(exposureControl, SIGNAL(exposureParameterChanged(int)),
+ q, SLOT(_q_exposureParameterChanged(int)));
+ q->connect(exposureControl, SIGNAL(exposureParameterRangeChanged(int)),
+ q, SLOT(_q_exposureParameterRangeChanged(int)));
+ }
+
+ if (flashControl)
+ q->connect(flashControl, SIGNAL(flashReady(bool)), q, SIGNAL(flashReady(bool)));
+}
+
+void QCameraExposurePrivate::_q_exposureParameterChanged(int parameter)
+{
+ Q_Q(QCameraExposure);
+
+#if DEBUG_EXPOSURE_CHANGES
+ qDebug() << "Exposure parameter changed:"
+ << ENUM_NAME(QCameraExposureControl, "ExposureParameter", parameter)
+ << exposureControl->exposureParameter(QCameraExposureControl::ExposureParameter(parameter));
+#endif
+
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ emit q->isoSensitivityChanged(q->isoSensitivity());
+ break;
+ case QCameraExposureControl::Aperture:
+ emit q->apertureChanged(q->aperture());
+ break;
+ case QCameraExposureControl::ShutterSpeed:
+ emit q->shutterSpeedChanged(q->shutterSpeed());
+ break;
+ case QCameraExposureControl::ExposureCompensation:
+ emit q->exposureCompensationChanged(q->exposureCompensation());
+ break;
+ }
+}
+
+void QCameraExposurePrivate::_q_exposureParameterRangeChanged(int parameter)
+{
+ Q_Q(QCameraExposure);
+
+ switch (parameter) {
+ case QCameraExposureControl::Aperture:
+ emit q->apertureRangeChanged();
+ break;
+ case QCameraExposureControl::ShutterSpeed:
+ emit q->shutterSpeedRangeChanged();
+ break;
+ }
+}
+
+/*!
+ Construct a QCameraExposure from service \a provider and \a parent.
+*/
+
+QCameraExposure::QCameraExposure(QCamera *parent):
+ QObject(parent), d_ptr(new QCameraExposurePrivate)
+{
+ Q_D(QCameraExposure);
+ d->camera = parent;
+ d->q_ptr = this;
+ d->initControls();
+}
+
+
+/*!
+ Destroys the camera exposure object.
+*/
+
+QCameraExposure::~QCameraExposure()
+{
+ Q_D(QCameraExposure);
+ if (d->exposureControl)
+ d->camera->service()->releaseControl(d->exposureControl);
+}
+
+/*!
+ Returns true if exposure settings are supported by this camera.
+ \since 1.1
+*/
+bool QCameraExposure::isAvailable() const
+{
+ return d_func()->exposureControl != 0;
+}
+
+
+/*!
+ \property QCameraExposure::flashMode
+ \brief The flash mode being used.
+
+ Usually the single QCameraExposure::FlashMode flag is used,
+ but some non conflicting flags combination are also allowed,
+ like QCameraExposure::FlashManual | QCameraExposure::FlashSlowSyncRearCurtain.
+
+ \since 1.1
+ \sa QCameraExposure::isFlashModeSupported(), QCameraExposure::isFlashReady()
+*/
+
+QCameraExposure::FlashModes QCameraExposure::flashMode() const
+{
+ return d_func()->flashControl ? d_func()->flashControl->flashMode() : QCameraExposure::FlashOff;
+}
+
+void QCameraExposure::setFlashMode(QCameraExposure::FlashModes mode)
+{
+ if (d_func()->flashControl)
+ d_func()->flashControl->setFlashMode(mode);
+}
+
+/*!
+ Returns true if the flash \a mode is supported.
+ \since 1.1
+*/
+
+bool QCameraExposure::isFlashModeSupported(QCameraExposure::FlashModes mode) const
+{
+ return d_func()->flashControl ? d_func()->flashControl->isFlashModeSupported(mode) : false;
+}
+
+/*!
+ Returns true if flash is charged.
+*/
+
+bool QCameraExposure::isFlashReady() const
+{
+ return d_func()->flashControl ? d_func()->flashControl->isFlashReady() : false;
+}
+
+
+/*!
+ \property QCameraExposure::exposureMode
+ \brief The exposure mode being used.
+
+ \since 1.1
+ \sa QCameraExposure::isExposureModeSupported()
+*/
+
+QCameraExposure::ExposureMode QCameraExposure::exposureMode() const
+{
+ return d_func()->exposureControl ? d_func()->exposureControl->exposureMode() : QCameraExposure::ExposureAuto;
+}
+
+void QCameraExposure::setExposureMode(QCameraExposure::ExposureMode mode)
+{
+ if (d_func()->exposureControl)
+ d_func()->exposureControl->setExposureMode(mode);
+}
+
+/*!
+ Returns true if the exposure \a mode is supported.
+ \since 1.1
+*/
+
+bool QCameraExposure::isExposureModeSupported(QCameraExposure::ExposureMode mode) const
+{
+ return d_func()->exposureControl ?
+ d_func()->exposureControl->isExposureModeSupported(mode) : false;
+}
+
+/*!
+ \property QCameraExposure::exposureCompensation
+ \brief Exposure compensation in EV units.
+
+ Exposure compensation property allows to adjust the automatically calculated exposure.
+ \since 1.1
+*/
+
+qreal QCameraExposure::exposureCompensation() const
+{
+ if (d_func()->exposureControl)
+ return d_func()->exposureControl->exposureParameter(QCameraExposureControl::ExposureCompensation).toReal();
+ else
+ return 0;
+}
+
+void QCameraExposure::setExposureCompensation(qreal ev)
+{
+ if (d_func()->exposureControl)
+ d_func()->exposureControl->setExposureParameter(QCameraExposureControl::ExposureCompensation, QVariant(ev));
+}
+
+/*!
+ \property QCameraExposure::meteringMode
+ \brief The metering mode being used.
+
+ \since 1.1
+ \sa QCameraExposure::isMeteringModeSupported()
+*/
+
+QCameraExposure::MeteringMode QCameraExposure::meteringMode() const
+{
+ return d_func()->exposureControl ? d_func()->exposureControl->meteringMode() : QCameraExposure::MeteringMatrix;
+}
+
+void QCameraExposure::setMeteringMode(QCameraExposure::MeteringMode mode)
+{
+ if (d_func()->exposureControl)
+ d_func()->exposureControl->setMeteringMode(mode);
+}
+
+/*!
+ Returns true if the metering \a mode is supported.
+ \since 1.1
+*/
+bool QCameraExposure::isMeteringModeSupported(QCameraExposure::MeteringMode mode) const
+{
+ return d_func()->exposureControl ? d_func()->exposureControl->isMeteringModeSupported(mode) : false;
+}
+
+int QCameraExposure::isoSensitivity() const
+{
+ if (d_func()->exposureControl)
+ return d_func()->exposureControl->exposureParameter(QCameraExposureControl::ISO).toInt();
+
+ return -1;
+}
+
+/*!
+ Returns the list of ISO senitivities camera supports.
+
+ If the camera supports arbitrary ISO sensitivities within the supported range,
+ *\a continuous is set to true, otherwise *\a continuous is set to false.
+ \since 1.1
+*/
+QList<int> QCameraExposure::supportedIsoSensitivities(bool *continuous) const
+{
+ QList<int> res;
+ QCameraExposureControl *control = d_func()->exposureControl;
+
+ if (!control)
+ return res;
+
+ foreach (const QVariant &value,
+ control->supportedParameterRange(QCameraExposureControl::ISO)) {
+ bool ok = false;
+ int intValue = value.toInt(&ok);
+ if (ok)
+ res.append(intValue);
+ else
+ qWarning() << "Incompatible ISO value type, int is expected";
+ }
+
+ if (continuous)
+ *continuous = control->exposureParameterFlags(QCameraExposureControl::ISO) &
+ QCameraExposureControl::ContinuousRange;
+
+ return res;
+}
+
+/*!
+ \fn QCameraExposure::setManualIsoSensitivity(int iso)
+ Sets the manual sensitivity to \a iso
+ \since 1.1
+*/
+
+void QCameraExposure::setManualIsoSensitivity(int iso)
+{
+ if (d_func()->exposureControl)
+ d_func()->exposureControl->setExposureParameter(QCameraExposureControl::ISO, QVariant(iso));
+}
+
+/*!
+ \fn QCameraExposure::setAutoIsoSensitivity()
+ Turn on auto sensitivity
+ \since 1.1
+*/
+
+void QCameraExposure::setAutoIsoSensitivity()
+{
+ if (d_func()->exposureControl)
+ d_func()->exposureControl->setExposureParameter(QCameraExposureControl::ISO, QVariant());
+}
+
+/*!
+ \property QCameraExposure::shutterSpeed
+ \brief Camera's shutter speed in seconds.
+
+ \since 1.1
+ \sa supportedShutterSpeeds(), setAutoShutterSpeed(), setManualShutterSpeed()
+*/
+
+/*!
+ \fn QCameraExposure::shutterSpeedChanged(qreal speed)
+
+ Signals that a camera's shutter \a speed has changed.
+ \since 1.1
+*/
+
+/*!
+ \property QCameraExposure::isoSensitivity
+ \brief The sensor ISO sensitivity.
+
+ \sa supportedIsoSensitivities(), setAutoIsoSensitivity(), setManualIsoSensitivity()
+ \since 1.1
+*/
+
+/*!
+ \property QCameraExposure::aperture
+ \brief Lens aperture is specified as an F number, the ratio of the focal length to effective aperture diameter.
+
+ \since 1.1
+ \sa supportedApertures(), setAutoAperture(), setManualAperture()
+*/
+
+
+qreal QCameraExposure::aperture() const
+{
+ if (d_func()->exposureControl)
+ return d_func()->exposureControl->exposureParameter(QCameraExposureControl::Aperture).toReal();
+
+ return -1.0;
+}
+
+/*!
+ Returns the list of aperture values camera supports.
+ The apertures list can change depending on the focal length,
+ in such a case the apertureRangeChanged() signal is emitted.
+
+ If the camera supports arbitrary aperture values within the supported range,
+ *\a continuous is set to true, otherwise *\a continuous is set to false.
+ \since 1.1
+*/
+QList<qreal> QCameraExposure::supportedApertures(bool * continuous) const
+{
+ QList<qreal> res;
+ QCameraExposureControl *control = d_func()->exposureControl;
+
+ if (!control)
+ return res;
+
+ foreach (const QVariant &value,
+ control->supportedParameterRange(QCameraExposureControl::Aperture)) {
+ bool ok = false;
+ qreal realValue = value.toReal(&ok);
+ if (ok)
+ res.append(realValue);
+ else
+ qWarning() << "Incompatible aperture value type, qreal is expected";
+ }
+
+ if (continuous)
+ *continuous = control->exposureParameterFlags(QCameraExposureControl::Aperture) &
+ QCameraExposureControl::ContinuousRange;
+
+ return res;
+}
+
+/*!
+ \fn QCameraExposure::setManualAperture(qreal aperture)
+ Sets the manual camera \a aperture value.
+ \since 1.1
+*/
+
+void QCameraExposure::setManualAperture(qreal aperture)
+{
+ if (d_func()->exposureControl)
+ d_func()->exposureControl->setExposureParameter(QCameraExposureControl::Aperture, QVariant(aperture));
+}
+
+/*!
+ \fn QCameraExposure::setAutoAperture()
+ Turn on auto aperture
+ \since 1.1
+*/
+
+void QCameraExposure::setAutoAperture()
+{
+ if (d_func()->exposureControl)
+ d_func()->exposureControl->setExposureParameter(QCameraExposureControl::Aperture, QVariant());
+}
+
+/*!
+ Returns the current shutter speed in seconds.
+ \since 1.1
+*/
+
+qreal QCameraExposure::shutterSpeed() const
+{
+ if (d_func()->exposureControl)
+ return d_func()->exposureControl->exposureParameter(QCameraExposureControl::ShutterSpeed).toReal();
+
+ return -1.0;
+}
+
+/*!
+ Returns the list of shutter speed values in seconds camera supports.
+
+ If the camera supports arbitrary shutter speed values within the supported range,
+ *\a continuous is set to true, otherwise *\a continuous is set to false.
+ \since 1.1
+*/
+QList<qreal> QCameraExposure::supportedShutterSpeeds(bool *continuous) const
+{
+ QList<qreal> res;
+
+ QCameraExposureControl *control = d_func()->exposureControl;
+ if (!control)
+ return res;
+
+ foreach (const QVariant &value,
+ control->supportedParameterRange(QCameraExposureControl::ShutterSpeed)) {
+ bool ok = false;
+ qreal realValue = value.toReal(&ok);
+ if (ok)
+ res.append(realValue);
+ else
+ qWarning() << "Incompatible shutter speed value type, qreal is expected";
+ }
+
+ if (continuous)
+ *continuous = control->exposureParameterFlags(QCameraExposureControl::ShutterSpeed) &
+ QCameraExposureControl::ContinuousRange;
+
+ return res;
+}
+
+/*!
+ Set the manual shutter speed to \a seconds
+ \since 1.1
+*/
+
+void QCameraExposure::setManualShutterSpeed(qreal seconds)
+{
+ if (d_func()->exposureControl)
+ d_func()->exposureControl->setExposureParameter(QCameraExposureControl::ShutterSpeed, QVariant(seconds));
+}
+
+/*!
+ Turn on auto shutter speed
+ \since 1.1
+*/
+
+void QCameraExposure::setAutoShutterSpeed()
+{
+ if (d_func()->exposureControl)
+ d_func()->exposureControl->setExposureParameter(QCameraExposureControl::ShutterSpeed, QVariant());
+}
+
+
+/*!
+ \enum QCameraExposure::FlashMode
+
+ \value FlashOff Flash is Off.
+ \value FlashOn Flash is On.
+ \value FlashAuto Automatic flash.
+ \value FlashRedEyeReduction Red eye reduction flash.
+ \value FlashFill Use flash to fillin shadows.
+ \value FlashTorch Constant light source, useful for focusing and video capture.
+ \value FlashSlowSyncFrontCurtain
+ Use the flash in conjunction with a slow shutter speed.
+ This mode allows better exposure of distant objects and/or motion blur effect.
+ \value FlashSlowSyncRearCurtain
+ The similar mode to FlashSlowSyncFrontCurtain but flash is fired at the end of exposure.
+ \value FlashManual Flash power is manualy set.
+*/
+
+/*!
+ \enum QCameraExposure::ExposureMode
+
+ \value ExposureManual Manual mode.
+ \value ExposureAuto Automatic mode.
+ \value ExposureNight Night mode.
+ \value ExposureBacklight Backlight exposure mode.
+ \value ExposureSpotlight Spotlight exposure mode.
+ \value ExposureSports Spots exposure mode.
+ \value ExposureSnow Snow exposure mode.
+ \value ExposureBeach Beach exposure mode.
+ \value ExposureLargeAperture Use larger aperture with small depth of field.
+ \value ExposureSmallAperture Use smaller aperture.
+ \value ExposurePortrait Portrait exposure mode.
+ \value ExposureModeVendor The base value for device specific exposure modes.
+*/
+
+/*!
+ \enum QCameraExposure::MeteringMode
+
+ \value MeteringAverage Center weighted average metering mode.
+ \value MeteringSpot Spot metering mode.
+ \value MeteringMatrix Matrix metering mode.
+*/
+
+/*!
+ \property QCameraExposure::flashReady
+ \brief Indicates if the flash is charged and ready to use.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraExposure::flashReady(bool ready)
+
+ Signal the flash \a ready status has changed.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraExposure::apertureChanged(qreal value)
+
+ Signal emitted when aperature changes to \a value.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraExposure::apertureRangeChanged()
+
+ Signal emitted when aperature range has changed.
+ \since 1.1
+*/
+
+
+/*!
+ \fn void QCameraExposure::shutterSpeedRangeChanged()
+
+ Signal emitted when the shutter speed range has changed.
+ \since 1.1
+*/
+
+
+/*!
+ \fn void QCameraExposure::isoSensitivityChanged(int value)
+
+ Signal emitted when sensitivity changes to \a value.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraExposure::exposureCompensationChanged(qreal value)
+
+ Signal emitted when the exposure compensation changes to \a value.
+ \since 1.1
+*/
+
+#include "moc_qcameraexposure.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediakit/qcameraexposure.h b/src/multimediakit/qcameraexposure.h
new file mode 100644
index 000000000..6da69afa2
--- /dev/null
+++ b/src/multimediakit/qcameraexposure.h
@@ -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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCAMERAEXPOSURE_H
+#define QCAMERAEXPOSURE_H
+
+#include <qmediaobject.h>
+#include <qmediaenumdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCamera;
+class QCameraExposurePrivate;
+
+class Q_MULTIMEDIA_EXPORT QCameraExposure : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal aperture READ aperture NOTIFY apertureChanged)
+ Q_PROPERTY(qreal shutterSpeed READ shutterSpeed NOTIFY shutterSpeedChanged)
+ Q_PROPERTY(int isoSensitivity READ isoSensitivity NOTIFY isoSensitivityChanged)
+ Q_PROPERTY(qreal exposureCompensation READ exposureCompensation WRITE setExposureCompensation NOTIFY exposureCompensationChanged)
+ Q_PROPERTY(bool flashReady READ isFlashReady NOTIFY flashReady)
+ Q_PROPERTY(QCameraExposure::FlashModes flashMode READ flashMode WRITE setFlashMode)
+ Q_PROPERTY(QCameraExposure::ExposureMode exposureMode READ exposureMode WRITE setExposureMode)
+ Q_PROPERTY(QCameraExposure::MeteringMode meteringMode READ meteringMode WRITE setMeteringMode)
+
+ Q_ENUMS(FlashMode)
+ Q_ENUMS(ExposureMode)
+ Q_ENUMS(MeteringMode)
+public:
+ enum FlashMode {
+ FlashAuto = 0x1,
+ FlashOff = 0x2,
+ FlashOn = 0x4,
+ FlashRedEyeReduction = 0x8,
+ FlashFill = 0x10,
+ FlashTorch = 0x20,
+ FlashSlowSyncFrontCurtain = 0x40,
+ FlashSlowSyncRearCurtain = 0x80,
+ FlashManual = 0x100
+ };
+ Q_DECLARE_FLAGS(FlashModes, FlashMode)
+
+ enum ExposureMode {
+ ExposureAuto = 0,
+ ExposureManual = 1,
+ ExposurePortrait = 2,
+ ExposureNight = 3,
+ ExposureBacklight = 4,
+ ExposureSpotlight = 5,
+ ExposureSports = 6,
+ ExposureSnow = 7,
+ ExposureBeach = 8,
+ ExposureLargeAperture = 9,
+ ExposureSmallAperture = 10,
+ ExposureModeVendor = 1000
+ };
+
+ enum MeteringMode {
+ MeteringMatrix = 1,
+ MeteringAverage = 2,
+ MeteringSpot = 3
+ };
+
+ bool isAvailable() const;
+
+ FlashModes flashMode() const;
+ bool isFlashModeSupported(FlashModes mode) const;
+ bool isFlashReady() const;
+
+ ExposureMode exposureMode() const;
+ bool isExposureModeSupported(ExposureMode mode) const;
+
+ qreal exposureCompensation() const;
+
+ MeteringMode meteringMode() const;
+
+ bool isMeteringModeSupported(MeteringMode mode) const;
+
+ int isoSensitivity() const;
+ QList<int> supportedIsoSensitivities(bool *continuous = 0) const;
+
+ qreal aperture() const;
+ QList<qreal> supportedApertures(bool *continuous = 0) const;
+
+ qreal shutterSpeed() const;
+ QList<qreal> supportedShutterSpeeds(bool *continuous = 0) const;
+
+public Q_SLOTS:
+ void setFlashMode(FlashModes mode);
+ void setExposureMode(ExposureMode mode);
+
+ void setExposureCompensation(qreal ev);
+
+ void setMeteringMode(MeteringMode mode);
+
+ void setManualIsoSensitivity(int iso);
+ void setAutoIsoSensitivity();
+
+ void setManualAperture(qreal aperture);
+ void setAutoAperture();
+
+ void setManualShutterSpeed(qreal seconds);
+ void setAutoShutterSpeed();
+
+Q_SIGNALS:
+ void flashReady(bool);
+
+ void apertureChanged(qreal);
+ void apertureRangeChanged();
+ void shutterSpeedChanged(qreal);
+ void shutterSpeedRangeChanged();
+ void isoSensitivityChanged(int);
+ void exposureCompensationChanged(qreal);
+
+private:
+ friend class QCamera;
+ explicit QCameraExposure(QCamera *parent = 0);
+ virtual ~QCameraExposure();
+
+ Q_DISABLE_COPY(QCameraExposure)
+ Q_DECLARE_PRIVATE(QCameraExposure)
+ Q_PRIVATE_SLOT(d_func(), void _q_exposureParameterChanged(int))
+ Q_PRIVATE_SLOT(d_func(), void _q_exposureParameterRangeChanged(int))
+ QCameraExposurePrivate *d_ptr;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QCameraExposure::FlashModes)
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QCameraExposure::ExposureMode)
+Q_DECLARE_METATYPE(QCameraExposure::FlashModes)
+Q_DECLARE_METATYPE(QCameraExposure::MeteringMode)
+
+Q_MEDIA_ENUM_DEBUG(QCameraExposure, ExposureMode)
+Q_MEDIA_ENUM_DEBUG(QCameraExposure, FlashMode)
+Q_MEDIA_ENUM_DEBUG(QCameraExposure, MeteringMode)
+
+#endif // QCAMERAEXPOSURE_H
diff --git a/src/multimediakit/qcameraexposurecontrol.cpp b/src/multimediakit/qcameraexposurecontrol.cpp
new file mode 100644
index 000000000..5df107e75
--- /dev/null
+++ b/src/multimediakit/qcameraexposurecontrol.cpp
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <qcameraexposurecontrol.h>
+#include "qmediacontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCameraExposureControl
+
+ \brief The QCameraExposureControl class allows controlling camera exposure parameters.
+
+ \inmodule QtMultimediaKit
+ \ingroup camera
+ \since 1.1
+
+ You can adjust a number of parameters that will affect images and video taken with
+ the corresponding QCamera object.
+
+ There are a number of different parameters that can be adjusted, including:
+
+ \table
+ \row
+ \header
+ \
+
+ \endtable
+
+ The interface name of QCameraExposureControl is \c com.nokia.Qt.QCameraExposureControl/1.0 as
+ defined in QCameraExposureControl_iid.
+
+ \sa QCamera
+*/
+
+/*!
+ \macro QCameraExposureControl_iid
+
+ \c com.nokia.Qt.QCameraExposureControl/1.0
+
+ Defines the interface name of the QCameraExposureControl class.
+
+ \relates QCameraExposureControl
+*/
+
+/*!
+ Constructs a camera exposure control object with \a parent.
+*/
+QCameraExposureControl::QCameraExposureControl(QObject *parent):
+ QMediaControl(*new QMediaControlPrivate, parent)
+{
+}
+
+/*!
+ Destroys the camera control object.
+*/
+QCameraExposureControl::~QCameraExposureControl()
+{
+}
+
+/*!
+ \fn QCamera::ExposureMode QCameraExposureControl::exposureMode() const
+
+ Returns the exposure mode.
+ \since 1.1
+*/
+
+
+/*!
+ \fn void QCameraExposureControl::setExposureMode(QCameraExposure::ExposureMode mode)
+
+ Set the exposure mode to \a mode.
+ \since 1.1
+*/
+
+
+/*!
+ \fn bool QCameraExposureControl::isExposureModeSupported(QCameraExposure::ExposureMode mode) const
+
+ Returns true if the exposure \a mode is supported.
+ \since 1.1
+*/
+
+
+/*!
+ \fn QCameraExposure::MeteringMode QCameraExposureControl::meteringMode() const
+ Returns the current metering mode.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraExposureControl::setMeteringMode(QCameraExposure::MeteringMode mode)
+
+ Set the metering mode to \a mode.
+ \since 1.1
+*/
+
+
+/*!
+ \fn bool QCameraExposureControl::isMeteringModeSupported(QCameraExposure::MeteringMode mode) const
+ Returns true if the metering \a mode is supported.
+ \since 1.1
+*/
+
+/*!
+ \enum QCameraExposureControl::ExposureParameter
+ \value InvalidParameter
+ Parameter is invalid.
+ \value ISO
+ Camera ISO sensitivity, specified as integer value.
+ \value Aperture
+ Lens aperture is specified as an qreal F number.
+ The supported apertures list can change depending on the focal length,
+ in such a case the exposureParameterRangeChanged() signal is emitted.
+ \value ShutterSpeed
+ Shutter speed in seconds, specified as qreal.
+ \value ExposureCompensation
+ Exposure compensation, specified as qreal EV value.
+ \value FlashPower
+ Manual flash power, specified as qreal value.
+ Accepted power range is [0..1.0],
+ with 0 value means no flash and 1.0 corresponds to full flash power.
+
+ This value is only used in the \l{QCameraExposure::FlashManual}{manual flash mode}.
+ \value FlashCompensation
+ Flash compensation, specified as qreal EV value.
+ \value ExtendedExposureParameter
+ The base value for platform specific extended parameters.
+ For such parameters the sequential values starting from ExtendedExposureParameter shuld be used.
+*/
+
+/*!
+ \enum QCameraExposureControl::ParameterFlag
+ \value AutomaticValue
+ Use the automatic values for parameters.
+ \value ReadOnly
+ Parameters are read only.
+ \value ContinuousRange
+ Parameters are continuous in their range.
+*/
+
+/*!
+ \fn QCameraExposureControl::isParameterSupported(ExposureParameter parameter) const
+
+ Returns true is exposure \a parameter is supported by backend.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraExposureControl::exposureParameter(ExposureParameter parameter) const
+
+ Returns the exposure \a parameter value, or invalid QVariant() if the value is unknown or not supported.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraExposureControl::exposureParameterFlags(ExposureParameter parameter) const
+
+ Returns the properties of exposure \a parameter.
+ \since 1.1
+*/
+
+
+/*!
+ \fn QCameraExposureControl::supportedParameterRange(ExposureParameter parameter) const
+
+ Returns the list of supported \a parameter values;
+ \since 1.1
+*/
+
+/*!
+ \fn bool QCameraExposureControl::setExposureParameter(ExposureParameter parameter, const QVariant& value)
+
+ Set the exposure \a parameter to \a value.
+ If a null or invalid QVariant is passed, backend should choose the value automatically,
+ and if possible report the actual value to user with QCameraExposureControl::exposureParameter().
+
+ Returns true if parameter is supported and value is correct.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraExposureControl::extendedParameterName(ExposureParameter parameter)
+
+ Returns the extended exposure \a parameter name.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraExposureControl::flashReady(bool ready)
+
+ Signal emitted when flash state changes, flash is charged \a ready.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraExposureControl::exposureParameterChanged(int parameter)
+
+ Signal emitted when the exposure \a parameter has changed.
+ \since 1.1
+*/
+
+/*!
+
+ \fn void QCameraExposureControl::exposureParameterRangeChanged(int parameter)
+
+ Signal emitted when the exposure \a parameter range has changed.
+ \since 1.1
+*/
+
+
+#include "moc_qcameraexposurecontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qcameraexposurecontrol.h b/src/multimediakit/qcameraexposurecontrol.h
new file mode 100644
index 000000000..5d8a59c67
--- /dev/null
+++ b/src/multimediakit/qcameraexposurecontrol.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCAMERAEXPOSURECONTROL_H
+#define QCAMERAEXPOSURECONTROL_H
+
+#include <qmediacontrol.h>
+#include <qmediaobject.h>
+
+#include <qcameraexposure.h>
+#include <qcamera.h>
+#include <qmediaenumdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QCameraExposureControl : public QMediaControl
+{
+ Q_OBJECT
+ Q_ENUMS(ExposureParameter)
+
+public:
+ ~QCameraExposureControl();
+
+ enum ExposureParameter {
+ InvalidParameter = 0,
+ ISO = 1,
+ Aperture = 2,
+ ShutterSpeed = 3,
+ ExposureCompensation = 4,
+ FlashPower = 5,
+ FlashCompensation = 6,
+ ExtendedExposureParameter = 1000
+ };
+
+ enum ParameterFlag {
+ AutomaticValue = 0x01,
+ ReadOnly = 0x02,
+ ContinuousRange = 0x04
+ };
+ Q_DECLARE_FLAGS(ParameterFlags, ParameterFlag)
+
+ virtual QCameraExposure::ExposureMode exposureMode() const = 0;
+ virtual void setExposureMode(QCameraExposure::ExposureMode mode) = 0;
+ virtual bool isExposureModeSupported(QCameraExposure::ExposureMode mode) const = 0;
+
+ virtual QCameraExposure::MeteringMode meteringMode() const = 0;
+ virtual void setMeteringMode(QCameraExposure::MeteringMode mode) = 0;
+ virtual bool isMeteringModeSupported(QCameraExposure::MeteringMode mode) const = 0;
+
+ virtual bool isParameterSupported(ExposureParameter parameter) const = 0;
+ virtual QVariant exposureParameter(ExposureParameter parameter) const = 0;
+ virtual ParameterFlags exposureParameterFlags(ExposureParameter parameter) const = 0;
+ virtual QVariantList supportedParameterRange(ExposureParameter parameter) const = 0;
+ virtual bool setExposureParameter(ExposureParameter parameter, const QVariant& value) = 0;
+
+ virtual QString extendedParameterName(ExposureParameter parameter) = 0;
+
+Q_SIGNALS:
+ void flashReady(bool);
+
+ void exposureParameterChanged(int parameter);
+ void exposureParameterRangeChanged(int parameter);
+
+protected:
+ QCameraExposureControl(QObject* parent = 0);
+};
+
+#define QCameraExposureControl_iid "com.nokia.Qt.QCameraExposureControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QCameraExposureControl, QCameraExposureControl_iid)
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QCameraExposureControl::ParameterFlags)
+
+Q_MEDIA_ENUM_DEBUG(QCameraExposureControl, ExposureParameter)
+
+QT_END_NAMESPACE
+
+#endif // QCAMERAEXPOSURECONTROL_H
+
diff --git a/src/multimediakit/qcameraflashcontrol.cpp b/src/multimediakit/qcameraflashcontrol.cpp
new file mode 100644
index 000000000..000cd28af
--- /dev/null
+++ b/src/multimediakit/qcameraflashcontrol.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qcameraflashcontrol.h>
+#include "qmediacontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCameraFlashControl
+
+ \brief The QCameraFlashControl class allows controlling a camera's flash.
+
+ \ingroup camera
+ \inmodule QtMultimediaKit
+ \since 1.1
+
+ \inmodule QtMultimediaKit
+
+ You can set the type of flash effect used when an image is captured, and test to see
+ if the flash hardware is ready to fire.
+
+ You can retrieve this control from the camera object in the usual way:
+
+ XXX snippet for retrieving control
+
+ Some camera devices may not have flash hardware, or may not be configurable. In that
+ case, there will be no QCameraFlashControl available.
+
+ The interface name of QCameraFlashControl is \c com.nokia.Qt.QCameraFlashControl/1.0 as
+ defined in QCameraFlashControl_iid.
+
+ \sa QCamera
+*/
+
+/*!
+ \macro QCameraFlashControl_iid
+
+ \c com.nokia.Qt.QCameraFlashControl/1.0
+
+ Defines the interface name of the QCameraFlashControl class.
+
+ \relates QCameraFlashControl
+*/
+
+/*!
+ Constructs a camera flash control object with \a parent.
+*/
+QCameraFlashControl::QCameraFlashControl(QObject *parent):
+ QMediaControl(*new QMediaControlPrivate, parent)
+{
+}
+
+/*!
+ Destroys the camera control object.
+*/
+QCameraFlashControl::~QCameraFlashControl()
+{
+}
+
+/*!
+ \fn QCamera::FlashModes QCameraFlashControl::flashMode() const
+
+ Returns the current flash mode.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraFlashControl::setFlashMode(QCameraExposure::FlashModes mode)
+
+ Set the current flash \a mode.
+
+ Usually a single QCameraExposure::FlashMode flag is used,
+ but some non conflicting flags combination are also allowed,
+ like QCameraExposure::FlashManual | QCameraExposure::FlashSlowSyncRearCurtain.
+ \since 1.1
+*/
+
+
+/*!
+ \fn QCameraFlashControl::isFlashModeSupported(QCameraExposure::FlashModes mode) const
+
+ Return true if the reqested flash \a mode is supported.
+ Some QCameraExposure::FlashMode values can be combined,
+ for example QCameraExposure::FlashManual | QCameraExposure::FlashSlowSyncRearCurtain
+ \since 1.1
+*/
+
+/*!
+ \fn bool QCameraFlashControl::isFlashReady() const
+
+ Returns true if flash is charged.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraFlashControl::flashReady(bool ready)
+
+ Signal emitted when flash state changes to \a ready.
+ \since 1.1
+*/
+
+#include "moc_qcameraflashcontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qcameraflashcontrol.h b/src/multimediakit/qcameraflashcontrol.h
new file mode 100644
index 000000000..8f203ae89
--- /dev/null
+++ b/src/multimediakit/qcameraflashcontrol.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCAMERAFLASHCONTROL_H
+#define QCAMERAFLASHCONTROL_H
+
+#include <qmediacontrol.h>
+#include <qmediaobject.h>
+
+#include <qcameraexposure.h>
+#include <qcamera.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QCameraFlashControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ ~QCameraFlashControl();
+
+ virtual QCameraExposure::FlashModes flashMode() const = 0;
+ virtual void setFlashMode(QCameraExposure::FlashModes mode) = 0;
+ virtual bool isFlashModeSupported(QCameraExposure::FlashModes mode) const = 0;
+
+ virtual bool isFlashReady() const = 0;
+
+Q_SIGNALS:
+ void flashReady(bool);
+
+protected:
+ QCameraFlashControl(QObject* parent = 0);
+};
+
+#define QCameraFlashControl_iid "com.nokia.Qt.QCameraFlashControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QCameraFlashControl, QCameraFlashControl_iid)
+
+QT_END_NAMESPACE
+
+#endif // QCAMERAFLASHCONTROL_H
+
diff --git a/src/multimediakit/qcamerafocus.cpp b/src/multimediakit/qcamerafocus.cpp
new file mode 100644
index 000000000..ccb157c0e
--- /dev/null
+++ b/src/multimediakit/qcamerafocus.cpp
@@ -0,0 +1,478 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <qcamera.h>
+#include <qcamerafocus.h>
+
+#include <qmediaobject_p.h>
+#include <qcameracontrol.h>
+#include <qcameraexposurecontrol.h>
+#include <qcamerafocuscontrol.h>
+#include <qmediarecordercontrol.h>
+#include <qcameraimagecapturecontrol.h>
+#include <qvideodevicecontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace
+{
+class CameraFocusRegisterMetaTypes
+{
+public:
+ CameraFocusRegisterMetaTypes()
+ {
+ qRegisterMetaType<QCameraFocus::FocusModes>("QCameraFocus::FocusModes");
+ qRegisterMetaType<QCameraFocus::FocusPointMode>("QCameraFocus::FocusPointMode");
+ }
+} _registerCameraFocusMetaTypes;
+}
+
+
+class QCameraFocusZoneData : public QSharedData
+{
+public:
+ QCameraFocusZoneData():
+ status(QCameraFocusZone::Invalid)
+ {
+
+ }
+
+ QCameraFocusZoneData(const QRectF &_area, QCameraFocusZone::FocusZoneStatus _status):
+ area(_area),
+ status(_status)
+ {
+
+ }
+
+
+ QCameraFocusZoneData(const QCameraFocusZoneData &other):
+ QSharedData(other),
+ area(other.area),
+ status(other.status)
+ {
+ }
+
+ QCameraFocusZoneData& operator=(const QCameraFocusZoneData &other)
+ {
+ area = other.area;
+ status = other.status;
+ return *this;
+ }
+
+ QRectF area;
+ QCameraFocusZone::FocusZoneStatus status;
+};
+
+QCameraFocusZone::QCameraFocusZone()
+ :d(new QCameraFocusZoneData)
+{
+
+}
+
+QCameraFocusZone::QCameraFocusZone(const QRectF &area, QCameraFocusZone::FocusZoneStatus status)
+ :d(new QCameraFocusZoneData(area, status))
+{
+}
+
+QCameraFocusZone::QCameraFocusZone(const QCameraFocusZone &other)
+ :d(other.d)
+{
+
+}
+
+QCameraFocusZone::~QCameraFocusZone()
+{
+
+}
+
+QCameraFocusZone& QCameraFocusZone::operator=(const QCameraFocusZone &other)
+{
+ d = other.d;
+ return *this;
+}
+
+bool QCameraFocusZone::operator==(const QCameraFocusZone &other) const
+{
+ return d == other.d ||
+ (d->area == other.d->area && d->status == other.d->status);
+}
+
+bool QCameraFocusZone::operator!=(const QCameraFocusZone &other) const
+{
+ return !(*this == other);
+}
+
+bool QCameraFocusZone::isValid() const
+{
+ return d->status != Invalid && !d->area.isValid();
+}
+
+QRectF QCameraFocusZone::area() const
+{
+ return d->area;
+}
+
+QCameraFocusZone::FocusZoneStatus QCameraFocusZone::status() const
+{
+ return d->status;
+}
+
+void QCameraFocusZone::setStatus(QCameraFocusZone::FocusZoneStatus status)
+{
+ d->status = status;
+}
+
+
+/*!
+ \class QCameraFocus
+
+
+ \brief The QCameraFocus class provides interface for
+ focus and zoom related camera settings.
+
+ \inmodule QtMultimediaKit
+ \ingroup camera
+ \since 1.1
+
+*/
+
+
+class QCameraFocusPrivate : public QMediaObjectPrivate
+{
+ Q_DECLARE_NON_CONST_PUBLIC(QCameraFocus)
+public:
+ void initControls();
+
+ QCameraFocus *q_ptr;
+
+ QCamera *camera;
+ QCameraFocusControl *focusControl;
+};
+
+
+void QCameraFocusPrivate::initControls()
+{
+ Q_Q(QCameraFocus);
+
+ focusControl = 0;
+
+ QMediaService *service = camera->service();
+ if (service)
+ focusControl = qobject_cast<QCameraFocusControl *>(service->requestControl(QCameraFocusControl_iid));
+
+ if (focusControl) {
+ q->connect(focusControl, SIGNAL(opticalZoomChanged(qreal)), q, SIGNAL(opticalZoomChanged(qreal)));
+ q->connect(focusControl, SIGNAL(digitalZoomChanged(qreal)), q, SIGNAL(digitalZoomChanged(qreal)));
+ q->connect(focusControl, SIGNAL(maximumOpticalZoomChanged(qreal)),
+ q, SIGNAL(maximumOpticalZoomChanged(qreal)));
+ q->connect(focusControl, SIGNAL(maximumDigitalZoomChanged(qreal)),
+ q, SIGNAL(maximumDigitalZoomChanged(qreal)));
+ q->connect(focusControl, SIGNAL(focusZonesChanged()), q, SIGNAL(focusZonesChanged()));
+ }
+}
+
+/*!
+ Construct a QCameraFocus for \a camera.
+*/
+
+QCameraFocus::QCameraFocus(QCamera *camera):
+ QObject(camera), d_ptr(new QCameraFocusPrivate)
+{
+ Q_D(QCameraFocus);
+ d->camera = camera;
+ d->q_ptr = this;
+ d->initControls();
+}
+
+
+/*!
+ Destroys the camera focus object.
+*/
+
+QCameraFocus::~QCameraFocus()
+{
+}
+
+/*!
+ Returns true if focus related settings are supported by this camera.
+ \since 1.1
+*/
+bool QCameraFocus::isAvailable() const
+{
+ return d_func()->focusControl != 0;
+}
+
+/*!
+ \property QCameraFocus::focusMode
+ \brief The current camera focus mode.
+
+ \since 1.1
+ \sa QCameraFocus::isFocusModeSupported()
+*/
+
+QCameraFocus::FocusMode QCameraFocus::focusMode() const
+{
+ return d_func()->focusControl ? d_func()->focusControl->focusMode() : QCameraFocus::AutoFocus;
+}
+
+void QCameraFocus::setFocusMode(QCameraFocus::FocusMode mode)
+{
+ if (d_func()->focusControl)
+ d_func()->focusControl->setFocusMode(mode);
+}
+
+/*!
+ Returns true if the focus \a mode is supported by camera.
+ \since 1.1
+*/
+
+bool QCameraFocus::isFocusModeSupported(QCameraFocus::FocusMode mode) const
+{
+ return d_func()->focusControl ? d_func()->focusControl->isFocusModeSupported(mode) : false;
+}
+
+/*!
+ \property QCameraFocus::focusPointMode
+ \brief The current camera focus point selection mode.
+
+ \sa QCameraFocus::isFocusPointModeSupported()
+ \since 1.1
+*/
+
+QCameraFocus::FocusPointMode QCameraFocus::focusPointMode() const
+{
+ return d_func()->focusControl ?
+ d_func()->focusControl->focusPointMode() :
+ QCameraFocus::FocusPointAuto;
+}
+
+void QCameraFocus::setFocusPointMode(QCameraFocus::FocusPointMode mode)
+{
+ if (d_func()->focusControl)
+ d_func()->focusControl->setFocusPointMode(mode);
+ else
+ qWarning("Focus points mode selection is not supported");
+}
+
+/*!
+ Returns true if focus point \a mode is supported.
+ \since 1.1
+ */
+bool QCameraFocus::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
+{
+ return d_func()->focusControl ?
+ d_func()->focusControl->isFocusPointModeSupported(mode) :
+ false;
+
+}
+
+/*!
+ \property QCameraFocus::customFocusPoint
+
+ Position of custom focus point, in relative frame coordinates:
+ QPointF(0,0) points to the left top frame point, QPointF(0.5,0.5) points to the frame center.
+
+ Custom focus point is used only in FocusPointCustom focus mode.
+ \since 1.1
+ */
+
+QPointF QCameraFocus::customFocusPoint() const
+{
+ return d_func()->focusControl ?
+ d_func()->focusControl->customFocusPoint() :
+ QPointF(0.5,0.5);
+}
+
+void QCameraFocus::setCustomFocusPoint(const QPointF &point)
+{
+ if (d_func()->focusControl)
+ d_func()->focusControl->setCustomFocusPoint(point);
+ else
+ qWarning("Focus points selection is not supported");
+
+}
+
+/*!
+ \property QCameraFocus::focusZones
+
+ Returns the list of active focus zones.
+
+ If QCamera::FocusPointAuto or QCamera::FocusPointFaceDetection focus mode is selected
+ this method returns the list of zones the camera is actually focused on.
+
+ The coordinates system is the same as for custom focus points:
+ QPointF(0,0) points to the left top frame point, QPointF(0.5,0.5) points to the frame center.
+ \since 1.1
+ */
+QCameraFocusZoneList QCameraFocus::focusZones() const
+{
+ return d_func()->focusControl ?
+ d_func()->focusControl->focusZones() :
+ QCameraFocusZoneList();
+}
+
+/*!
+ Returns the maximum optical zoom
+ \since 1.1
+*/
+
+qreal QCameraFocus::maximumOpticalZoom() const
+{
+ return d_func()->focusControl ? d_func()->focusControl->maximumOpticalZoom() : 1.0;
+}
+
+/*!
+ Returns the maximum digital zoom
+ \since 1.1
+*/
+
+qreal QCameraFocus::maximumDigitalZoom() const
+{
+ return d_func()->focusControl ? d_func()->focusControl->maximumDigitalZoom() : 1.0;
+}
+
+/*!
+ \property QCameraFocus::opticalZoom
+ \brief The current optical zoom value.
+
+ \since 1.1
+ \sa QCameraFocus::digitalZoom
+*/
+
+qreal QCameraFocus::opticalZoom() const
+{
+ return d_func()->focusControl ? d_func()->focusControl->opticalZoom() : 1.0;
+}
+
+/*!
+ \property QCameraFocus::digitalZoom
+ \brief The current digital zoom value.
+
+ \since 1.1
+ \sa QCameraFocus::opticalZoom
+*/
+qreal QCameraFocus::digitalZoom() const
+{
+ return d_func()->focusControl ? d_func()->focusControl->digitalZoom() : 1.0;
+}
+
+
+/*!
+ Set the camera \a optical and \a digital zoom values.
+ \since 1.1
+*/
+void QCameraFocus::zoomTo(qreal optical, qreal digital)
+{
+ if (d_func()->focusControl)
+ d_func()->focusControl->zoomTo(optical, digital);
+ else
+ qWarning("The camera doesn't support zooming.");
+}
+
+/*!
+ \enum QCameraFocus::FocusMode
+
+ \value ManualFocus Manual or fixed focus mode.
+ \value AutoFocus One-shot auto focus mode.
+ \value ContinuousFocus Continuous auto focus mode.
+ \value InfinityFocus Focus strictly to infinity.
+ \value HyperfocalFocus Focus to hyperfocal distance, with with the maximum depth of field achieved.
+ All objects at distances from half of this
+ distance out to infinity will be acceptably sharp.
+ \value MacroFocus One shot auto focus to objects close to camera.
+*/
+
+/*!
+ \enum QCameraFocus::FocusPointMode
+
+ \value FocusPointAuto Automatically select one or multiple focus points.
+ \value FocusPointCenter Focus to the frame center.
+ \value FocusPointFaceDetection Focus on faces in the frame.
+ \value FocusPointCustom Focus to the custom point, defined by QCameraFocus::customFocusPoint property.
+*/
+
+/*!
+ \fn void QCameraFocus::opticalZoomChanged(qreal value)
+
+ Signal emitted when optical zoom value changes to new \a value.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraFocus::digitalZoomChanged(qreal value)
+
+ Signal emitted when digital zoom value changes to new \a value.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraFocus::maximumOpticalZoomChanged(qreal zoom)
+
+ Signal emitted when the maximum supported optical \a zoom value changed.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraFocus::maximumDigitalZoomChanged(qreal zoom)
+
+ Signal emitted when the maximum supported digital \a zoom value changed.
+
+ The maximum supported zoom value can depend on other camera settings,
+ like capture mode or resolution.
+ \since 1.1
+*/
+
+
+
+/*!
+ \fn QCameraFocus::focusZonesChanged()
+
+ Signal is emitted when the set of zones, camera focused on is changed.
+
+ Usually the zones list is changed when the camera is focused.
+ \since 1.1
+*/
+
+
+#include "moc_qcamerafocus.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediakit/qcamerafocus.h b/src/multimediakit/qcamerafocus.h
new file mode 100644
index 000000000..dcc8111e1
--- /dev/null
+++ b/src/multimediakit/qcamerafocus.h
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCAMERAFOCUS_H
+#define QCAMERAFOCUS_H
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qshareddata.h>
+
+#include <qmediaobject.h>
+#include <qmediaenumdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCamera;
+
+class QCameraFocusZoneData;
+
+class Q_MULTIMEDIA_EXPORT QCameraFocusZone {
+public:
+ enum FocusZoneStatus {
+ Invalid,
+ Unused,
+ Selected,
+ Focused
+ };
+
+ QCameraFocusZone();
+ QCameraFocusZone(const QRectF &area, FocusZoneStatus status = Selected);
+ QCameraFocusZone(const QCameraFocusZone &other);
+
+ QCameraFocusZone& operator=(const QCameraFocusZone &other);
+ bool operator==(const QCameraFocusZone &other) const;
+ bool operator!=(const QCameraFocusZone &other) const;
+
+ ~QCameraFocusZone();
+
+ bool isValid() const;
+
+ QRectF area() const;
+
+ FocusZoneStatus status() const;
+ void setStatus(FocusZoneStatus status);
+
+private:
+ QSharedDataPointer<QCameraFocusZoneData> d;
+};
+
+typedef QList<QCameraFocusZone> QCameraFocusZoneList;
+
+
+class QCameraFocusPrivate;
+class Q_MULTIMEDIA_EXPORT QCameraFocus : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(FocusMode focusMode READ focusMode WRITE setFocusMode)
+ Q_PROPERTY(FocusPointMode focusPointMode READ focusPointMode WRITE setFocusPointMode)
+ Q_PROPERTY(QPointF customFocusPoint READ customFocusPoint WRITE setCustomFocusPoint)
+ Q_PROPERTY(QCameraFocusZoneList focusZones READ focusZones NOTIFY focusZonesChanged)
+ Q_PROPERTY(qreal opticalZoom READ opticalZoom NOTIFY opticalZoomChanged)
+ Q_PROPERTY(qreal digitalZoom READ digitalZoom NOTIFY digitalZoomChanged)
+
+ Q_ENUMS(FocusMode)
+ Q_ENUMS(FocusPointMode)
+public:
+ enum FocusMode {
+ ManualFocus = 0x1,
+ HyperfocalFocus = 0x02,
+ InfinityFocus = 0x04,
+ AutoFocus = 0x8,
+ ContinuousFocus = 0x10,
+ MacroFocus = 0x20
+ };
+ Q_DECLARE_FLAGS(FocusModes, FocusMode)
+
+ enum FocusPointMode {
+ FocusPointAuto,
+ FocusPointCenter,
+ FocusPointFaceDetection,
+ FocusPointCustom
+ };
+
+ bool isAvailable() const;
+
+ FocusMode focusMode() const;
+ void setFocusMode(FocusMode mode);
+ bool isFocusModeSupported(FocusMode mode) const;
+
+ FocusPointMode focusPointMode() const;
+ void setFocusPointMode(FocusPointMode mode);
+ bool isFocusPointModeSupported(FocusPointMode) const;
+ QPointF customFocusPoint() const;
+ void setCustomFocusPoint(const QPointF &point);
+
+ QCameraFocusZoneList focusZones() const;
+
+ qreal maximumOpticalZoom() const;
+ qreal maximumDigitalZoom() const;
+ qreal opticalZoom() const;
+ qreal digitalZoom() const;
+
+ void zoomTo(qreal opticalZoom, qreal digitalZoom);
+
+Q_SIGNALS:
+ void opticalZoomChanged(qreal);
+ void digitalZoomChanged(qreal);
+
+ void focusZonesChanged();
+
+ void maximumOpticalZoomChanged(qreal);
+ void maximumDigitalZoomChanged(qreal);
+
+private:
+ friend class QCamera;
+ QCameraFocus(QCamera *camera);
+ ~QCameraFocus();
+
+ Q_DISABLE_COPY(QCameraFocus)
+ Q_DECLARE_PRIVATE(QCameraFocus)
+ QCameraFocusPrivate *d_ptr;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QCameraFocus::FocusModes)
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QCameraFocus::FocusModes)
+Q_DECLARE_METATYPE(QCameraFocus::FocusPointMode)
+
+Q_MEDIA_ENUM_DEBUG(QCameraFocus, FocusMode)
+Q_MEDIA_ENUM_DEBUG(QCameraFocus, FocusPointMode)
+
+#endif // QCAMERAFOCUS_H
diff --git a/src/multimediakit/qcamerafocuscontrol.cpp b/src/multimediakit/qcamerafocuscontrol.cpp
new file mode 100644
index 000000000..1a30a9c21
--- /dev/null
+++ b/src/multimediakit/qcamerafocuscontrol.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <qcamerafocuscontrol.h>
+#include "qmediacontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCameraFocusControl
+
+
+ \brief The QCameraFocusControl class supplies control for
+ focusing related camera parameters.
+
+ \inmodule QtMultimediaKit
+ \ingroup camera
+ \since 1.1
+
+ The interface name of QCameraFocusControl is \c com.nokia.Qt.QCameraFocusControl/1.0 as
+ defined in QCameraFocusControl_iid.
+
+
+ \sa QMediaService::requestControl(), QCamera
+*/
+
+/*!
+ \macro QCameraFocusControl_iid
+
+ \c com.nokia.Qt.QCameraFocusControl/1.0
+
+ Defines the interface name of the QCameraFocusControl class.
+
+ \relates QCameraFocusControl
+*/
+
+/*!
+ Constructs a camera control object with \a parent.
+*/
+
+QCameraFocusControl::QCameraFocusControl(QObject *parent):
+ QMediaControl(*new QMediaControlPrivate, parent)
+{
+}
+
+/*!
+ Destruct the camera control object.
+*/
+
+QCameraFocusControl::~QCameraFocusControl()
+{
+}
+
+
+/*!
+ \fn QCameraFocus::FocusMode QCameraFocusControl::focusMode() const
+
+ Returns the focus mode being used.
+ \since 1.1
+*/
+
+
+/*!
+ \fn void QCameraFocusControl::setFocusMode(QCameraFocus::FocusMode mode)
+
+ Set the focus mode to \a mode.
+ \since 1.1
+*/
+
+
+/*!
+ \fn bool QCameraFocusControl::isFocusModeSupported(QCameraFocus::FocusMode mode) const
+
+ Returns true if focus \a mode is supported.
+ \since 1.1
+*/
+
+
+/*!
+ \fn qreal QCameraFocusControl::maximumOpticalZoom() const
+
+ Returns the maximum optical zoom value, or 1.0 if optical zoom is not supported.
+ \since 1.1
+*/
+
+
+/*!
+ \fn qreal QCameraFocusControl::maximumDigitalZoom() const
+
+ Returns the maximum digital zoom value, or 1.0 if digital zoom is not supported.
+ \since 1.1
+*/
+
+
+/*!
+ \fn qreal QCameraFocusControl::opticalZoom() const
+
+ Return the current optical zoom value.
+ \since 1.1
+*/
+
+/*!
+ \fn qreal QCameraFocusControl::digitalZoom() const
+
+ Return the current digital zoom value.
+ \since 1.1
+*/
+
+
+/*!
+ \fn void QCameraFocusControl::zoomTo(qreal optical, qreal digital)
+
+ Sets \a optical and \a digital zoom values.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraFocusControl::focusPointMode() const
+
+ Returns the camera focus point selection mode.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraFocusControl::setFocusPointMode(QCameraFocus::FocusPointMode mode)
+
+ Sets the camera focus point selection \a mode.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraFocusControl::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
+
+ Returns true if the camera focus point \a mode is supported.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraFocusControl::customFocusPoint() const
+
+ Return the position of custom focus point, in relative frame coordinates:
+ QPointF(0,0) points to the left top frame point, QPointF(0.5,0.5) points to the frame center.
+
+ Custom focus point is used only in FocusPointCustom focus mode.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraFocusControl::setCustomFocusPoint(const QPointF &point)
+
+ Sets the custom focus \a point.
+
+ If camera supports fixed set of focus points,
+ it should use the nearest supported focus point,
+ and return the actual focus point with QCameraFocusControl::focusZones().
+
+ \since 1.1
+ \sa QCameraFocusControl::customFocusPoint(), QCameraFocusControl::focusZones()
+*/
+
+/*!
+ \fn QCameraFocusControl::focusZones() const
+
+ Returns the list of zones, the camera is using for focusing or focused on.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraFocusControl::opticalZoomChanged(qreal zoom)
+
+ Signal emitted when the optical \a zoom value changed.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraFocusControl::digitalZoomChanged(qreal zoom)
+
+ Signal emitted when the digital \a zoom value changed.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraFocusControl::maximumOpticalZoomChanged(qreal zoom)
+
+ Signal emitted when the maximum supported optical \a zoom value changed.
+ \since 1.1
+*/
+
+/*!
+ \fn void QCameraFocusControl::maximumDigitalZoomChanged(qreal zoom)
+
+ Signal emitted when the maximum supported digital \a zoom value changed.
+
+ The maximum supported zoom value can depend on other camera settings,
+ like capture mode or resolution.
+ \since 1.1
+*/
+
+
+/*!
+ \fn QCameraFocusControl::focusZonesChanged()
+
+ Signal is emitted when the set of zones, camera focused on is changed.
+
+ Usually the zones list is changed when the camera is focused.
+
+ \since 1.1
+ \sa QCameraFocusControl::focusZones()
+*/
+
+
+
+#include "moc_qcamerafocuscontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qcamerafocuscontrol.h b/src/multimediakit/qcamerafocuscontrol.h
new file mode 100644
index 000000000..23b930115
--- /dev/null
+++ b/src/multimediakit/qcamerafocuscontrol.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCAMERAFOCUSCONTROL_H
+#define QCAMERAFOCUSCONTROL_H
+
+#include <qmediacontrol.h>
+#include <qmediaobject.h>
+
+#include <qcamerafocus.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QCameraFocusControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ ~QCameraFocusControl();
+
+ virtual QCameraFocus::FocusMode focusMode() const = 0;
+ virtual void setFocusMode(QCameraFocus::FocusMode mode) = 0;
+ virtual bool isFocusModeSupported(QCameraFocus::FocusMode mode) const = 0;
+
+ virtual qreal maximumOpticalZoom() const = 0;
+ virtual qreal maximumDigitalZoom() const = 0;
+ virtual qreal opticalZoom() const = 0;
+ virtual qreal digitalZoom() const = 0;
+
+ virtual void zoomTo(qreal optical, qreal digital) = 0;
+
+ virtual QCameraFocus::FocusPointMode focusPointMode() const = 0;
+ virtual void setFocusPointMode(QCameraFocus::FocusPointMode mode) = 0;
+ virtual bool isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const = 0;
+ virtual QPointF customFocusPoint() const = 0;
+ virtual void setCustomFocusPoint(const QPointF &point) = 0;
+
+ virtual QCameraFocusZoneList focusZones() const = 0;
+
+Q_SIGNALS:
+ void opticalZoomChanged(qreal opticalZoom);
+ void digitalZoomChanged(qreal digitalZoom);
+ void focusZonesChanged();
+ void maximumOpticalZoomChanged(qreal);
+ void maximumDigitalZoomChanged(qreal);
+
+protected:
+ QCameraFocusControl(QObject* parent = 0);
+};
+
+#define QCameraFocusControl_iid "com.nokia.Qt.QCameraFocusingControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QCameraFocusControl, QCameraFocusControl_iid)
+
+QT_END_NAMESPACE
+
+#endif // QCAMERAFOCUSCONTROL_H
+
diff --git a/src/multimediakit/qcameraimagecapture.cpp b/src/multimediakit/qcameraimagecapture.cpp
new file mode 100644
index 000000000..5fad8313a
--- /dev/null
+++ b/src/multimediakit/qcameraimagecapture.cpp
@@ -0,0 +1,668 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qcameraimagecapture.h>
+#include <qcameraimagecapturecontrol.h>
+#include <qmediaencodersettings.h>
+#include <qcameracapturedestinationcontrol.h>
+#include <qcameracapturebufferformatcontrol.h>
+
+#include <qimageencodercontrol.h>
+#include <qmediaobject_p.h>
+#include <qmediaservice.h>
+#include <qcamera.h>
+#include <qcameracontrol.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmetaobject.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCameraImageCapture
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.1
+
+
+ \brief The QCameraImageCapture class is used for the recording of media content.
+
+ The QCameraImageCapture class is a high level images recording class.
+ It's not intended to be used alone but for accessing the media
+ recording functions of other media objects, like QCamera.
+
+ \snippet doc/src/snippets/multimedia-snippets/camera.cpp Camera
+
+ \snippet doc/src/snippets/multimedia-snippets/camera.cpp Camera keys
+
+ \sa QCamera
+*/
+
+namespace
+{
+class MediaRecorderRegisterMetaTypes
+{
+public:
+ MediaRecorderRegisterMetaTypes()
+ {
+ qRegisterMetaType<QCameraImageCapture::Error>("QCameraImageCapture::Error");
+ qRegisterMetaType<QCameraImageCapture::CaptureDestination>("QCameraImageCapture::CaptureDestination");
+ qRegisterMetaType<QCameraImageCapture::CaptureDestinations>("QCameraImageCapture::CaptureDestinations");
+ }
+} _registerRecorderMetaTypes;
+}
+
+
+class QCameraImageCapturePrivate
+{
+ Q_DECLARE_NON_CONST_PUBLIC(QCameraImageCapture)
+public:
+ QCameraImageCapturePrivate();
+
+ QMediaObject *mediaObject;
+
+ QCameraImageCaptureControl *control;
+ QImageEncoderControl *encoderControl;
+ QCameraCaptureDestinationControl *captureDestinationControl;
+ QCameraCaptureBufferFormatControl *bufferFormatControl;
+
+ QCameraImageCapture::Error error;
+ QString errorString;
+
+ void _q_error(int id, int error, const QString &errorString);
+ void _q_readyChanged(bool);
+
+ void unsetError() { error = QCameraImageCapture::NoError; errorString.clear(); }
+
+ QCameraImageCapture *q_ptr;
+};
+
+QCameraImageCapturePrivate::QCameraImageCapturePrivate():
+ mediaObject(0),
+ control(0),
+ encoderControl(0),
+ captureDestinationControl(0),
+ bufferFormatControl(0),
+ error(QCameraImageCapture::NoError)
+{
+}
+
+void QCameraImageCapturePrivate::_q_error(int id, int error, const QString &errorString)
+{
+ Q_Q(QCameraImageCapture);
+
+ this->error = QCameraImageCapture::Error(error);
+ this->errorString = errorString;
+
+ emit q->error(id, this->error, errorString);
+}
+
+void QCameraImageCapturePrivate::_q_readyChanged(bool ready)
+{
+ Q_Q(QCameraImageCapture);
+ emit q->readyForCaptureChanged(ready);
+}
+
+
+/*!
+ Constructs a media recorder which records the media produced by \a mediaObject.
+
+ The \a parent is passed to QMediaObject.
+*/
+
+QCameraImageCapture::QCameraImageCapture(QMediaObject *mediaObject, QObject *parent):
+ QObject(parent), d_ptr(new QCameraImageCapturePrivate)
+{
+ Q_D(QCameraImageCapture);
+
+ d->q_ptr = this;
+
+ if (mediaObject)
+ mediaObject->bind(this);
+}
+
+/*!
+ Destroys images capture object.
+*/
+
+QCameraImageCapture::~QCameraImageCapture()
+{
+ Q_D(QCameraImageCapture);
+
+ if (d->mediaObject)
+ d->mediaObject->unbind(this);
+}
+
+/*!
+ \reimp
+ \since 1.1
+*/
+QMediaObject *QCameraImageCapture::mediaObject() const
+{
+ return d_func()->mediaObject;
+}
+
+/*!
+ \reimp
+ \since 1.1
+*/
+bool QCameraImageCapture::setMediaObject(QMediaObject *mediaObject)
+{
+ Q_D(QCameraImageCapture);
+
+ if (d->mediaObject) {
+ if (d->control) {
+ disconnect(d->control, SIGNAL(imageExposed(int)),
+ this, SIGNAL(imageExposed(int)));
+ disconnect(d->control, SIGNAL(imageCaptured(int,QImage)),
+ this, SIGNAL(imageCaptured(int,QImage)));
+ disconnect(d->control, SIGNAL(imageAvailable(int,QVideoFrame)),
+ this, SIGNAL(imageAvailable(int,QVideoFrame)));
+ disconnect(d->control, SIGNAL(imageMetadataAvailable(int,QtMultimediaKit::MetaData,QVariant)),
+ this, SIGNAL(imageMetadataAvailable(int,QtMultimediaKit::MetaData,QVariant)));
+ disconnect(d->control, SIGNAL(imageMetadataAvailable(int,QString,QVariant)),
+ this, SIGNAL(imageMetadataAvailable(int,QString,QVariant)));
+ disconnect(d->control, SIGNAL(imageSaved(int,QString)),
+ this, SIGNAL(imageSaved(int,QString)));
+ disconnect(d->control, SIGNAL(readyForCaptureChanged(bool)),
+ this, SLOT(_q_readyChanged(bool)));
+ disconnect(d->control, SIGNAL(error(int,int,QString)),
+ this, SLOT(_q_error(int,int,QString)));
+
+ if (d->captureDestinationControl) {
+ disconnect(d->captureDestinationControl, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)),
+ this, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)));
+ }
+
+ if (d->bufferFormatControl) {
+ disconnect(d->bufferFormatControl, SIGNAL(bufferFormatChanged(QVideoFrame::PixelFormat)),
+ this, SIGNAL(bufferFormatChanged(QVideoFrame::PixelFormat)));
+ }
+
+ QMediaService *service = d->mediaObject->service();
+ service->releaseControl(d->control);
+ if (d->encoderControl)
+ service->releaseControl(d->encoderControl);
+ if (d->captureDestinationControl)
+ service->releaseControl(d->captureDestinationControl);
+ if (d->bufferFormatControl)
+ service->releaseControl(d->bufferFormatControl);
+ }
+ }
+
+ d->mediaObject = mediaObject;
+
+ if (d->mediaObject) {
+ QMediaService *service = mediaObject->service();
+ if (service) {
+ d->control = qobject_cast<QCameraImageCaptureControl*>(service->requestControl(QCameraImageCaptureControl_iid));
+
+ if (d->control) {
+ d->encoderControl = qobject_cast<QImageEncoderControl *>(service->requestControl(QImageEncoderControl_iid));
+ d->captureDestinationControl = qobject_cast<QCameraCaptureDestinationControl *>(
+ service->requestControl(QCameraCaptureDestinationControl_iid));
+ d->bufferFormatControl = qobject_cast<QCameraCaptureBufferFormatControl *>(
+ service->requestControl(QCameraCaptureBufferFormatControl_iid));
+
+ connect(d->control, SIGNAL(imageExposed(int)),
+ this, SIGNAL(imageExposed(int)));
+ connect(d->control, SIGNAL(imageCaptured(int,QImage)),
+ this, SIGNAL(imageCaptured(int,QImage)));
+ connect(d->control, SIGNAL(imageMetadataAvailable(int,QtMultimediaKit::MetaData,QVariant)),
+ this, SIGNAL(imageMetadataAvailable(int,QtMultimediaKit::MetaData,QVariant)));
+ connect(d->control, SIGNAL(imageMetadataAvailable(int,QString,QVariant)),
+ this, SIGNAL(imageMetadataAvailable(int,QString,QVariant)));
+ connect(d->control, SIGNAL(imageAvailable(int,QVideoFrame)),
+ this, SIGNAL(imageAvailable(int,QVideoFrame)));
+ connect(d->control, SIGNAL(imageSaved(int, QString)),
+ this, SIGNAL(imageSaved(int, QString)));
+ connect(d->control, SIGNAL(readyForCaptureChanged(bool)),
+ this, SLOT(_q_readyChanged(bool)));
+ connect(d->control, SIGNAL(error(int,int,QString)),
+ this, SLOT(_q_error(int,int,QString)));
+
+ if (d->captureDestinationControl) {
+ connect(d->captureDestinationControl, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)),
+ this, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)));
+ }
+
+ if (d->bufferFormatControl) {
+ connect(d->bufferFormatControl, SIGNAL(bufferFormatChanged(QVideoFrame::PixelFormat)),
+ this, SIGNAL(bufferFormatChanged(QVideoFrame::PixelFormat)));
+ }
+
+ return true;
+ }
+ }
+ }
+
+ // without QCameraImageCaptureControl discard the media object
+ d->mediaObject = 0;
+ d->control = 0;
+ d->encoderControl = 0;
+ d->captureDestinationControl = 0;
+ d->bufferFormatControl = 0;
+
+ return false;
+}
+
+/*!
+ Returns true if the images capture service ready to use.
+ \since 1.1
+*/
+bool QCameraImageCapture::isAvailable() const
+{
+ if (d_func()->control != NULL)
+ return true;
+ else
+ return false;
+}
+
+/*!
+ Returns the availability error code.
+ \since 1.1
+*/
+QtMultimediaKit::AvailabilityError QCameraImageCapture::availabilityError() const
+{
+ if (d_func()->control != NULL)
+ return QtMultimediaKit::NoError;
+ else
+ return QtMultimediaKit::ServiceMissingError;
+}
+
+/*!
+ Returns the current error state.
+
+ \since 1.1
+ \sa errorString()
+*/
+
+QCameraImageCapture::Error QCameraImageCapture::error() const
+{
+ return d_func()->error;
+}
+
+/*!
+ Returns a string describing the current error state.
+
+ \since 1.1
+ \sa error()
+*/
+
+QString QCameraImageCapture::errorString() const
+{
+ return d_func()->errorString;
+}
+
+
+/*!
+ Returns a list of supported image codecs.
+ \since 1.1
+*/
+QStringList QCameraImageCapture::supportedImageCodecs() const
+{
+ return d_func()->encoderControl ?
+ d_func()->encoderControl->supportedImageCodecs() : QStringList();
+}
+
+/*!
+ Returns a description of an image \a codec.
+ \since 1.1
+*/
+QString QCameraImageCapture::imageCodecDescription(const QString &codec) const
+{
+ return d_func()->encoderControl ?
+ d_func()->encoderControl->imageCodecDescription(codec) : QString();
+}
+
+/*!
+ Returns a list of resolutions images can be encoded at.
+
+ If non null image \a settings parameter is passed,
+ the returned list is reduced to resolution supported with partial settings like image codec or quality applied.
+
+ If the encoder supports arbitrary resolutions within the supported range,
+ *\a continuous is set to true, otherwise *\a continuous is set to false.
+
+ \since 1.1
+ \sa QImageEncoderSettings::resolution()
+*/
+QList<QSize> QCameraImageCapture::supportedResolutions(const QImageEncoderSettings &settings, bool *continuous) const
+{
+ if (continuous)
+ *continuous = false;
+
+ return d_func()->encoderControl ?
+ d_func()->encoderControl->supportedResolutions(settings, continuous) : QList<QSize>();
+}
+
+/*!
+ Returns the image encoder settings being used.
+
+ \since 1.1
+ \sa setEncodingSettings()
+*/
+
+QImageEncoderSettings QCameraImageCapture::encodingSettings() const
+{
+ return d_func()->encoderControl ?
+ d_func()->encoderControl->imageSettings() : QImageEncoderSettings();
+}
+
+/*!
+ Sets the image encoding \a settings.
+
+ If some parameters are not specified, or null settings are passed,
+ the encoder choose the default encoding parameters.
+
+ \since 1.1
+ \sa encodingSettings()
+*/
+
+void QCameraImageCapture::setEncodingSettings(const QImageEncoderSettings &settings)
+{
+ Q_D(QCameraImageCapture);
+
+ if (d->encoderControl) {
+ QCamera *camera = qobject_cast<QCamera*>(d->mediaObject);
+ if (camera && camera->captureMode() == QCamera::CaptureStillImage) {
+ QMetaObject::invokeMethod(camera,
+ "_q_preparePropertyChange",
+ Qt::DirectConnection,
+ Q_ARG(int, QCameraControl::ImageEncodingSettings));
+ }
+
+ d->encoderControl->setImageSettings(settings);
+ }
+}
+
+/*!
+ Returns the list of supported buffer image capture formats.
+
+ \since 1.1
+ \sa bufferFormat() setBufferFormat()
+*/
+QList<QVideoFrame::PixelFormat> QCameraImageCapture::supportedBufferFormats() const
+{
+ if (d_func()->bufferFormatControl)
+ return d_func()->bufferFormatControl->supportedBufferFormats();
+ else
+ return QList<QVideoFrame::PixelFormat>();
+}
+
+/*!
+ Returns the buffer image capture format being used.
+
+ \since 1.2
+ \sa supportedBufferCaptureFormats() setBufferCaptureFormat()
+*/
+QVideoFrame::PixelFormat QCameraImageCapture::bufferFormat() const
+{
+ if (d_func()->bufferFormatControl)
+ return d_func()->bufferFormatControl->bufferFormat();
+ else
+ return QVideoFrame::Format_Invalid;
+}
+
+/*!
+ Sets the buffer image capture format to be used.
+
+ \since 1.2
+ \sa bufferCaptureFormat() supportedBufferCaptureFormats() captureDestination()
+*/
+void QCameraImageCapture::setBufferFormat(const QVideoFrame::PixelFormat format)
+{
+ if (d_func()->bufferFormatControl)
+ d_func()->bufferFormatControl->setBufferFormat(format);
+}
+
+/*!
+ Returns true if the image capture \a destination is supported; otherwise returns false.
+
+ \since 1.2
+ \sa captureDestination() setCaptureDestination()
+*/
+bool QCameraImageCapture::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const
+{
+ if (d_func()->captureDestinationControl)
+ return d_func()->captureDestinationControl->isCaptureDestinationSupported(destination);
+ else
+ return destination == CaptureToFile;
+}
+
+/*!
+ Returns the image capture destination being used.
+
+ \since 1.2
+ \sa isCaptureDestinationSupported() setCaptureDestination()
+*/
+QCameraImageCapture::CaptureDestinations QCameraImageCapture::captureDestination() const
+{
+ if (d_func()->captureDestinationControl)
+ return d_func()->captureDestinationControl->captureDestination();
+ else
+ return CaptureToFile;
+}
+
+/*!
+ Sets the capture \a destination to be used.
+
+ \since 1.2
+ \sa isCaptureDestinationSupported() captureDestination()
+*/
+void QCameraImageCapture::setCaptureDestination(QCameraImageCapture::CaptureDestinations destination)
+{
+ Q_D(QCameraImageCapture);
+
+ if (d->captureDestinationControl)
+ d->captureDestinationControl->setCaptureDestination(destination);
+}
+
+/*!
+ \property QCameraImageCapture::readyForCapture
+ Indicates the service is ready to capture a an image immediately.
+ \since 1.1
+*/
+
+bool QCameraImageCapture::isReadyForCapture() const
+{
+ if (d_func()->control)
+ return d_func()->control->isReadyForCapture();
+ else
+ return false;
+}
+
+/*!
+ \fn QCameraImageCapture::readyForCaptureChanged(bool ready)
+
+ Signals that a camera's \a ready for capture state has changed.
+ \since 1.1
+*/
+
+
+/*!
+ Capture the image and save it to \a file.
+ This operation is asynchronous in majority of cases,
+ followed by signals QCameraImageCapture::imageCaptured(), QCameraImageCapture::imageSaved()
+ or QCameraImageCapture::error().
+
+ If an empty \a file is passed, the camera backend choses
+ the default location and naming scheme for photos on the system,
+ if only file name without full path is specified, the image will be saved to
+ the default directory, with a full path reported with imageCaptured() and imageSaved() signals.
+
+ QCameraImageCapture::capture returns the capture Id parameter, used with
+ imageExposed(), imageCaptured() and imageSaved() signals.
+ \since 1.1
+*/
+int QCameraImageCapture::capture(const QString &file)
+{
+ Q_D(QCameraImageCapture);
+
+ d->unsetError();
+
+ if (d->control) {
+ return d->control->capture(file);
+ } else {
+ d->error = NotSupportedFeatureError;
+ d->errorString = tr("Device does not support images capture.");
+
+ emit error(-1, d->error, d->errorString);
+ }
+
+ return -1;
+}
+
+/*!
+ Cancel incomplete capture requests.
+ Already captured and queused for proicessing images may be discarded.
+ \since 1.1
+*/
+void QCameraImageCapture::cancelCapture()
+{
+ Q_D(QCameraImageCapture);
+
+ d->unsetError();
+
+ if (d->control) {
+ d->control->cancelCapture();
+ } else {
+ d->error = NotSupportedFeatureError;
+ d->errorString = tr("Device does not support images capture.");
+
+ emit error(-1, d->error, d->errorString);
+ }
+}
+
+
+/*!
+ \enum QCameraImageCapture::Error
+
+ \value NoError No Errors.
+ \value NotReadyError The service is not ready for capture yet.
+ \value ResourceError Device is not ready or not available.
+ \value NotSupportedFeatureError Device does not support stillimages capture.
+ \value FormatError Current format is not supported.
+ \value OutOfSpaceError No space left on device.
+*/
+
+/*!
+ \enum QCameraImageCapture::DriveMode
+
+ \value SingleImageCapture Drive mode is capturing a single picture.
+*/
+
+/*!
+ \fn QCameraImageCapture::error(int id, QCameraImageCapture::Error error, const QString &errorString)
+
+ Signals that the capture request \a id has failed with an \a error
+ and \a errorString description.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageCapture::bufferFormatChanged(QVideoFrame::PixelFormat format)
+
+ Signal emitted when the buffer \a format for the buffer image capture has changed.
+ \since 1.2
+*/
+
+/*!
+ \fn QCameraImageCapture::captureDestinationChanged(CaptureDestinations destination)
+
+ Signal emitted when the capture \a destination has changed.
+ \since 1.2
+*/
+
+/*!
+ \fn QCameraImageCapture::imageExposed(int id)
+
+ Signal emitted when the frame with request \a id was exposed.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageCapture::imageCaptured(int id, const QImage &preview);
+
+ Signal emitted when the frame with request \a id was captured, but not processed and saved yet.
+ Frame \a preview can be displayed to user.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageCapture::imageMetadataAvailable(int id, QtMultimediaKit::MetaData key, const QVariant &value)
+
+ Signals that a metadata for an image with request \a id is available.
+ This signal is emitted for metadata \a value with a \a key listed in QtMultimediaKit::MetaData enum.
+
+ This signal is emitted between imageExposed and imageSaved signals.
+ \since 1.2
+*/
+
+/*!
+ \fn QCameraImageCapture::imageMetadataAvailable(int id, const QString &key, const QVariant &value)
+
+ Signals that a metadata for an image with request \a id is available.
+ This signal is emitted for extended metadata \a value with a \a key not listed in QtMultimediaKit::MetaData enum.
+
+ This signal is emitted between imageExposed and imageSaved signals.
+ \since 1.2
+*/
+
+
+/*!
+ \fn QCameraImageCapture::imageAvailable(int id, const QVideoFrame &buffer)
+
+ Signal emitted when the frame with request \a id is available as \a buffer.
+ \since 1.2
+*/
+
+/*!
+ \fn QCameraImageCapture::imageSaved(int id, const QString &fileName)
+
+ Signal emitted when the frame with request \a id was saved to \a fileName.
+ \since 1.1
+*/
+
+
+#include "moc_qcameraimagecapture.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qcameraimagecapture.h b/src/multimediakit/qcameraimagecapture.h
new file mode 100644
index 000000000..09d4d67b4
--- /dev/null
+++ b/src/multimediakit/qcameraimagecapture.h
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCAMERAIMAGECAPTURE_H
+#define QCAMERAIMAGECAPTURE_H
+
+#include <qmediaobject.h>
+#include <qmediaencodersettings.h>
+#include <qmediabindableinterface.h>
+#include <qvideoframe.h>
+
+#include <qmediaenumdebug.h>
+
+QT_BEGIN_NAMESPACE
+class QSize;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class QImageEncoderSettings;
+
+class QCameraImageCapturePrivate;
+class Q_MULTIMEDIA_EXPORT QCameraImageCapture : public QObject, public QMediaBindableInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaBindableInterface)
+ Q_ENUMS(Error)
+ Q_ENUMS(CaptureDestination)
+ Q_PROPERTY(bool readyForCapture READ isReadyForCapture NOTIFY readyForCaptureChanged)
+public:
+ enum Error
+ {
+ NoError,
+ NotReadyError,
+ ResourceError,
+ OutOfSpaceError,
+ NotSupportedFeatureError,
+ FormatError
+ };
+
+ enum DriveMode
+ {
+ SingleImageCapture
+ };
+
+ enum CaptureDestination
+ {
+ CaptureToFile = 0x01,
+ CaptureToBuffer = 0x02
+ };
+ Q_DECLARE_FLAGS(CaptureDestinations, CaptureDestination)
+
+ QCameraImageCapture(QMediaObject *mediaObject, QObject *parent = 0);
+ ~QCameraImageCapture();
+
+ bool isAvailable() const;
+ QtMultimediaKit::AvailabilityError availabilityError() const;
+
+ QMediaObject *mediaObject() const;
+
+ Error error() const;
+ QString errorString() const;
+
+ bool isReadyForCapture() const;
+
+ QStringList supportedImageCodecs() const;
+ QString imageCodecDescription(const QString &codecName) const;
+
+ QList<QSize> supportedResolutions(const QImageEncoderSettings &settings = QImageEncoderSettings(),
+ bool *continuous = 0) const;
+
+ QImageEncoderSettings encodingSettings() const;
+ void setEncodingSettings(const QImageEncoderSettings& settings);
+
+ QList<QVideoFrame::PixelFormat> supportedBufferFormats() const;
+ QVideoFrame::PixelFormat bufferFormat() const;
+ void setBufferFormat(QVideoFrame::PixelFormat format);
+
+ bool isCaptureDestinationSupported(CaptureDestinations destination) const;
+ CaptureDestinations captureDestination() const;
+ void setCaptureDestination(CaptureDestinations destination);
+
+public Q_SLOTS:
+ int capture(const QString &location = QString());
+ void cancelCapture();
+
+Q_SIGNALS:
+ void error(int id, QCameraImageCapture::Error error, const QString &errorString);
+
+ void readyForCaptureChanged(bool);
+ void bufferFormatChanged(QVideoFrame::PixelFormat);
+ void captureDestinationChanged(QCameraImageCapture::CaptureDestinations);
+
+ void imageExposed(int id);
+ void imageCaptured(int id, const QImage &preview);
+ void imageMetadataAvailable(int id, QtMultimediaKit::MetaData key, const QVariant &value);
+ void imageMetadataAvailable(int id, const QString &key, const QVariant &value);
+ void imageAvailable(int id, const QVideoFrame &image);
+ void imageSaved(int id, const QString &fileName);
+
+protected:
+ bool setMediaObject(QMediaObject *);
+
+ QCameraImageCapturePrivate *d_ptr;
+private:
+ Q_DISABLE_COPY(QCameraImageCapture)
+ Q_DECLARE_PRIVATE(QCameraImageCapture)
+ Q_PRIVATE_SLOT(d_func(), void _q_error(int, int, const QString &))
+ Q_PRIVATE_SLOT(d_func(), void _q_readyChanged(bool))
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QCameraImageCapture::CaptureDestinations)
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QCameraImageCapture::Error)
+Q_DECLARE_METATYPE(QCameraImageCapture::CaptureDestination)
+Q_DECLARE_METATYPE(QCameraImageCapture::CaptureDestinations)
+
+Q_MEDIA_ENUM_DEBUG(QCameraImageCapture, Error)
+Q_MEDIA_ENUM_DEBUG(QCameraImageCapture, CaptureDestination)
+
+#endif
+
diff --git a/src/multimediakit/qcameraimagecapturecontrol.cpp b/src/multimediakit/qcameraimagecapturecontrol.cpp
new file mode 100644
index 000000000..9733cfb61
--- /dev/null
+++ b/src/multimediakit/qcameraimagecapturecontrol.cpp
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <qcameraimagecapturecontrol.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCameraImageCaptureControl
+
+ \brief The QCameraImageCaptureControl class provides a control interface
+ for image capture services.
+
+ \inmodule QtMultimediaKit
+ \ingroup camera
+ \since 1.1
+
+
+
+ The interface name of QCameraImageCaptureControl is \c com.nokia.Qt.QCameraImageCaptureControl/1.0 as
+ defined in QCameraImageCaptureControl_iid.
+
+
+ \sa QMediaService::requestControl()
+*/
+
+/*!
+ \macro QCameraImageCaptureControl_iid
+
+ \c com.nokia.Qt.QCameraImageCaptureControl/1.0
+
+ Defines the interface name of the QCameraImageCaptureControl class.
+
+ \relates QCameraImageCaptureControl
+*/
+
+/*!
+ Constructs a new image capture control object with the given \a parent
+*/
+QCameraImageCaptureControl::QCameraImageCaptureControl(QObject *parent)
+ :QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys an image capture control.
+*/
+QCameraImageCaptureControl::~QCameraImageCaptureControl()
+{
+}
+
+/*!
+ \fn QCameraImageCaptureControl::isReadyForCapture() const
+
+ Identifies if a capture control is ready to perform a capture
+ immediately (all the resources necessary for image capture are allocated,
+ hardware initialized, flash is charged, etc).
+
+ Returns true if the camera is ready for capture; and false if it is not.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageCaptureControl::readyForCaptureChanged(bool ready)
+
+ Signals that a capture control's \a ready state has changed.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageCaptureControl::capture(const QString &fileName)
+
+ Initiates the capture of an image to \a fileName.
+ The \a fileName can be relative or empty,
+ in this case the service should use the system specific place
+ and file naming scheme.
+
+ Returns the capture request id number, which is used later
+ with imageExposed(), imageCaptured() and imageSaved() signals.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageCaptureControl::cancelCapture()
+
+ Cancel pending capture requests.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageCaptureControl::imageExposed(int requestId)
+
+ Signals that an image with it \a requestId
+ has just been exposed.
+ This signal can be used for the shutter sound or other indicaton.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageCaptureControl::imageCaptured(int requestId, const QImage &preview)
+
+ Signals that an image with it \a requestId
+ has been captured and a \a preview is available.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageCaptureControl::imageMetadataAvailable(int id, QtMultimediaKit::MetaData key, const QVariant &value)
+
+ Signals that a metadata for an image with request \a id is available.
+ This signal is emitted for metadata \a value with a \a key listed in QtMultimediaKit::MetaData enum.
+
+ This signal should be emitted between imageExposed and imageSaved signals.
+ \since 1.2
+*/
+
+/*!
+ \fn QCameraImageCaptureControl::imageMetadataAvailable(int id, const QString &key, const QVariant &value)
+
+ Signals that a metadata for an image with request \a id is available.
+ This signal is emitted for extended metadata \a value with a \a key not listed in QtMultimediaKit::MetaData enum.
+
+ This signal should be emitted between imageExposed and imageSaved signals.
+ \since 1.2
+*/
+
+/*!
+ \fn QCameraImageCaptureControl::imageAvailable(int requestId, const QVideoFrame &buffer)
+
+ Signals that a captured \a buffer with a \a requestId is available.
+ \since 1.2
+*/
+
+/*!
+ \fn QCameraImageCaptureControl::imageSaved(int requestId, const QString &fileName)
+
+ Signals that a captured image with a \a requestId has been saved
+ to \a fileName.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageCaptureControl::driveMode() const
+
+ Returns the current camera drive mode.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageCaptureControl::setDriveMode(QCameraImageCapture::DriveMode mode)
+
+ Sets the current camera drive \a mode.
+ \since 1.1
+*/
+
+
+/*!
+ \fn QCameraImageCaptureControl::error(int id, int error, const QString &errorString)
+
+ Signals the capture request \a id failed with \a error code and message \a errorString.
+
+ \since 1.1
+ \sa QCameraImageCapture::Error
+*/
+
+
+#include "moc_qcameraimagecapturecontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qcameraimagecapturecontrol.h b/src/multimediakit/qcameraimagecapturecontrol.h
new file mode 100644
index 000000000..a33dd1bf8
--- /dev/null
+++ b/src/multimediakit/qcameraimagecapturecontrol.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCAMERAIMAGECAPTURECONTROL_H
+#define QCAMERAIMAGECAPTURECONTROL_H
+
+#include <qmediacontrol.h>
+#include <qcameraimagecapture.h>
+
+QT_BEGIN_NAMESPACE
+class QImage;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QCameraImageCaptureControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ ~QCameraImageCaptureControl();
+
+ virtual bool isReadyForCapture() const = 0;
+
+ virtual QCameraImageCapture::DriveMode driveMode() const = 0;
+ virtual void setDriveMode(QCameraImageCapture::DriveMode mode) = 0;
+
+ virtual int capture(const QString &fileName) = 0;
+ virtual void cancelCapture() = 0;
+
+Q_SIGNALS:
+ void readyForCaptureChanged(bool);
+
+ void imageExposed(int id);
+ void imageCaptured(int id, const QImage &preview);
+ void imageMetadataAvailable(int id, QtMultimediaKit::MetaData key, const QVariant &value);
+ void imageMetadataAvailable(int id, const QString &key, const QVariant &value);
+ void imageAvailable(int id, const QVideoFrame &buffer);
+ void imageSaved(int id, const QString &fileName);
+
+ void error(int id, int error, const QString &errorString);
+
+protected:
+ QCameraImageCaptureControl(QObject* parent = 0);
+};
+
+#define QCameraImageCaptureControl_iid "com.nokia.Qt.QCameraImageCaptureControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QCameraImageCaptureControl, QCameraImageCaptureControl_iid)
+
+QT_END_NAMESPACE
+
+#endif // QCAMERAIMAGECAPTURECONTROL_H
+
diff --git a/src/multimediakit/qcameraimageprocessing.cpp b/src/multimediakit/qcameraimageprocessing.cpp
new file mode 100644
index 000000000..ee19911e5
--- /dev/null
+++ b/src/multimediakit/qcameraimageprocessing.cpp
@@ -0,0 +1,353 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+
+#include <qcameraimageprocessing.h>
+
+#include <qmediaobject_p.h>
+#include <qcameracontrol.h>
+#include <qcameraexposurecontrol.h>
+#include <qcamerafocuscontrol.h>
+#include <qmediarecordercontrol.h>
+#include <qcameraimageprocessingcontrol.h>
+#include <qcameraimagecapturecontrol.h>
+#include <qvideodevicecontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCameraImageProcessing
+
+
+ \brief The QCameraImageProcessing class provides interface for
+ focus and zoom related camera settings.
+
+ \inmodule QtMultimediaKit
+ \ingroup camera
+ \since 1.1
+
+*/
+
+
+class QCameraImageProcessingPrivate : public QMediaObjectPrivate
+{
+ Q_DECLARE_NON_CONST_PUBLIC(QCameraImageProcessing)
+public:
+ void initControls();
+
+ QCameraImageProcessing *q_ptr;
+
+ QCamera *camera;
+ QCameraImageProcessingControl *imageControl;
+};
+
+
+void QCameraImageProcessingPrivate::initControls()
+{
+ imageControl = 0;
+
+ QMediaService *service = camera->service();
+ if (service)
+ imageControl = qobject_cast<QCameraImageProcessingControl *>(service->requestControl(QCameraImageProcessingControl_iid));
+}
+
+/*!
+ Construct a QCameraImageProcessing for \a camera.
+*/
+
+QCameraImageProcessing::QCameraImageProcessing(QCamera *camera):
+ QObject(camera), d_ptr(new QCameraImageProcessingPrivate)
+{
+ Q_D(QCameraImageProcessing);
+ d->camera = camera;
+ d->q_ptr = this;
+ d->initControls();
+}
+
+
+/*!
+ Destroys the camera focus object.
+*/
+
+QCameraImageProcessing::~QCameraImageProcessing()
+{
+}
+
+
+/*!
+ Returns true if image processing related settings are supported by this camera.
+ \since 1.1
+*/
+bool QCameraImageProcessing::isAvailable() const
+{
+ return d_func()->imageControl != 0;
+}
+
+
+/*!
+ Returns the white balance mode being used.
+ \since 1.1
+*/
+
+QCameraImageProcessing::WhiteBalanceMode QCameraImageProcessing::whiteBalanceMode() const
+{
+ return d_func()->imageControl ? d_func()->imageControl->whiteBalanceMode() : QCameraImageProcessing::WhiteBalanceAuto;
+}
+
+/*!
+ Sets the white balance to \a mode.
+ \since 1.1
+*/
+
+void QCameraImageProcessing::setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode)
+{
+ if (d_func()->imageControl)
+ d_func()->imageControl->setWhiteBalanceMode(mode);
+}
+
+/*!
+ Returns true if the white balance \a mode is supported.
+ \since 1.1
+*/
+
+bool QCameraImageProcessing::isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const
+{
+ return d_func()->imageControl ? d_func()->imageControl->isWhiteBalanceModeSupported(mode) : false;
+}
+
+/*!
+ Returns the current color temperature if the
+ manual white balance is active, otherwise the
+ return value is undefined.
+ \since 1.1
+*/
+
+int QCameraImageProcessing::manualWhiteBalance() const
+{
+ QVariant value;
+
+ if (d_func()->imageControl)
+ value = d_func()->imageControl->processingParameter(QCameraImageProcessingControl::ColorTemperature);
+
+ return value.toInt();
+}
+
+/*!
+ Sets manual white balance to \a colorTemperature
+ \since 1.1
+*/
+
+void QCameraImageProcessing::setManualWhiteBalance(int colorTemperature)
+{
+ if (d_func()->imageControl) {
+ d_func()->imageControl->setProcessingParameter(
+ QCameraImageProcessingControl::ColorTemperature,
+ QVariant(colorTemperature));
+ }
+}
+
+/*!
+ Return the contrast.
+ \since 1.1
+*/
+int QCameraImageProcessing::contrast() const
+{
+ QVariant value;
+
+ if (d_func()->imageControl)
+ value = d_func()->imageControl->processingParameter(QCameraImageProcessingControl::Contrast);
+
+ return value.toInt();
+}
+
+/*!
+ Set the contrast to \a value.
+
+ Valid contrast values range between -100 and 100, the default is 0.
+ \since 1.1
+*/
+void QCameraImageProcessing::setContrast(int value)
+{
+ if (d_func()->imageControl)
+ d_func()->imageControl->setProcessingParameter(QCameraImageProcessingControl::Contrast,
+ QVariant(value));
+}
+
+/*!
+ Returns the saturation value.
+ \since 1.1
+*/
+int QCameraImageProcessing::saturation() const
+{
+ QVariant value;
+
+ if (d_func()->imageControl)
+ value = d_func()->imageControl->processingParameter(QCameraImageProcessingControl::Saturation);
+
+ return value.toInt();
+}
+
+/*!
+ Sets the saturation value to \a value.
+
+ Valid saturation values range between -100 and 100, the default is 0.
+ \since 1.1
+*/
+
+void QCameraImageProcessing::setSaturation(int value)
+{
+ if (d_func()->imageControl)
+ d_func()->imageControl->setProcessingParameter(QCameraImageProcessingControl::Saturation,
+ QVariant(value));
+}
+
+/*!
+ Identifies if sharpening is supported.
+
+ Returns true if sharpening is supported; and false if it is not.
+ \since 1.1
+*/
+bool QCameraImageProcessing::isSharpeningSupported() const
+{
+ if (d_func()->imageControl)
+ return d_func()->imageControl->isProcessingParameterSupported(QCameraImageProcessingControl::Sharpening);
+ else
+ return false;
+}
+
+/*!
+ Returns the sharpening level.
+ \since 1.1
+*/
+int QCameraImageProcessing::sharpeningLevel() const
+{
+ QVariant value;
+
+ if (d_func()->imageControl)
+ value = d_func()->imageControl->processingParameter(QCameraImageProcessingControl::Sharpening);
+
+ if (value.isNull())
+ return -1;
+ else
+ return value.toInt();
+}
+
+/*!
+ Sets the sharpening \a level.
+
+ Valid sharpening level values range between -1 for default sharpening level,
+ 0 for sharpening disabled and 100 for maximum sharpening applied.
+ \since 1.1
+*/
+
+void QCameraImageProcessing::setSharpeningLevel(int level)
+{
+ Q_D(QCameraImageProcessing);
+ if (d->imageControl)
+ d->imageControl->setProcessingParameter(QCameraImageProcessingControl::Sharpening,
+ level == -1 ? QVariant() : QVariant(level));
+}
+
+/*!
+ Returns true if denoising is supported.
+ \since 1.1
+*/
+bool QCameraImageProcessing::isDenoisingSupported() const
+{
+ if (d_func()->imageControl)
+ return d_func()->imageControl->isProcessingParameterSupported(QCameraImageProcessingControl::Denoising);
+ else
+ return false;
+}
+
+/*!
+ Returns the denoising level.
+ \since 1.1
+*/
+int QCameraImageProcessing::denoisingLevel() const
+{
+ QVariant value;
+
+ if (d_func()->imageControl)
+ value = d_func()->imageControl->processingParameter(QCameraImageProcessingControl::Denoising);
+
+ if (value.isNull())
+ return -1;
+ else
+ return value.toInt();
+}
+
+/*!
+ Sets the denoising \a level.
+
+ Valid denoising level values range between -1 for default denoising level,
+ 0 for denoising disabled and 100 for maximum denoising applied.
+ \since 1.1
+*/
+void QCameraImageProcessing::setDenoisingLevel(int level)
+{
+ Q_D(QCameraImageProcessing);
+ if (d->imageControl)
+ d->imageControl->setProcessingParameter(QCameraImageProcessingControl::Denoising,
+ level == -1 ? QVariant() : QVariant(level));
+}
+
+
+/*!
+ \enum QCameraImageProcessing::WhiteBalanceMode
+
+ \value WhiteBalanceManual Manual white balance. In this mode the white balance should be set with
+ setManualWhiteBalance()
+ \value WhiteBalanceAuto Auto white balance mode.
+ \value WhiteBalanceSunlight Sunlight white balance mode.
+ \value WhiteBalanceCloudy Cloudy white balance mode.
+ \value WhiteBalanceShade Shade white balance mode.
+ \value WhiteBalanceTungsten Tungsten white balance mode.
+ \value WhiteBalanceFluorescent Fluorescent white balance mode.
+ \value WhiteBalanceIncandescent Incandescent white balance mode.
+ \value WhiteBalanceFlash Flash white balance mode.
+ \value WhiteBalanceSunset Sunset white balance mode.
+ \value WhiteBalanceVendor Vendor defined white balance mode.
+*/
+
+#include "moc_qcameraimageprocessing.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediakit/qcameraimageprocessing.h b/src/multimediakit/qcameraimageprocessing.h
new file mode 100644
index 000000000..76c36975d
--- /dev/null
+++ b/src/multimediakit/qcameraimageprocessing.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCAMERAIMAGEPROCESSING_H
+#define QCAMERAIMAGEPROCESSING_H
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+
+#include <qmediacontrol.h>
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qmediaenumdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCamera;
+
+class QCameraImageProcessingPrivate;
+class Q_MULTIMEDIA_EXPORT QCameraImageProcessing : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(WhiteBalanceMode)
+public:
+ enum WhiteBalanceMode {
+ WhiteBalanceAuto = 0,
+ WhiteBalanceManual = 1,
+ WhiteBalanceSunlight = 2,
+ WhiteBalanceCloudy = 3,
+ WhiteBalanceShade = 4,
+ WhiteBalanceTungsten = 5,
+ WhiteBalanceFluorescent = 6,
+ WhiteBalanceIncandescent = 7,
+ WhiteBalanceFlash = 8,
+ WhiteBalanceSunset = 9,
+ WhiteBalanceVendor = 1000
+ };
+
+ bool isAvailable() const;
+
+ WhiteBalanceMode whiteBalanceMode() const;
+ void setWhiteBalanceMode(WhiteBalanceMode mode);
+ bool isWhiteBalanceModeSupported(WhiteBalanceMode mode) const;
+ int manualWhiteBalance() const;
+ void setManualWhiteBalance(int colorTemperature);
+
+ int contrast() const;
+ void setContrast(int value);
+
+ int saturation() const;
+ void setSaturation(int value);
+
+ bool isSharpeningSupported() const;
+ int sharpeningLevel() const;
+ void setSharpeningLevel(int value);
+
+ bool isDenoisingSupported() const;
+ int denoisingLevel() const;
+ void setDenoisingLevel(int value);
+
+private:
+ friend class QCamera;
+ QCameraImageProcessing(QCamera *camera);
+ ~QCameraImageProcessing();
+
+ Q_DISABLE_COPY(QCameraImageProcessing)
+ Q_DECLARE_PRIVATE(QCameraImageProcessing)
+ QCameraImageProcessingPrivate *d_ptr;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QCameraImageProcessing::WhiteBalanceMode)
+
+Q_MEDIA_ENUM_DEBUG(QCameraImageProcessing, WhiteBalanceMode)
+
+#endif // QCAMERAIMAGEPROCESSING_H
diff --git a/src/multimediakit/qcameraimageprocessingcontrol.cpp b/src/multimediakit/qcameraimageprocessingcontrol.cpp
new file mode 100644
index 000000000..1b7007180
--- /dev/null
+++ b/src/multimediakit/qcameraimageprocessingcontrol.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <qcameraimageprocessingcontrol.h>
+#include "qmediacontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCameraImageProcessingControl
+ \inmodule QtMultimediaKit
+ \ingroup multimedia-serv
+ \since 1.1
+
+
+ \brief The QCameraImageProcessingControl class provides an abstract class
+ for controlling image processing parameters, like white balance,
+ contrast, saturation, sharpening and denoising.
+
+ The interface name of QCameraImageProcessingControl is \c com.nokia.Qt.QCameraImageProcessingControl/1.0 as
+ defined in QCameraImageProcessingControl_iid.
+
+
+
+ \sa QMediaService::requestControl(), QCamera
+*/
+
+/*!
+ \macro QCameraImageProcessingControl_iid
+
+ \c com.nokia.Qt.QCameraImageProcessingControl/1.0
+
+ Defines the interface name of the QCameraImageProcessingControl class.
+
+ \relates QCameraImageProcessingControl
+*/
+
+/*!
+ Constructs an image processing control object with \a parent.
+*/
+
+QCameraImageProcessingControl::QCameraImageProcessingControl(QObject *parent):
+ QMediaControl(*new QMediaControlPrivate, parent)
+{
+}
+
+/*!
+ Destruct the image processing control object.
+*/
+
+QCameraImageProcessingControl::~QCameraImageProcessingControl()
+{
+}
+
+
+/*!
+ \fn QCameraImageProcessingControl::whiteBalanceMode() const
+ Return the white balance mode being used.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageProcessingControl::setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode)
+ Set the white balance mode to \a mode
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageProcessingControl::isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const
+ Returns true if the white balance \a mode is supported.
+ The backend should support at least QCameraImageProcessing::WhiteBalanceAuto mode.
+ \since 1.1
+*/
+
+/*!
+ \fn bool QCameraImageProcessingControl::isProcessingParameterSupported(ProcessingParameter parameter) const
+
+ Returns true if the camera supports adjusting image processing \a parameter.
+
+ Usually the the supported settings is static,
+ but some parameter may not be available depending on other
+ camera settings, like presets.
+ In such case the currently supported parameters should be returned.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageProcessingControl::processingParameter(ProcessingParameter parameter) const
+ Returns the image processing \a parameter value.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraImageProcessingControl::setProcessingParameter(ProcessingParameter parameter, QVariant value)
+
+ Sets the image processing \a parameter \a value.
+ Passing the null or invalid QVariant value allows
+ backend to choose the suitable parameter value.
+
+ The valid values range depends on the parameter type,
+ for contrast, saturation and brightness value should be
+ between -100 and 100, the default is 0,
+
+ For sharpening and denoising the range is 0..100,
+ 0 for sharpening or denoising disabled
+ and 100 for maximum sharpening/denoising applied.
+ \since 1.1
+*/
+
+/*!
+ \enum QCameraImageProcessingControl::ProcessingParameter
+
+ \value Contrast
+ Image contrast.
+ \value Saturation
+ Image saturation.
+ \value Brightness
+ Image brightness.
+ \value Sharpening
+ Amount of sharpening applied.
+ \value Denoising
+ Amount of denoising applied.
+ \value ColorTemperature
+ Color temperature in K. This value is used when the manual white balance mode is selected.
+ \value ExtendedParameter
+ The base value for platform specific extended parameters.
+ */
+
+#include "moc_qcameraimageprocessingcontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qcameraimageprocessingcontrol.h b/src/multimediakit/qcameraimageprocessingcontrol.h
new file mode 100644
index 000000000..6a1c920e3
--- /dev/null
+++ b/src/multimediakit/qcameraimageprocessingcontrol.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCAMERAIMAGEPROCESSINGCONTROL_H
+#define QCAMERAIMAGEPROCESSINGCONTROL_H
+
+#include <qmediacontrol.h>
+#include <qmediaobject.h>
+
+#include <qcamera.h>
+#include <qmediaenumdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QCameraImageProcessingControl : public QMediaControl
+{
+ Q_OBJECT
+ Q_ENUMS(ProcessingParameter)
+
+public:
+ ~QCameraImageProcessingControl();
+
+ enum ProcessingParameter {
+ Contrast = 0,
+ Saturation = 1,
+ Brightness = 2,
+ Sharpening = 3,
+ Denoising = 4,
+ ColorTemperature = 5,
+ ExtendedParameter = 1000
+ };
+
+ virtual QCameraImageProcessing::WhiteBalanceMode whiteBalanceMode() const = 0;
+ virtual void setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode) = 0;
+ virtual bool isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode) const = 0;
+
+ virtual bool isProcessingParameterSupported(ProcessingParameter) const = 0;
+ virtual QVariant processingParameter(ProcessingParameter parameter) const = 0;
+ virtual void setProcessingParameter(ProcessingParameter parameter, QVariant value) = 0;
+
+protected:
+ QCameraImageProcessingControl(QObject* parent = 0);
+};
+
+#define QCameraImageProcessingControl_iid "com.nokia.Qt.QCameraImageProcessingControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QCameraImageProcessingControl, QCameraImageProcessingControl_iid)
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QCameraImageProcessingControl::ProcessingParameter)
+
+Q_MEDIA_ENUM_DEBUG(QCameraImageProcessingControl, ProcessingParameter)
+
+#endif
+
diff --git a/src/multimediakit/qcameralockscontrol.cpp b/src/multimediakit/qcameralockscontrol.cpp
new file mode 100644
index 000000000..f254fdd61
--- /dev/null
+++ b/src/multimediakit/qcameralockscontrol.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <qcameralockscontrol.h>
+#include "qmediacontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCameraLocksControl
+
+
+
+ \brief The QCameraLocksControl class is an abstract base class for
+ classes that control still cameras or video cameras.
+
+ \inmodule QtMultimediaKit
+ \ingroup camera
+ \since 1.1
+
+ This service is provided by a QMediaService object via
+ QMediaService::control(). It is used by QCamera.
+
+ The interface name of QCameraLocksControl is \c com.nokia.Qt.QCameraLocksControl/1.0 as
+ defined in QCameraLocksControl_iid.
+
+
+ \sa QMediaService::requestControl(), QCamera
+*/
+
+/*!
+ \macro QCameraLocksControl_iid
+
+ \c com.nokia.Qt.QCameraLocksControl/1.0
+
+ Defines the interface name of the QCameraLocksControl class.
+
+ \relates QCameraLocksControl
+*/
+
+/*!
+ Constructs a camera locks control object with \a parent.
+*/
+
+QCameraLocksControl::QCameraLocksControl(QObject *parent):
+ QMediaControl(*new QMediaControlPrivate, parent)
+{
+}
+
+/*!
+ Destruct the camera locks control object.
+*/
+
+QCameraLocksControl::~QCameraLocksControl()
+{
+}
+
+/*!
+ \fn QCameraLocksControl::supportedLocks() const
+
+ Returns the lock types, the camera supports.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraLocksControl::lockStatus(QCamera::LockType lock) const
+
+ Returns the camera \a lock status.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraLocksControl::searchAndLock(QCamera::LockTypes locks)
+
+ Request camera \a locks.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraLocksControl::unlock(QCamera::LockTypes locks)
+
+ Unlock camera \a locks.
+ \since 1.1
+*/
+
+/*!
+ \fn QCameraLocksControl::lockStatusChanged(QCamera::LockType lock, QCamera::LockStatus status, QCamera::LockChangeReason reason)
+
+ Signals the \a lock \a status was changed with a specified \a reason.
+ \since 1.1
+*/
+
+
+
+#include "moc_qcameralockscontrol.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediakit/qcameralockscontrol.h b/src/multimediakit/qcameralockscontrol.h
new file mode 100644
index 000000000..02da2ef97
--- /dev/null
+++ b/src/multimediakit/qcameralockscontrol.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCAMERALOCKSCONTROL_H
+#define QCAMERALOCKSCONTROL_H
+
+#include <qmediacontrol.h>
+#include <qmediaobject.h>
+
+#include <qcamera.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QCameraLocksControl : public QMediaControl
+{
+ Q_OBJECT
+public:
+ ~QCameraLocksControl();
+
+ virtual QCamera::LockTypes supportedLocks() const = 0;
+
+ virtual QCamera::LockStatus lockStatus(QCamera::LockType lock) const = 0;
+
+ virtual void searchAndLock(QCamera::LockTypes locks) = 0;
+ virtual void unlock(QCamera::LockTypes locks) = 0;
+
+Q_SIGNALS:
+ void lockStatusChanged(QCamera::LockType type, QCamera::LockStatus status, QCamera::LockChangeReason reason);
+
+protected:
+ QCameraLocksControl(QObject* parent = 0);
+};
+
+#define QCameraLocksControl_iid "com.nokia.Qt.QCameraLocksControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QCameraLocksControl, QCameraLocksControl_iid)
+
+QT_END_NAMESPACE
+
+#endif // QCAMERALOCKSCONTROL_H
+
diff --git a/src/multimediakit/qcameraviewfinder.cpp b/src/multimediakit/qcameraviewfinder.cpp
new file mode 100644
index 000000000..dc779c60d
--- /dev/null
+++ b/src/multimediakit/qcameraviewfinder.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 <qmediaobject_p.h>
+
+#include <qcamera.h>
+#include <qcameraviewfinder.h>
+#include <qvideowidget_p.h>
+#include <qvideodevicecontrol.h>
+
+QT_USE_NAMESPACE
+
+/*!
+ \class QCameraViewfinder
+
+
+ \brief The QCameraViewfinder class provides a camera viewfinder widget.
+
+ \inmodule QtMultimediaKit
+ \ingroup camera
+ \since 1.1
+
+ \snippet doc/src/snippets/multimedia-snippets/camera.cpp Camera
+
+*/
+
+class QCameraViewfinderPrivate : public QVideoWidgetPrivate
+{
+ Q_DECLARE_NON_CONST_PUBLIC(QCameraViewfinder)
+public:
+ QCameraViewfinderPrivate():
+ QVideoWidgetPrivate()
+ {
+ }
+};
+
+/*!
+ Constructs a new camera viewfinder widget.
+
+ The \a parent is passed to QVideoWidget.
+*/
+
+QCameraViewfinder::QCameraViewfinder(QWidget *parent)
+ :QVideoWidget(*new QCameraViewfinderPrivate, parent)
+{
+}
+
+/*!
+ Destroys a camera viewfinder widget.
+*/
+QCameraViewfinder::~QCameraViewfinder()
+{
+}
+
+/*!
+ \reimp
+ \since 1.1
+*/
+QMediaObject *QCameraViewfinder::mediaObject() const
+{
+ return QVideoWidget::mediaObject();
+}
+
+/*!
+ \reimp
+ \since 1.1
+*/
+bool QCameraViewfinder::setMediaObject(QMediaObject *object)
+{
+ Q_D(QCameraViewfinder);
+
+ return QVideoWidget::setMediaObject(object);
+}
+
+#include "moc_qcameraviewfinder.cpp"
diff --git a/src/multimediakit/qcameraviewfinder.h b/src/multimediakit/qcameraviewfinder.h
new file mode 100644
index 000000000..6602b0b03
--- /dev/null
+++ b/src/multimediakit/qcameraviewfinder.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 QCAMERAVIEWFINDER_H
+#define QCAMERAVIEWFINDER_H
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+
+#include <qmediacontrol.h>
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qvideowidget.h>
+
+#include <qmediaserviceprovider.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCamera;
+
+class QCameraViewfinderPrivate;
+class Q_MULTIMEDIA_EXPORT QCameraViewfinder : public QVideoWidget
+{
+ Q_OBJECT
+public:
+ QCameraViewfinder(QWidget *parent = 0);
+ ~QCameraViewfinder();
+
+ QMediaObject *mediaObject() const;
+
+protected:
+ bool setMediaObject(QMediaObject *object);
+
+private:
+ Q_DISABLE_COPY(QCameraViewfinder)
+ Q_DECLARE_PRIVATE(QCameraViewfinder)
+};
+
+QT_END_NAMESPACE
+
+#endif // QCAMERA_H
diff --git a/src/multimediakit/qeglimagetexturesurface.cpp b/src/multimediakit/qeglimagetexturesurface.cpp
new file mode 100644
index 000000000..d4b10dcce
--- /dev/null
+++ b/src/multimediakit/qeglimagetexturesurface.cpp
@@ -0,0 +1,554 @@
+/****************************************************************************
+**
+** 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 <qeglimagetexturesurface_p.h>
+#include <qpaintervideosurface_p.h>
+
+#include <QtCore/qmath.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qx11info_x11.h>
+#include <qvideosurfaceformat.h>
+
+
+QT_BEGIN_NAMESPACE
+
+//#define DEBUG_OMAPFB_SURFACE
+
+const QAbstractVideoBuffer::HandleType EGLImageTextureHandle =
+QAbstractVideoBuffer::HandleType(QAbstractVideoBuffer::UserHandle+3434);
+
+/*!
+ \class QOmapFbVideoSurface
+ \internal
+ \since 1.2
+*/
+
+/*!
+*/
+QEglImageTextureSurface::QEglImageTextureSurface(QObject *parent)
+ : QAbstractVideoSurface(parent)
+ , m_context(0)
+ , m_program(0)
+ , m_pixelFormat(QVideoFrame::Format_Invalid)
+ , m_ready(false)
+ , m_colorKey(49,0,49)
+ , m_fallbackSurface(0)
+ , m_fallbackSurfaceActive(false)
+{
+ m_fallbackSurface = new QPainterVideoSurface(this);
+}
+
+/*!
+*/
+QEglImageTextureSurface::~QEglImageTextureSurface()
+{
+ if (isActive())
+ stop();
+}
+
+/*!
+ \since 1.2
+*/
+QList<QVideoFrame::PixelFormat> QEglImageTextureSurface::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+#ifdef DEBUG_OMAPFB_SURFACE
+ qDebug() << Q_FUNC_INFO << handleType;
+#endif
+
+ if (handleType == EGLImageTextureHandle) {
+ return QList<QVideoFrame::PixelFormat>()
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_ARGB32;
+ }
+
+ return m_fallbackSurface->supportedPixelFormats(handleType);
+}
+
+const char *qt_glsl_eglTextureVertexShaderProgram =
+ "attribute highp vec4 vertexCoordArray;\n"
+ "attribute mediump vec2 textureCoordArray;\n"
+ "uniform highp mat4 positionMatrix;\n"
+ "varying mediump vec2 textureCoord;\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_Position = positionMatrix * vertexCoordArray;\n"
+ " textureCoord = textureCoordArray;\n"
+ "}";
+
+static const char* qt_glsl_eglTextureShaderProgram =
+ "#extension GL_OES_EGL_image_external: enable\n"
+ "\n"
+ "uniform samplerExternalOES texRgb;\n"
+ "varying mediump vec2 textureCoord;\n"
+ "\n"
+ "void main (void)\n"
+ "{\n"
+ " gl_FragColor = texture2D(texRgb, textureCoord);\n"
+ "}";
+
+
+/*!
+ \since 1.2
+*/
+bool QEglImageTextureSurface::start(const QVideoSurfaceFormat &format)
+{
+#ifdef DEBUG_OMAPFB_SURFACE
+ qDebug() << Q_FUNC_INFO << format;
+#endif
+
+ m_fallbackSurfaceActive = false;
+ if (format.handleType() != EGLImageTextureHandle) {
+ qWarning() << Q_FUNC_INFO << "Non EGLImageTextureHandle based format requested, fallback to QPainterVideoSurface";
+ connect(m_fallbackSurface, SIGNAL(activeChanged(bool)),
+ this, SIGNAL(activeChanged(bool)));
+ connect(m_fallbackSurface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)));
+ connect(m_fallbackSurface, SIGNAL(supportedFormatsChanged()),
+ this, SIGNAL(supportedFormatsChanged()));
+ connect(m_fallbackSurface, SIGNAL(nativeResolutionChanged(QSize)),
+ this, SIGNAL(nativeResolutionChanged(QSize)));
+ connect(m_fallbackSurface, SIGNAL(frameChanged()),
+ this, SIGNAL(frameChanged()));
+
+ if (m_fallbackSurface->start(format)) {
+ m_fallbackSurfaceActive = true;
+ QAbstractVideoSurface::start(format);
+ } else {
+ qWarning() << Q_FUNC_INFO << "failed to start video surface:" << m_fallbackSurface->error();
+ setError(m_fallbackSurface->error());
+
+ disconnect(m_fallbackSurface, SIGNAL(activeChanged(bool)),
+ this, SIGNAL(activeChanged(bool)));
+ disconnect(m_fallbackSurface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)));
+ disconnect(m_fallbackSurface, SIGNAL(supportedFormatsChanged()),
+ this, SIGNAL(supportedFormatsChanged()));
+ disconnect(m_fallbackSurface, SIGNAL(nativeResolutionChanged(QSize)),
+ this, SIGNAL(nativeResolutionChanged(QSize)));
+ disconnect(m_fallbackSurface, SIGNAL(frameChanged()),
+ this, SIGNAL(frameChanged()));
+ }
+
+ return m_fallbackSurfaceActive;
+ }
+
+ QAbstractVideoSurface::Error error = NoError;
+
+ if (isActive())
+ stop();
+
+ if (format.frameSize().isEmpty()) {
+ setError(UnsupportedFormatError);
+ } else if (m_context) {
+ m_context->makeCurrent();
+ m_program = new QGLShaderProgram(m_context, this);
+
+ if (!m_program->addShaderFromSourceCode(QGLShader::Vertex, qt_glsl_eglTextureVertexShaderProgram)) {
+ qWarning("QOmapFbVideoSurface: Vertex shader compile error %s",
+ qPrintable(m_program->log()));
+ error = ResourceError;
+ }
+
+ if (error == NoError
+ && !m_program->addShaderFromSourceCode(QGLShader::Fragment, qt_glsl_eglTextureShaderProgram)) {
+ qWarning("QOmapFbVideoSurface: Vertex shader compile error %s",
+ qPrintable(m_program->log()));
+ error = QAbstractVideoSurface::ResourceError;
+ }
+
+ if (error == NoError) {
+ m_program->bindAttributeLocation("textureCoordArray", 1);
+ if(!m_program->link()) {
+ qWarning("QOmapFbVideoSurface: Shader link error %s", qPrintable(m_program->log()));
+ m_program->removeAllShaders();
+ error = QAbstractVideoSurface::ResourceError;
+ }
+ }
+
+ if (error != QAbstractVideoSurface::NoError) {
+ delete m_program;
+ m_program = 0;
+ }
+ }
+
+ if (error == QAbstractVideoSurface::NoError) {
+ m_scanLineDirection = format.scanLineDirection();
+ m_frameSize = format.frameSize();
+ m_pixelFormat = format.pixelFormat();
+ m_frameSize = format.frameSize();
+ m_sourceRect = format.viewport();
+ m_ready = true;
+
+ return QAbstractVideoSurface::start(format);
+ }
+
+ QAbstractVideoSurface::stop();
+ return false;
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::stop()
+{
+#ifdef DEBUG_OMAPFB_SURFACE
+ qDebug() << Q_FUNC_INFO;
+#endif
+
+ if (m_fallbackSurfaceActive) {
+ m_fallbackSurface->stop();
+ m_fallbackSurfaceActive = false;
+
+ disconnect(m_fallbackSurface, SIGNAL(activeChanged(bool)),
+ this, SIGNAL(activeChanged(bool)));
+ disconnect(m_fallbackSurface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)));
+ disconnect(m_fallbackSurface, SIGNAL(supportedFormatsChanged()),
+ this, SIGNAL(supportedFormatsChanged()));
+ disconnect(m_fallbackSurface, SIGNAL(nativeResolutionChanged(QSize)),
+ this, SIGNAL(nativeResolutionChanged(QSize)));
+ disconnect(m_fallbackSurface, SIGNAL(frameChanged()),
+ this, SIGNAL(frameChanged()));
+
+ m_ready = false;
+ QAbstractVideoSurface::stop();
+ }
+
+ if (isActive()) {
+ if (m_context)
+ m_context->makeCurrent();
+ m_frame = QVideoFrame();
+
+ m_program->removeAllShaders();
+ delete m_program;
+ m_program = 0;
+ m_ready = false;
+
+ QAbstractVideoSurface::stop();
+ }
+}
+
+/*!
+ \since 1.2
+*/
+bool QEglImageTextureSurface::present(const QVideoFrame &frame)
+{
+ if (m_fallbackSurfaceActive) {
+ if (m_fallbackSurface->present(frame)) {
+ return true;
+ } else {
+ setError(m_fallbackSurface->error());
+ stop();
+ return false;
+ }
+ }
+
+ if (!m_ready) {
+ if (!isActive())
+ setError(StoppedError);
+ else
+ m_frame = frame;
+ } else if (frame.isValid()
+ && (frame.pixelFormat() != m_pixelFormat || frame.size() != m_frameSize)) {
+ setError(IncorrectFormatError);
+ qWarning() << "Received frame of incorrect format, stopping the surface";
+
+ stop();
+ } else {
+ if (m_context)
+ m_context->makeCurrent();
+ m_frame = frame;
+ m_ready = false;
+ emit frameChanged();
+ return true;
+ }
+ return false;
+}
+
+/*!
+ \since 1.2
+*/
+int QEglImageTextureSurface::brightness() const
+{
+ return m_fallbackSurface->brightness();
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::setBrightness(int brightness)
+{
+ m_fallbackSurface->setBrightness(brightness);
+}
+
+/*!
+ \since 1.2
+*/
+int QEglImageTextureSurface::contrast() const
+{
+ return m_fallbackSurface->contrast();
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::setContrast(int contrast)
+{
+ m_fallbackSurface->setContrast(contrast);
+}
+
+/*!
+ \since 1.2
+*/
+int QEglImageTextureSurface::hue() const
+{
+ return m_fallbackSurface->hue();
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::setHue(int hue)
+{
+ m_fallbackSurface->setHue(hue);
+}
+
+/*!
+ \since 1.2
+*/
+int QEglImageTextureSurface::saturation() const
+{
+ return m_fallbackSurface->saturation();
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::setSaturation(int saturation)
+{
+ m_fallbackSurface->setSaturation(saturation);
+}
+
+/*!
+ \since 1.2
+*/
+bool QEglImageTextureSurface::isReady() const
+{
+ return m_fallbackSurfaceActive ? m_fallbackSurface->isReady() : m_ready;
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::setReady(bool ready)
+{
+ m_ready = ready;
+ if (m_fallbackSurfaceActive)
+ m_fallbackSurface->setReady(ready);
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::paint(QPainter *painter, const QRectF &target, const QRectF &sourceRect)
+{
+ if (m_fallbackSurfaceActive) {
+ m_fallbackSurface->paint(painter, target, sourceRect);
+ return;
+ }
+
+ if (!isActive() || !m_frame.isValid()) {
+ painter->fillRect(target, QBrush(Qt::black));
+ } else {
+ const QRectF source(
+ m_sourceRect.x() + m_sourceRect.width() * sourceRect.x(),
+ m_sourceRect.y() + m_sourceRect.height() * sourceRect.y(),
+ m_sourceRect.width() * sourceRect.width(),
+ m_sourceRect.height() * sourceRect.height());
+
+ bool stencilTestEnabled = glIsEnabled(GL_STENCIL_TEST);
+ bool scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
+
+ painter->beginNativePainting();
+
+ if (stencilTestEnabled)
+ glEnable(GL_STENCIL_TEST);
+ if (scissorTestEnabled)
+ glEnable(GL_SCISSOR_TEST);
+
+ const int width = QGLContext::currentContext()->device()->width();
+ const int height = QGLContext::currentContext()->device()->height();
+
+ const QTransform transform = painter->deviceTransform();
+
+ const GLfloat wfactor = 2.0 / width;
+ const GLfloat hfactor = -2.0 / height;
+
+ const GLfloat positionMatrix[4][4] =
+ {
+ {
+ /*(0,0)*/ GLfloat(wfactor * transform.m11() - transform.m13()),
+ /*(0,1)*/ GLfloat(hfactor * transform.m12() + transform.m13()),
+ /*(0,2)*/ 0.0,
+ /*(0,3)*/ GLfloat(transform.m13())
+ }, {
+ /*(1,0)*/ GLfloat(wfactor * transform.m21() - transform.m23()),
+ /*(1,1)*/ GLfloat(hfactor * transform.m22() + transform.m23()),
+ /*(1,2)*/ 0.0,
+ /*(1,3)*/ GLfloat(transform.m23())
+ }, {
+ /*(2,0)*/ 0.0,
+ /*(2,1)*/ 0.0,
+ /*(2,2)*/ -1.0,
+ /*(2,3)*/ 0.0
+ }, {
+ /*(3,0)*/ GLfloat(wfactor * transform.dx() - transform.m33()),
+ /*(3,1)*/ GLfloat(hfactor * transform.dy() + transform.m33()),
+ /*(3,2)*/ 0.0,
+ /*(3,3)*/ GLfloat(transform.m33())
+ }
+ };
+
+ const GLfloat vTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? target.top()
+ : target.bottom() + 1;
+ const GLfloat vBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? target.bottom() + 1
+ : target.top();
+
+
+ const GLfloat vertexCoordArray[] =
+ {
+ GLfloat(target.left()) , GLfloat(vBottom),
+ GLfloat(target.right() + 1), GLfloat(vBottom),
+ GLfloat(target.left()) , GLfloat(vTop),
+ GLfloat(target.right() + 1), GLfloat(vTop)
+ };
+
+ const GLfloat txLeft = source.left() / m_frameSize.width();
+ const GLfloat txRight = source.right() / m_frameSize.width();
+ const GLfloat txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.top() / m_frameSize.height()
+ : source.bottom() / m_frameSize.height();
+ const GLfloat txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.bottom() / m_frameSize.height()
+ : source.top() / m_frameSize.height();
+
+ const GLfloat textureCoordArray[] =
+ {
+ txLeft , txBottom,
+ txRight, txBottom,
+ txLeft , txTop,
+ txRight, txTop
+ };
+
+ m_program->bind();
+
+ m_program->enableAttributeArray("vertexCoordArray");
+ m_program->enableAttributeArray("textureCoordArray");
+ m_program->setAttributeArray("vertexCoordArray", vertexCoordArray, 2);
+ m_program->setAttributeArray("textureCoordArray", textureCoordArray, 2);
+ m_program->setUniformValue("positionMatrix", positionMatrix);
+ m_program->setUniformValue("texRgb", 0);
+
+ //map() binds the external texture
+ m_frame.map(QAbstractVideoBuffer::ReadOnly);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ //it's necessary to unbind the external texture
+ m_frame.unmap();
+
+ m_program->release();
+
+ painter->endNativePainting();
+ }
+}
+
+/*!
+ \fn QOmapFbVideoSurface::frameChanged()
+ \since 1.2
+*/
+
+/*!
+ \since 1.2
+*/
+const QGLContext *QEglImageTextureSurface::glContext() const
+{
+ return m_context;
+}
+
+/*!
+ \since 1.2
+*/
+void QEglImageTextureSurface::setGLContext(QGLContext *context)
+{
+ if (m_context == context)
+ return;
+
+ stop();
+
+ m_context = context;
+
+ m_fallbackSurface->setGLContext(context);
+ if (m_fallbackSurface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) {
+ m_fallbackSurface->setShaderType(QPainterVideoSurface::GlslShader);
+ } else {
+ m_fallbackSurface->setShaderType(QPainterVideoSurface::FragmentProgramShader);
+ }
+
+ emit supportedFormatsChanged();
+}
+
+void QEglImageTextureSurface::viewportDestroyed()
+{
+ m_context = 0;
+ m_fallbackSurface->viewportDestroyed();
+
+ setError(ResourceError);
+ stop();
+}
+
+#include "moc_qeglimagetexturesurface_p.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediakit/qeglimagetexturesurface_p.h b/src/multimediakit/qeglimagetexturesurface_p.h
new file mode 100644
index 000000000..f193692ce
--- /dev/null
+++ b/src/multimediakit/qeglimagetexturesurface_p.h
@@ -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$
+**
+****************************************************************************/
+
+#ifndef QEGLIMAGETEXTURESURFACE_P_H
+#define QEGLIMAGETEXTURESURFACE_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/qsize.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qpaintengine.h>
+
+#include <QtOpenGL/qglshaderprogram.h>
+
+#include <qabstractvideosurface.h>
+#include <qvideosurfaceformat.h>
+#include <qvideoframe.h>
+
+QT_BEGIN_NAMESPACE
+class QGLContext;
+class QGLShaderProgram;
+class QPainterVideoSurface;
+
+class QEglImageTextureSurface : public QAbstractVideoSurface
+{
+ Q_OBJECT
+public:
+ explicit QEglImageTextureSurface(QObject *parent = 0);
+ ~QEglImageTextureSurface();
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
+
+ bool start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ bool present(const QVideoFrame &frame);
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ bool isReady() const;
+ void setReady(bool ready);
+
+ void paint(QPainter *painter, const QRectF &target, const QRectF &source = QRectF(0, 0, 1, 1));
+
+ const QGLContext *glContext() const;
+ void setGLContext(QGLContext *context);
+
+ bool isOverlayEnabled() const;
+ void setOverlayEnabled(bool enabled);
+
+ QRect displayRect() const;
+ void setDisplayRect(const QRect &rect);
+
+public Q_SLOTS:
+ void viewportDestroyed();
+
+Q_SIGNALS:
+ void frameChanged();
+
+private:
+ QGLContext *m_context;
+ QGLShaderProgram *m_program;
+
+ QVideoFrame m_frame;
+
+ QVideoFrame::PixelFormat m_pixelFormat;
+ QVideoSurfaceFormat::Direction m_scanLineDirection;
+ QSize m_frameSize;
+ QRect m_sourceRect;
+ bool m_ready;
+
+ QRect m_viewport;
+ QRect m_displayRect;
+ QColor m_colorKey;
+
+ QPainterVideoSurface *m_fallbackSurface;
+ bool m_fallbackSurfaceActive;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qgraphicsvideoitem.cpp b/src/multimediakit/qgraphicsvideoitem.cpp
new file mode 100644
index 000000000..00d0f1c59
--- /dev/null
+++ b/src/multimediakit/qgraphicsvideoitem.cpp
@@ -0,0 +1,432 @@
+/****************************************************************************
+**
+** 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 "qgraphicsvideoitem.h"
+
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qpaintervideosurface_p.h>
+#include <qvideorenderercontrol.h>
+
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qpointer.h>
+
+#include <qvideosurfaceformat.h>
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+#include <QtOpenGL/qgl.h>
+#endif
+
+Q_DECLARE_METATYPE(QVideoSurfaceFormat)
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsVideoItemPrivate
+{
+public:
+ QGraphicsVideoItemPrivate()
+ : q_ptr(0)
+ , surface(0)
+ , mediaObject(0)
+ , service(0)
+ , rendererControl(0)
+ , aspectRatioMode(Qt::KeepAspectRatio)
+ , updatePaintDevice(true)
+ , rect(0.0, 0.0, 320, 240)
+ {
+ }
+
+ QGraphicsVideoItem *q_ptr;
+
+ QPainterVideoSurface *surface;
+ QPointer<QMediaObject> mediaObject;
+ QMediaService *service;
+ QVideoRendererControl *rendererControl;
+ Qt::AspectRatioMode aspectRatioMode;
+ bool updatePaintDevice;
+ QRectF rect;
+ QRectF boundingRect;
+ QRectF sourceRect;
+ QSizeF nativeSize;
+
+ void clearService();
+ void updateRects();
+
+ void _q_present();
+ void _q_formatChanged(const QVideoSurfaceFormat &format);
+ void _q_updateNativeSize();
+ void _q_serviceDestroyed();
+};
+
+void QGraphicsVideoItemPrivate::clearService()
+{
+ if (rendererControl) {
+ surface->stop();
+ rendererControl->setSurface(0);
+ service->releaseControl(rendererControl);
+ rendererControl = 0;
+ }
+ if (service) {
+ QObject::disconnect(service, SIGNAL(destroyed()), q_ptr, SLOT(_q_serviceDestroyed()));
+ service = 0;
+ }
+}
+
+void QGraphicsVideoItemPrivate::updateRects()
+{
+ q_ptr->prepareGeometryChange();
+
+ if (nativeSize.isEmpty()) {
+ //this is necessary for item to receive the
+ //first paint event and configure video surface.
+ boundingRect = rect;
+ } else if (aspectRatioMode == Qt::IgnoreAspectRatio) {
+ boundingRect = rect;
+ sourceRect = QRectF(0, 0, 1, 1);
+ } else if (aspectRatioMode == Qt::KeepAspectRatio) {
+ QSizeF size = nativeSize;
+ size.scale(rect.size(), Qt::KeepAspectRatio);
+
+ boundingRect = QRectF(0, 0, size.width(), size.height());
+ boundingRect.moveCenter(rect.center());
+
+ sourceRect = QRectF(0, 0, 1, 1);
+ } else if (aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
+ boundingRect = rect;
+
+ QSizeF size = rect.size();
+ size.scale(nativeSize, Qt::KeepAspectRatio);
+
+ sourceRect = QRectF(
+ 0, 0, size.width() / nativeSize.width(), size.height() / nativeSize.height());
+ sourceRect.moveCenter(QPointF(0.5, 0.5));
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_present()
+{
+ if (q_ptr->isObscured()) {
+ q_ptr->update(boundingRect);
+ surface->setReady(true);
+ } else {
+ q_ptr->update(boundingRect);
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_updateNativeSize()
+{
+ const QSize &size = surface->surfaceFormat().sizeHint();
+ if (nativeSize != size) {
+ nativeSize = size;
+
+ updateRects();
+ emit q_ptr->nativeSizeChanged(nativeSize);
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_serviceDestroyed()
+{
+ rendererControl = 0;
+ service = 0;
+
+ surface->stop();
+}
+
+
+/*!
+ \class QGraphicsVideoItem
+
+ \brief The QGraphicsVideoItem class provides a graphics item which display video produced by a QMediaObject.
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ Attaching a QGraphicsVideoItem to a QMediaObject allows it to display
+ the video or image output of that media object. A QGraphicsVideoItem
+ is attached to a media object by passing a pointer to the QMediaObject
+ to the setMediaObject() function.
+
+ \snippet doc/src/snippets/multimedia-snippets/video.cpp Video graphics item
+
+ \bold {Note}: Only a single display output can be attached to a media
+ object at one time.
+
+ \sa QMediaObject, QMediaPlayer, QVideoWidget
+*/
+
+/*!
+ Constructs a graphics item that displays video.
+
+ The \a parent is passed to QGraphicsItem.
+*/
+QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent)
+ : QGraphicsObject(parent)
+ , d_ptr(new QGraphicsVideoItemPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->surface = new QPainterVideoSurface;
+
+ qRegisterMetaType<QVideoSurfaceFormat>();
+
+ connect(d_ptr->surface, SIGNAL(frameChanged()), this, SLOT(_q_present()));
+ connect(d_ptr->surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SLOT(_q_updateNativeSize()), Qt::QueuedConnection);
+}
+
+/*!
+ Destroys a video graphics item.
+*/
+QGraphicsVideoItem::~QGraphicsVideoItem()
+{
+ if (d_ptr->rendererControl) {
+ d_ptr->rendererControl->setSurface(0);
+ d_ptr->service->releaseControl(d_ptr->rendererControl);
+ }
+
+ delete d_ptr->surface;
+ delete d_ptr;
+}
+
+/*!
+ \property QGraphicsVideoItem::mediaObject
+ \brief the media object which provides the video displayed by a graphics
+ item.
+ \since 1.0
+*/
+
+QMediaObject *QGraphicsVideoItem::mediaObject() const
+{
+ return d_func()->mediaObject;
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+bool QGraphicsVideoItem::setMediaObject(QMediaObject *object)
+{
+ Q_D(QGraphicsVideoItem);
+
+ if (object == d->mediaObject)
+ return true;
+
+ d->clearService();
+
+ d->mediaObject = object;
+
+ if (d->mediaObject) {
+ d->service = d->mediaObject->service();
+
+ if (d->service) {
+ QMediaControl *control = d->service->requestControl(QVideoRendererControl_iid);
+ if (control) {
+ d->rendererControl = qobject_cast<QVideoRendererControl *>(control);
+
+ if (d->rendererControl) {
+ //don't set the surface untill the item is painted
+ //at least once and the surface is configured
+ if (!d->updatePaintDevice)
+ d->rendererControl->setSurface(d->surface);
+ else
+ update(boundingRect());
+
+ connect(d->service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed()));
+
+ return true;
+ }
+ if (control)
+ d->service->releaseControl(control);
+ }
+ }
+ }
+
+ d->mediaObject = 0;
+ return false;
+}
+
+/*!
+ \property QGraphicsVideoItem::aspectRatioMode
+ \brief how a video is scaled to fit the graphics item's size.
+ \since 1.0
+*/
+
+Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode() const
+{
+ return d_func()->aspectRatioMode;
+}
+
+void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->aspectRatioMode = mode;
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::offset
+ \brief the video item's offset.
+
+ QGraphicsVideoItem will draw video using the offset for its top left
+ corner.
+ \since 1.0
+*/
+
+QPointF QGraphicsVideoItem::offset() const
+{
+ return d_func()->rect.topLeft();
+}
+
+void QGraphicsVideoItem::setOffset(const QPointF &offset)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.moveTo(offset);
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::size
+ \brief the video item's size.
+
+ QGraphicsVideoItem will draw video scaled to fit size according to its
+ fillMode.
+ \since 1.0
+*/
+
+QSizeF QGraphicsVideoItem::size() const
+{
+ return d_func()->rect.size();
+}
+
+void QGraphicsVideoItem::setSize(const QSizeF &size)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.setSize(size.isValid() ? size : QSizeF(0, 0));
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::nativeSize
+ \brief the native size of the video.
+ \since 1.0
+*/
+
+QSizeF QGraphicsVideoItem::nativeSize() const
+{
+ return d_func()->nativeSize;
+}
+
+/*!
+ \fn QGraphicsVideoItem::nativeSizeChanged(const QSizeF &size)
+
+ Signals that the native \a size of the video has changed.
+ \since 1.0
+*/
+
+/*!
+ \reimp
+ \since 1.0
+*/
+QRectF QGraphicsVideoItem::boundingRect() const
+{
+ return d_func()->boundingRect;
+}
+
+/*!
+ \reimp
+ \since 1.0
+*/
+void QGraphicsVideoItem::paint(
+ QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_D(QGraphicsVideoItem);
+
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ if (d->surface && d->updatePaintDevice) {
+ d->updatePaintDevice = false;
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ if (widget)
+ connect(widget, SIGNAL(destroyed()), d->surface, SLOT(viewportDestroyed()));
+
+ d->surface->setGLContext(const_cast<QGLContext *>(QGLContext::currentContext()));
+ if (d->surface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) {
+ d->surface->setShaderType(QPainterVideoSurface::GlslShader);
+ } else {
+ d->surface->setShaderType(QPainterVideoSurface::FragmentProgramShader);
+ }
+#endif
+ if (d->rendererControl && d->rendererControl->surface() != d->surface)
+ d->rendererControl->setSurface(d->surface);
+ }
+
+ if (d->surface && d->surface->isActive()) {
+ d->surface->paint(painter, d->boundingRect, d->sourceRect);
+ d->surface->setReady(true);
+ }
+}
+
+/*!
+ \reimp
+
+ \internal
+ \since 1.0
+*/
+QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ return QGraphicsItem::itemChange(change, value);
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+void QGraphicsVideoItem::timerEvent(QTimerEvent *event)
+{
+ QGraphicsObject::timerEvent(event);
+}
+
+#include "moc_qgraphicsvideoitem.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediakit/qgraphicsvideoitem.h b/src/multimediakit/qgraphicsvideoitem.h
new file mode 100644
index 000000000..fd39ab90a
--- /dev/null
+++ b/src/multimediakit/qgraphicsvideoitem.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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 QGRAPHICSVIDEOITEM_H
+#define QGRAPHICSVIDEOITEM_H
+
+#include <QtGui/qgraphicsitem.h>
+
+#include <qvideowidget.h>
+#include <qmediabindableinterface.h>
+
+QT_BEGIN_NAMESPACE
+class QVideoSurfaceFormat;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsVideoItemPrivate;
+class Q_MULTIMEDIA_EXPORT QGraphicsVideoItem : public QGraphicsObject, public QMediaBindableInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaBindableInterface)
+ Q_PROPERTY(QMediaObject* mediaObject READ mediaObject WRITE setMediaObject)
+ Q_PROPERTY(Qt::AspectRatioMode aspectRatioMode READ aspectRatioMode WRITE setAspectRatioMode)
+ Q_PROPERTY(QPointF offset READ offset WRITE setOffset)
+ Q_PROPERTY(QSizeF size READ size WRITE setSize)
+ Q_PROPERTY(QSizeF nativeSize READ nativeSize NOTIFY nativeSizeChanged)
+public:
+ QGraphicsVideoItem(QGraphicsItem *parent = 0);
+ ~QGraphicsVideoItem();
+
+ QMediaObject *mediaObject() const;
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ QPointF offset() const;
+ void setOffset(const QPointF &offset);
+
+ QSizeF size() const;
+ void setSize(const QSizeF &size);
+
+ QSizeF nativeSize() const;
+
+ QRectF boundingRect() const;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+Q_SIGNALS:
+ void nativeSizeChanged(const QSizeF &size);
+
+protected:
+ void timerEvent(QTimerEvent *event);
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+
+ bool setMediaObject(QMediaObject *object);
+
+ QGraphicsVideoItemPrivate *d_ptr;
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsVideoItem)
+ Q_PRIVATE_SLOT(d_func(), void _q_present())
+ Q_PRIVATE_SLOT(d_func(), void _q_updateNativeSize())
+ Q_PRIVATE_SLOT(d_func(), void _q_serviceDestroyed())
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qgraphicsvideoitem_maemo5.cpp b/src/multimediakit/qgraphicsvideoitem_maemo5.cpp
new file mode 100644
index 000000000..8551b313d
--- /dev/null
+++ b/src/multimediakit/qgraphicsvideoitem_maemo5.cpp
@@ -0,0 +1,647 @@
+/****************************************************************************
+**
+** 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/qpointer.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qbasictimer.h>
+#include <QtCore/qcoreevent.h>
+#include <QtGui/qgraphicsscene.h>
+#include <QtGui/qgraphicsview.h>
+#include <QtGui/qscrollbar.h>
+#include <QtGui/qx11info_x11.h>
+
+#include "qgraphicsvideoitem.h"
+
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qpaintervideosurface_p.h>
+#include <qvideorenderercontrol.h>
+
+#include <qvideosurfaceformat.h>
+
+#include "qxvideosurface_maemo5_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+//#define DEBUG_GFX_VIDEO_ITEM
+
+//update overlay geometry slightly later,
+//to ensure color key is alredy replaced with static frame
+#define GEOMETRY_UPDATE_DELAY 20
+//this is necessary to prevent flickering, see maemo bug 8798
+//on geometry changes, the color key is replaced with static image frame
+//until the overlay is re-initialized
+#define SOFTWARE_RENDERING_DURATION 150
+
+#ifdef __ARM_NEON__
+
+/*
+* ARM NEON optimized implementation of UYVY -> RGB16 convertor
+*/
+static void uyvy422_to_rgb16_line_neon (uint8_t * dst, const uint8_t * src, int n)
+{
+ /* and this is the NEON code itself */
+ static __attribute__ ((aligned (16))) uint16_t acc_r[8] = {
+ 22840, 22840, 22840, 22840, 22840, 22840, 22840, 22840,
+ };
+ static __attribute__ ((aligned (16))) uint16_t acc_g[8] = {
+ 17312, 17312, 17312, 17312, 17312, 17312, 17312, 17312,
+ };
+ static __attribute__ ((aligned (16))) uint16_t acc_b[8] = {
+ 28832, 28832, 28832, 28832, 28832, 28832, 28832, 28832,
+ };
+ /*
+ * Registers:
+ * q0, q1 : d0, d1, d2, d3 - are used for initial loading of YUV data
+ * q2 : d4, d5 - are used for storing converted RGB data
+ * q3 : d6, d7 - are used for temporary storage
+ *
+ * q6 : d12, d13 - are used for converting to RGB16
+ * q7 : d14, d15 - are used for storing RGB16 data
+ * q4-q5 - reserved
+ *
+ * q8, q9 : d16, d17, d18, d19 - are used for expanded Y data
+ * q10 : d20, d21
+ * q11 : d22, d23
+ * q12 : d24, d25
+ * q13 : d26, d27
+ * q13, q14, q15 - various constants (#16, #149, #204, #50, #104, #154)
+ */
+ asm volatile (".macro convert_macroblock size\n"
+ /* load up to 16 source pixels in UYVY format */
+ ".if \\size == 16\n"
+ "pld [%[src], #128]\n"
+ "vld1.32 {d0, d1, d2, d3}, [%[src]]!\n"
+ ".elseif \\size == 8\n"
+ "vld1.32 {d0, d1}, [%[src]]!\n"
+ ".elseif \\size == 4\n"
+ "vld1.32 {d0}, [%[src]]!\n"
+ ".elseif \\size == 2\n"
+ "vld1.32 {d0[0]}, [%[src]]!\n"
+ ".else\n" ".error \"unsupported macroblock size\"\n" ".endif\n"
+ /* convert from 'packed' to 'planar' representation */
+ "vuzp.8 d0, d1\n" /* d1 - separated Y data (first 8 bytes) */
+ "vuzp.8 d2, d3\n" /* d3 - separated Y data (next 8 bytes) */
+ "vuzp.8 d0, d2\n" /* d0 - separated U data, d2 - separated V data */
+ /* split even and odd Y color components */
+ "vuzp.8 d1, d3\n" /* d1 - evenY, d3 - oddY */
+ /* clip upper and lower boundaries */
+ "vqadd.u8 q0, q0, q4\n"
+ "vqadd.u8 q1, q1, q4\n"
+ "vqsub.u8 q0, q0, q5\n"
+ "vqsub.u8 q1, q1, q5\n"
+ "vshr.u8 d4, d2, #1\n" /* d4 = V >> 1 */
+ "vmull.u8 q8, d1, d27\n" /* q8 = evenY * 149 */
+ "vmull.u8 q9, d3, d27\n" /* q9 = oddY * 149 */
+ "vld1.16 {d20, d21}, [%[acc_r], :128]\n" /* q10 - initialize accumulator for red */
+ "vsubw.u8 q10, q10, d4\n" /* red acc -= (V >> 1) */
+ "vmlsl.u8 q10, d2, d28\n" /* red acc -= V * 204 */
+ "vld1.16 {d22, d23}, [%[acc_g], :128]\n" /* q11 - initialize accumulator for green */
+ "vmlsl.u8 q11, d2, d30\n" /* green acc -= V * 104 */
+ "vmlsl.u8 q11, d0, d29\n" /* green acc -= U * 50 */
+ "vld1.16 {d24, d25}, [%[acc_b], :128]\n" /* q12 - initialize accumulator for blue */
+ "vmlsl.u8 q12, d0, d30\n" /* blue acc -= U * 104 */
+ "vmlsl.u8 q12, d0, d31\n" /* blue acc -= U * 154 */
+ "vhsub.s16 q3, q8, q10\n" /* calculate even red components */
+ "vhsub.s16 q10, q9, q10\n" /* calculate odd red components */
+ "vqshrun.s16 d0, q3, #6\n" /* right shift, narrow and saturate even red components */
+ "vqshrun.s16 d3, q10, #6\n" /* right shift, narrow and saturate odd red components */
+ "vhadd.s16 q3, q8, q11\n" /* calculate even green components */
+ "vhadd.s16 q11, q9, q11\n" /* calculate odd green components */
+ "vqshrun.s16 d1, q3, #6\n" /* right shift, narrow and saturate even green components */
+ "vqshrun.s16 d4, q11, #6\n" /* right shift, narrow and saturate odd green components */
+ "vhsub.s16 q3, q8, q12\n" /* calculate even blue components */
+ "vhsub.s16 q12, q9, q12\n" /* calculate odd blue components */
+ "vqshrun.s16 d2, q3, #6\n" /* right shift, narrow and saturate even blue components */
+ "vqshrun.s16 d5, q12, #6\n" /* right shift, narrow and saturate odd blue components */
+ "vzip.8 d0, d3\n" /* join even and odd red components */
+ "vzip.8 d1, d4\n" /* join even and odd green components */
+ "vzip.8 d2, d5\n" /* join even and odd blue components */
+ "vshll.u8 q7, d0, #8\n" //red
+ "vshll.u8 q6, d1, #8\n" //greed
+ "vsri.u16 q7, q6, #5\n"
+ "vshll.u8 q6, d2, #8\n" //blue
+ "vsri.u16 q7, q6, #11\n" //now there is rgb16 in q7
+ ".if \\size == 16\n"
+ "vst1.16 {d14, d15}, [%[dst]]!\n"
+ //"vst3.8 {d0, d1, d2}, [%[dst]]!\n"
+ "vshll.u8 q7, d3, #8\n" //red
+ "vshll.u8 q6, d4, #8\n" //greed
+ "vsri.u16 q7, q6, #5\n"
+ "vshll.u8 q6, d5, #8\n" //blue
+ "vsri.u16 q7, q6, #11\n" //now there is rgb16 in q7
+ //"vst3.8 {d3, d4, d5}, [%[dst]]!\n"
+ "vst1.16 {d14, d15}, [%[dst]]!\n"
+ ".elseif \\size == 8\n"
+ "vst1.16 {d14, d15}, [%[dst]]!\n"
+ //"vst3.8 {d0, d1, d2}, [%[dst]]!\n"
+ ".elseif \\size == 4\n"
+ "vst1.8 {d14}, [%[dst]]!\n"
+ ".elseif \\size == 2\n"
+ "vst1.8 {d14[0]}, [%[dst]]!\n"
+ "vst1.8 {d14[1]}, [%[dst]]!\n"
+ ".else\n"
+ ".error \"unsupported macroblock size\"\n"
+ ".endif\n"
+ ".endm\n"
+ "vmov.u8 d8, #15\n" /* add this to U/V to saturate upper boundary */
+ "vmov.u8 d9, #20\n" /* add this to Y to saturate upper boundary */
+ "vmov.u8 d10, #31\n" /* sub this from U/V to saturate lower boundary */
+ "vmov.u8 d11, #36\n" /* sub this from Y to saturate lower boundary */
+ "vmov.u8 d26, #16\n"
+ "vmov.u8 d27, #149\n"
+ "vmov.u8 d28, #204\n"
+ "vmov.u8 d29, #50\n"
+ "vmov.u8 d30, #104\n"
+ "vmov.u8 d31, #154\n"
+ "subs %[n], %[n], #16\n"
+ "blt 2f\n"
+ "1:\n"
+ "convert_macroblock 16\n"
+ "subs %[n], %[n], #16\n"
+ "bge 1b\n"
+ "2:\n"
+ "tst %[n], #8\n"
+ "beq 3f\n"
+ "convert_macroblock 8\n"
+ "3:\n"
+ "tst %[n], #4\n"
+ "beq 4f\n"
+ "convert_macroblock 4\n"
+ "4:\n"
+ "tst %[n], #2\n"
+ "beq 5f\n"
+ "convert_macroblock 2\n"
+ "5:\n"
+ ".purgem convert_macroblock\n":[src] "+&r" (src),[dst] "+&r" (dst),
+ [n] "+&r" (n)
+ :[acc_r] "r" (&acc_r[0]),[acc_g] "r" (&acc_g[0]),[acc_b] "r" (&acc_b[0])
+ :"cc", "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
+ "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
+ "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31");
+}
+
+#endif
+
+class QGraphicsVideoItemPrivate
+{
+public:
+ QGraphicsVideoItemPrivate()
+ : q_ptr(0)
+ , surface(0)
+ , mediaObject(0)
+ , service(0)
+ , rendererControl(0)
+ , savedViewportUpdateMode(QGraphicsView::FullViewportUpdate)
+ , aspectRatioMode(Qt::KeepAspectRatio)
+ , rect(0.0, 0.0, 320, 240)
+ , softwareRenderingEnabled(false)
+ {
+ }
+
+ QGraphicsVideoItem *q_ptr;
+
+ QXVideoSurface *surface;
+ QMediaObject *mediaObject;
+ QMediaService *service;
+ QVideoRendererControl *rendererControl;
+ QPointer<QGraphicsView> currentView;
+ QGraphicsView::ViewportUpdateMode savedViewportUpdateMode;
+
+ Qt::AspectRatioMode aspectRatioMode;
+ QRectF rect;
+ QRectF boundingRect;
+ QRectF sourceRect;
+ QSizeF nativeSize;
+
+ QPixmap lastFrame;
+ QBasicTimer softwareRenderingTimer;
+ QBasicTimer geometryUpdateTimer;
+ bool softwareRenderingEnabled;
+ QRect overlayRect;
+
+ void clearService();
+ void updateRects();
+ void updateLastFrame();
+
+ void _q_present();
+ void _q_updateNativeSize();
+ void _q_serviceDestroyed();
+ void _q_mediaObjectDestroyed();
+};
+
+void QGraphicsVideoItemPrivate::clearService()
+{
+ if (rendererControl) {
+ surface->stop();
+ rendererControl->setSurface(0);
+ service->releaseControl(rendererControl);
+ rendererControl = 0;
+ }
+
+ if (service) {
+ QObject::disconnect(service, SIGNAL(destroyed()), q_ptr, SLOT(_q_serviceDestroyed()));
+ service = 0;
+ }
+}
+
+void QGraphicsVideoItemPrivate::updateRects()
+{
+ q_ptr->prepareGeometryChange();
+
+ if (nativeSize.isEmpty()) {
+ boundingRect = QRectF();
+ } else if (aspectRatioMode == Qt::IgnoreAspectRatio) {
+ boundingRect = rect;
+ sourceRect = QRectF(0, 0, 1, 1);
+ } else if (aspectRatioMode == Qt::KeepAspectRatio) {
+ QSizeF size = nativeSize;
+ size.scale(rect.size(), Qt::KeepAspectRatio);
+
+ boundingRect = QRectF(0, 0, size.width(), size.height());
+ boundingRect.moveCenter(rect.center());
+
+ sourceRect = QRectF(0, 0, 1, 1);
+ } else if (aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
+ boundingRect = rect;
+
+ QSizeF size = rect.size();
+ size.scale(nativeSize, Qt::KeepAspectRatio);
+
+ sourceRect = QRectF(
+ 0, 0, size.width() / nativeSize.width(), size.height() / nativeSize.height());
+ sourceRect.moveCenter(QPointF(0.5, 0.5));
+ }
+}
+
+void QGraphicsVideoItemPrivate::updateLastFrame()
+{
+ lastFrame = QPixmap();
+
+ if (!softwareRenderingEnabled)
+ return;
+
+ QVideoFrame lastVideoFrame = surface->lastFrame();
+
+ if (!lastVideoFrame.isValid())
+ return;
+
+ if (lastVideoFrame.map(QAbstractVideoBuffer::ReadOnly)) {
+
+#ifdef __ARM_NEON__
+ if (lastVideoFrame.pixelFormat() == QVideoFrame::Format_UYVY) {
+ QImage lastImage(lastVideoFrame.size(), QImage::Format_RGB16);
+
+ const uchar *src = lastVideoFrame.bits();
+ uchar *dst = lastImage.bits();
+ const int srcLineStep = lastVideoFrame.bytesPerLine();
+ const int dstLineStep = lastImage.bytesPerLine();
+ const int h = lastVideoFrame.height();
+ const int w = lastVideoFrame.width();
+
+ for (int y=0; y<h; y++) {
+ uyvy422_to_rgb16_line_neon(dst, src, w);
+ src += srcLineStep;
+ dst += dstLineStep;
+ }
+ lastFrame = QPixmap::fromImage(
+ lastImage.scaled(boundingRect.size().toSize(), Qt::IgnoreAspectRatio, Qt::FastTransformation));
+ } else
+#endif
+ {
+ QImage::Format imgFormat = QVideoFrame::imageFormatFromPixelFormat(lastVideoFrame.pixelFormat());
+
+ if (imgFormat != QImage::Format_Invalid) {
+ QImage lastImage(lastVideoFrame.bits(),
+ lastVideoFrame.width(),
+ lastVideoFrame.height(),
+ lastVideoFrame.bytesPerLine(),
+ imgFormat);
+
+ lastFrame = QPixmap::fromImage(
+ lastImage.scaled(boundingRect.size().toSize(), Qt::IgnoreAspectRatio, Qt::FastTransformation));
+ }
+ }
+
+ lastVideoFrame.unmap();
+ }
+
+}
+
+void QGraphicsVideoItemPrivate::_q_present()
+{
+ q_ptr->update(boundingRect);
+}
+
+void QGraphicsVideoItemPrivate::_q_updateNativeSize()
+{
+ const QSize &size = surface->surfaceFormat().sizeHint();
+ if (nativeSize != size) {
+ lastFrame = QPixmap();
+ nativeSize = size;
+
+ updateRects();
+ emit q_ptr->nativeSizeChanged(nativeSize);
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_serviceDestroyed()
+{
+ rendererControl = 0;
+ service = 0;
+
+ surface->stop();
+}
+
+void QGraphicsVideoItemPrivate::_q_mediaObjectDestroyed()
+{
+ mediaObject = 0;
+
+ clearService();
+}
+
+QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent)
+ : QGraphicsObject(parent)
+ , d_ptr(new QGraphicsVideoItemPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->surface = new QXVideoSurface;
+
+ setCacheMode(NoCache);
+ setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
+ setFlag(QGraphicsItem::ItemSendsGeometryChanges);
+ setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
+
+ connect(d_ptr->surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SLOT(_q_updateNativeSize()));
+
+ connect(d_ptr->surface, SIGNAL(activeChanged(bool)), this, SLOT(_q_present()));
+}
+
+QGraphicsVideoItem::~QGraphicsVideoItem()
+{
+ if (d_ptr->rendererControl) {
+ d_ptr->rendererControl->setSurface(0);
+ d_ptr->service->releaseControl(d_ptr->rendererControl);
+ }
+
+ if (d_ptr->currentView)
+ d_ptr->currentView->setViewportUpdateMode(d_ptr->savedViewportUpdateMode);
+
+ delete d_ptr->surface;
+ delete d_ptr;
+}
+
+QMediaObject *QGraphicsVideoItem::mediaObject() const
+{
+ return d_func()->mediaObject;
+}
+
+bool QGraphicsVideoItem::setMediaObject(QMediaObject *object)
+{
+ Q_D(QGraphicsVideoItem);
+
+ if (object == d->mediaObject)
+ return true;
+
+ d->clearService();
+
+ d->mediaObject = object;
+
+ if (d->mediaObject) {
+ d->service = d->mediaObject->service();
+
+ if (d->service) {
+ d->rendererControl = qobject_cast<QVideoRendererControl *>(
+ d->service->requestControl(QVideoRendererControl_iid));
+
+ if (d->rendererControl != 0) {
+ connect(d->service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed()));
+ d->rendererControl->setSurface(d->surface);
+ return true;
+ }
+
+ }
+ }
+
+ return false;
+}
+
+Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode() const
+{
+ return d_func()->aspectRatioMode;
+}
+
+void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->aspectRatioMode = mode;
+ d->updateRects();
+}
+
+QPointF QGraphicsVideoItem::offset() const
+{
+ return d_func()->rect.topLeft();
+}
+
+void QGraphicsVideoItem::setOffset(const QPointF &offset)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.moveTo(offset);
+ d->updateRects();
+}
+
+QSizeF QGraphicsVideoItem::size() const
+{
+ return d_func()->rect.size();
+}
+
+void QGraphicsVideoItem::setSize(const QSizeF &size)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.setSize(size.isValid() ? size : QSizeF(0, 0));
+ d->updateRects();
+}
+
+QSizeF QGraphicsVideoItem::nativeSize() const
+{
+ return d_func()->nativeSize;
+}
+
+QRectF QGraphicsVideoItem::boundingRect() const
+{
+ return d_func()->boundingRect;
+}
+
+void QGraphicsVideoItem::paint(
+ QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+#ifdef DEBUG_GFX_VIDEO_ITEM
+ qDebug() << "QGraphicsVideoItem::paint";
+#endif
+
+ Q_UNUSED(option);
+ Q_D(QGraphicsVideoItem);
+
+ QGraphicsView *view = 0;
+ if (scene() && !scene()->views().isEmpty())
+ view = scene()->views().first();
+
+ //it's necessary to switch vieport update mode to FullViewportUpdate
+ //otherwise the video item area can be just scrolled without notifying overlay
+ //about geometry changes
+ if (view != d->currentView) {
+ if (d->currentView) {
+ d->currentView->setViewportUpdateMode(d->savedViewportUpdateMode);
+ }
+
+ d->currentView = view;
+ if (view) {
+ d->savedViewportUpdateMode = view->viewportUpdateMode();
+ view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
+ }
+ }
+
+ QColor colorKey = Qt::black;
+ bool geometryChanged = false;
+
+ if (d->surface) {
+ if (widget)
+ d->surface->setWinId(widget->winId());
+
+ QTransform transform = painter->combinedTransform();
+ QRect overlayRect = transform.mapRect(boundingRect()).toRect();
+ QRect currentSurfaceRect = d->surface->displayRect();
+
+ if (widget) {
+ //workaround for xvideo issue with U/V planes swapped
+ QPoint topLeft = widget->mapToGlobal(overlayRect.topLeft());
+ if ((topLeft.x() & 1) == 0 && topLeft.x() != 0)
+ overlayRect.moveLeft(overlayRect.left()-1);
+ }
+
+ d->overlayRect = overlayRect;
+
+ if (currentSurfaceRect != overlayRect) {
+ if (!d->surface->displayRect().isEmpty()) {
+ if (d->softwareRenderingEnabled) {
+ //recalculate scaled frame pixmap if area is resized
+ if (currentSurfaceRect.size() != overlayRect.size()) {
+ d->updateLastFrame();
+ d->surface->setDisplayRect( overlayRect );
+ }
+ } else {
+ d->softwareRenderingEnabled = true;
+ d->updateLastFrame();
+
+ //don't set new geometry right now,
+ //but with small delay, to ensure the frame is already
+ //rendered on top of color key
+ if (!d->geometryUpdateTimer.isActive())
+ d->geometryUpdateTimer.start(GEOMETRY_UPDATE_DELAY, this);
+ }
+ } else
+ d->surface->setDisplayRect( overlayRect );
+
+ geometryChanged = true;
+ d->softwareRenderingTimer.start(SOFTWARE_RENDERING_DURATION, this);
+
+#ifdef DEBUG_GFX_VIDEO_ITEM
+ qDebug() << "set video display rect:" << overlayRect;
+#endif
+
+ }
+
+ colorKey = d->surface->colorKey();
+ }
+
+
+ if (!d->softwareRenderingEnabled) {
+ painter->fillRect(d->boundingRect, colorKey);
+ } else {
+ if (!d->lastFrame.isNull()) {
+ painter->drawPixmap(d->boundingRect.topLeft(), d->lastFrame );
+
+ } else
+ painter->fillRect(d->boundingRect, Qt::black);
+ }
+}
+
+QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ Q_D(QGraphicsVideoItem);
+
+ if (change == ItemScenePositionHasChanged) {
+ update(boundingRect());
+ } else {
+ return QGraphicsItem::itemChange(change, value);
+ }
+
+ return value;
+}
+
+void QGraphicsVideoItem::timerEvent(QTimerEvent *event)
+{
+ Q_D(QGraphicsVideoItem);
+
+ if (event->timerId() == d->softwareRenderingTimer.timerId() && d->softwareRenderingEnabled) {
+ d->softwareRenderingTimer.stop();
+ d->softwareRenderingEnabled = false;
+ d->updateLastFrame();
+ // repaint last frame, to ensure geometry change is applyed in paused state
+ d->surface->repaintLastFrame();
+ d->_q_present();
+ } else if ((event->timerId() == d->geometryUpdateTimer.timerId())) {
+ d->geometryUpdateTimer.stop();
+ //slightly delayed geometry update,
+ //to avoid flicker at the first geometry change
+ d->surface->setDisplayRect( d->overlayRect );
+ }
+
+ QGraphicsObject::timerEvent(event);
+}
+
+#include "moc_qgraphicsvideoitem.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediakit/qgraphicsvideoitem_maemo6.cpp b/src/multimediakit/qgraphicsvideoitem_maemo6.cpp
new file mode 100644
index 000000000..de71daf1b
--- /dev/null
+++ b/src/multimediakit/qgraphicsvideoitem_maemo6.cpp
@@ -0,0 +1,498 @@
+/****************************************************************************
+**
+** 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 "qgraphicsvideoitem.h"
+
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/qbasictimer.h>
+
+#include <QtGui/qgraphicsscene.h>
+
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qpaintervideosurface_p.h>
+#include <qeglimagetexturesurface_p.h>
+#include <qvideorenderercontrol.h>
+
+#include <qvideosurfaceformat.h>
+
+#include <X11/Xlib.h>
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+#include <QtOpenGL/qgl.h>
+#endif
+
+//#define ENABLE_OVERLAY
+
+namespace
+{
+//XInitThreads is necessary for gltexturesink element.
+//To ensure it's called before main() it's better to link to
+//libQtMultimediaKit.so directly, not when QML multimedia plugin is loaded.
+class InitThreads
+{
+public:
+ InitThreads()
+ {
+ XInitThreads();
+ }
+} _initThreads;
+}
+
+Q_DECLARE_METATYPE(QVideoSurfaceFormat)
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsVideoItemPrivate
+{
+public:
+ QGraphicsVideoItemPrivate()
+ : q_ptr(0)
+ , surface(0)
+ , mediaObject(0)
+ , service(0)
+ , rendererControl(0)
+ , aspectRatioMode(Qt::KeepAspectRatio)
+ , updatePaintDevice(true)
+ , rect(0.0, 0.0, 320, 240)
+ {
+ }
+
+ QGraphicsVideoItem *q_ptr;
+
+ QEglImageTextureSurface *surface;
+ QPointer<QMediaObject> mediaObject;
+ QMediaService *service;
+ QVideoRendererControl *rendererControl;
+ Qt::AspectRatioMode aspectRatioMode;
+ bool updatePaintDevice;
+ QRectF rect;
+ QRectF boundingRect;
+ QRectF sourceRect;
+ QSizeF nativeSize;
+
+ void clearService();
+ void updateRects();
+
+ void _q_present();
+ void _q_formatChanged(const QVideoSurfaceFormat &format);
+ void _q_updateNativeSize();
+ void _q_serviceDestroyed();
+};
+
+void QGraphicsVideoItemPrivate::clearService()
+{
+ if (rendererControl) {
+ surface->stop();
+ rendererControl->setSurface(0);
+ service->releaseControl(rendererControl);
+ rendererControl = 0;
+ }
+ if (service) {
+ QObject::disconnect(service, SIGNAL(destroyed()), q_ptr, SLOT(_q_serviceDestroyed()));
+ service = 0;
+ }
+}
+
+void QGraphicsVideoItemPrivate::updateRects()
+{
+ q_ptr->prepareGeometryChange();
+
+ if (nativeSize.isEmpty()) {
+ //this is necessary for item to receive the
+ //first paint event and configure video surface.
+ boundingRect = rect;
+ } else if (aspectRatioMode == Qt::IgnoreAspectRatio) {
+ boundingRect = rect;
+ sourceRect = QRectF(0, 0, 1, 1);
+ } else if (aspectRatioMode == Qt::KeepAspectRatio) {
+ QSizeF size = nativeSize;
+ size.scale(rect.size(), Qt::KeepAspectRatio);
+
+ boundingRect = QRectF(0, 0, size.width(), size.height());
+ boundingRect.moveCenter(rect.center());
+
+ sourceRect = QRectF(0, 0, 1, 1);
+ } else if (aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
+ boundingRect = rect;
+
+ QSizeF size = rect.size();
+ size.scale(nativeSize, Qt::KeepAspectRatio);
+
+ sourceRect = QRectF(
+ 0, 0, size.width() / nativeSize.width(), size.height() / nativeSize.height());
+ sourceRect.moveCenter(QPointF(0.5, 0.5));
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_present()
+{
+ if (q_ptr->isObscured()) {
+ q_ptr->update(boundingRect);
+ surface->setReady(true);
+ } else {
+ q_ptr->update(boundingRect);
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_updateNativeSize()
+{
+ QSize size = surface->surfaceFormat().sizeHint();
+ if (size.isEmpty())
+ size = rendererControl->property("nativeSize").toSize();
+
+ if (nativeSize != size) {
+ nativeSize = size;
+
+ updateRects();
+ emit q_ptr->nativeSizeChanged(nativeSize);
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_serviceDestroyed()
+{
+ rendererControl = 0;
+ service = 0;
+
+ surface->stop();
+}
+
+
+/*!
+ \class QGraphicsVideoItem
+
+ \brief The QGraphicsVideoItem class provides a graphics item which display video produced by a QMediaObject.
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+
+ Attaching a QGraphicsVideoItem to a QMediaObject allows it to display
+ the video or image output of that media object. A QGraphicsVideoItem
+ is attached to a media object by passing a pointer to the QMediaObject
+ to the setMediaObject() function.
+
+ \code
+ player = new QMediaPlayer(this);
+
+ QGraphicsVideoItem *item = new QGraphicsVideoItem;
+ player->setVideoOutput(item);
+ graphicsView->scene()->addItem(item);
+ graphicsView->show();
+
+ player->setMedia(video);
+ player->play();
+ \endcode
+
+ \bold {Note}: Only a single display output can be attached to a media
+ object at one time.
+
+ \sa QMediaObject, QMediaPlayer, QVideoWidget
+*/
+
+/*!
+ Constructs a graphics item that displays video.
+
+ The \a parent is passed to QGraphicsItem.
+*/
+QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent)
+ : QGraphicsObject(parent)
+ , d_ptr(new QGraphicsVideoItemPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->surface = new QEglImageTextureSurface(this);
+
+ qRegisterMetaType<QVideoSurfaceFormat>();
+
+ connect(d_ptr->surface, SIGNAL(frameChanged()), this, SLOT(_q_present()));
+ connect(d_ptr->surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SLOT(_q_updateNativeSize()), Qt::QueuedConnection);
+}
+
+/*!
+ Destroys a video graphics item.
+*/
+QGraphicsVideoItem::~QGraphicsVideoItem()
+{
+ if (d_ptr->rendererControl) {
+ d_ptr->rendererControl->setSurface(0);
+ d_ptr->service->releaseControl(d_ptr->rendererControl);
+ }
+
+ delete d_ptr->surface;
+ delete d_ptr;
+}
+
+/*!
+ \property QGraphicsVideoItem::mediaObject
+ \brief the media object which provides the video displayed by a graphics
+ item.
+*/
+
+QMediaObject *QGraphicsVideoItem::mediaObject() const
+{
+ return d_func()->mediaObject;
+}
+
+/*!
+ \internal
+*/
+bool QGraphicsVideoItem::setMediaObject(QMediaObject *object)
+{
+ Q_D(QGraphicsVideoItem);
+
+ if (object == d->mediaObject)
+ return true;
+
+ d->clearService();
+
+ d->mediaObject = object;
+
+ if (d->mediaObject) {
+ d->service = d->mediaObject->service();
+
+ if (d->service) {
+ QMediaControl *control = d->service->requestControl(QVideoRendererControl_iid);
+ if (control) {
+ d->rendererControl = qobject_cast<QVideoRendererControl *>(control);
+
+ if (d->rendererControl) {
+ connect(d->rendererControl, SIGNAL(nativeSizeChanged()),
+ this, SLOT(_q_updateNativeSize()), Qt::QueuedConnection);
+ d->_q_updateNativeSize();
+ //don't set the surface untill the item is painted
+ //at least once and the surface is configured
+ if (!d->updatePaintDevice)
+ d->rendererControl->setSurface(d->surface);
+ else
+ update(boundingRect());
+
+ connect(d->service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed()));
+
+ return true;
+ }
+ if (control)
+ d->service->releaseControl(control);
+ }
+ }
+ }
+
+ d->mediaObject = 0;
+ return false;
+}
+
+/*!
+ \property QGraphicsVideoItem::aspectRatioMode
+ \brief how a video is scaled to fit the graphics item's size.
+*/
+
+Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode() const
+{
+ return d_func()->aspectRatioMode;
+}
+
+void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->aspectRatioMode = mode;
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::offset
+ \brief the video item's offset.
+
+ QGraphicsVideoItem will draw video using the offset for its top left
+ corner.
+*/
+
+QPointF QGraphicsVideoItem::offset() const
+{
+ return d_func()->rect.topLeft();
+}
+
+void QGraphicsVideoItem::setOffset(const QPointF &offset)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.moveTo(offset);
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::size
+ \brief the video item's size.
+
+ QGraphicsVideoItem will draw video scaled to fit size according to its
+ fillMode.
+*/
+
+QSizeF QGraphicsVideoItem::size() const
+{
+ return d_func()->rect.size();
+}
+
+void QGraphicsVideoItem::setSize(const QSizeF &size)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.setSize(size.isValid() ? size : QSizeF(0, 0));
+ d->updateRects();
+}
+
+/*!
+ \property QGraphicsVideoItem::nativeSize
+ \brief the native size of the video.
+*/
+
+QSizeF QGraphicsVideoItem::nativeSize() const
+{
+ return d_func()->nativeSize;
+}
+
+/*!
+ \fn QGraphicsVideoItem::nativeSizeChanged(const QSizeF &size)
+
+ Signals that the native \a size of the video has changed.
+*/
+
+/*!
+ \reimp
+*/
+QRectF QGraphicsVideoItem::boundingRect() const
+{
+ return d_func()->boundingRect;
+}
+
+/*!
+ \reimp
+*/
+void QGraphicsVideoItem::paint(
+ QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_D(QGraphicsVideoItem);
+
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+
+ if (d->surface && d->rendererControl && d->updatePaintDevice) {
+ d->updatePaintDevice = false;
+
+ if (widget)
+ d->rendererControl->setProperty("winId", qulonglong(widget->winId()));
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ if (widget)
+ connect(widget, SIGNAL(destroyed()), d->surface, SLOT(viewportDestroyed()));
+
+ d->surface->setGLContext(const_cast<QGLContext *>(QGLContext::currentContext()));
+#endif
+ if (d->rendererControl->surface() != d->surface)
+ d->rendererControl->setSurface(d->surface);
+ }
+
+
+ //overlay doesn't work reliably
+
+ //check if the item is obscured:
+#ifdef ENABLE_OVERLAY
+ if (!isObscured()) {
+ bool obscured = false;
+
+ if (scene()) {
+ foreach (QGraphicsItem *item,
+ scene()->items(mapToScene(boundingRect()), Qt::IntersectsItemBoundingRect) ) {
+ if (item->flags() & QGraphicsItem::ItemHasNoContents)
+ continue;
+
+ if (item == this)
+ break;
+
+ if (collidesWithItem(item)) {
+ obscured = true;
+ break;
+ }
+ }
+ }
+
+ d->rendererControl->setProperty("overlayEnabled", !obscured);
+ }
+
+ if (d->rendererControl->property("overlayEnabled").toBool()) {
+ QTransform transform = painter->combinedTransform();
+ QRect overlayRect = transform.mapRect(d->boundingRect).toRect();
+
+ d->rendererControl->setProperty("overlayGeometry", overlayRect);
+ QMetaObject::invokeMethod(d->rendererControl, "repaintOverlay");
+
+ painter->fillRect(d->boundingRect,
+ d->rendererControl->property("colorKey").value<QColor>());
+ } else
+#endif //ENABLE_OVERLAY
+ {
+ if (d->surface && d->surface->isActive()) {
+ d->surface->paint(painter, d->boundingRect, d->sourceRect);
+ d->surface->setReady(true);
+ }
+ }
+}
+
+/*!
+ \reimp
+
+ \internal
+*/
+QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ return QGraphicsItem::itemChange(change, value);
+}
+
+/*!
+ \internal
+*/
+void QGraphicsVideoItem::timerEvent(QTimerEvent *event)
+{
+ QGraphicsObject::timerEvent(event);
+}
+
+#include "moc_qgraphicsvideoitem.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediakit/qgraphicsvideoitem_overlay.cpp b/src/multimediakit/qgraphicsvideoitem_overlay.cpp
new file mode 100644
index 000000000..f09d25ebb
--- /dev/null
+++ b/src/multimediakit/qgraphicsvideoitem_overlay.cpp
@@ -0,0 +1,436 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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/qpointer.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qbasictimer.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/qgraphicsscene.h>
+#include <QtGui/qgraphicsview.h>
+#include <QtGui/qscrollbar.h>
+#include <QtGui/qx11info_x11.h>
+
+#include "qgraphicsvideoitem.h"
+
+#ifdef Q_OS_SYMBIAN
+#define QGRAPHICSVIDEOITEM_ROTATION_SUPPORT
+#endif
+
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qvideowindowcontrol.h>
+
+
+QT_BEGIN_NAMESPACE
+
+#define DEBUG_GFX_VIDEO_ITEM
+
+class QGraphicsVideoItemPrivate : public QObject
+{
+public:
+ QGraphicsVideoItemPrivate()
+ : q_ptr(0)
+ , mediaObject(0)
+ , service(0)
+ , windowControl(0)
+ , savedViewportUpdateMode(QGraphicsView::FullViewportUpdate)
+ , aspectRatioMode(Qt::KeepAspectRatio)
+ , rect(0.0, 0.0, 320, 240)
+ , videoWidget(0)
+ {
+ }
+
+ QGraphicsVideoItem *q_ptr;
+
+ QMediaObject *mediaObject;
+ QMediaService *service;
+ QVideoWindowControl *windowControl;
+ QPointer<QGraphicsView> currentView;
+ QList<QPointer<QObject> > eventFilterTargets;
+ QGraphicsView::ViewportUpdateMode savedViewportUpdateMode;
+
+ Qt::AspectRatioMode aspectRatioMode;
+ QRectF rect;
+ QRectF boundingRect;
+ QRectF displayRect;
+ QSizeF nativeSize;
+
+ QWidget *videoWidget;
+
+ bool eventFilter(QObject *object, QEvent *event);
+ void updateEventFilters();
+
+ void setWidget(QWidget *widget);
+ void clearService();
+ void updateRects();
+ void updateLastFrame();
+
+ void _q_present();
+ void _q_updateNativeSize();
+ void _q_serviceDestroyed();
+ void _q_mediaObjectDestroyed();
+};
+
+void QGraphicsVideoItemPrivate::_q_present()
+{
+
+}
+
+bool QGraphicsVideoItemPrivate::eventFilter(QObject *object, QEvent *event)
+{
+ if (windowControl && object == videoWidget && QEvent::WinIdChange == event->type()) {
+ windowControl->setWinId(videoWidget->effectiveWinId());
+ } else {
+ bool updateEventFiltersRequired = false;
+ bool refreshDisplayRequired = false;
+ foreach (QPointer<QObject> target, eventFilterTargets) {
+ if (object == target.data()) {
+ switch (event->type()) {
+ case QEvent::ParentChange:
+ updateEventFiltersRequired = true;
+ refreshDisplayRequired = true;
+ break;
+ case QEvent::Move:
+ case QEvent::Resize:
+ refreshDisplayRequired = true;
+ break;
+ }
+ }
+ }
+ if (updateEventFiltersRequired)
+ updateEventFilters();
+#ifdef Q_OS_SYMBIAN
+ if (refreshDisplayRequired && windowControl)
+ QMetaObject::invokeMethod(windowControl, "refreshDisplay");
+#endif
+ }
+ return false;
+}
+
+void QGraphicsVideoItemPrivate::setWidget(QWidget *widget)
+{
+ if (videoWidget != widget) {
+ videoWidget = widget;
+ if (widget) {
+ windowControl->setWinId(widget->winId());
+ widget->installEventFilter(this);
+ }
+ }
+}
+
+void QGraphicsVideoItemPrivate::clearService()
+{
+ if (windowControl) {
+ QObject::disconnect(windowControl, SIGNAL(nativeSizeChanged()), q_ptr, SLOT(_q_updateNativeSize()));
+ service->releaseControl(windowControl);
+ windowControl = 0;
+ }
+
+ if (service) {
+ QObject::disconnect(service, SIGNAL(destroyed()), q_ptr, SLOT(_q_serviceDestroyed()));
+ service = 0;
+ }
+}
+
+void QGraphicsVideoItemPrivate::updateRects()
+{
+ q_ptr->prepareGeometryChange();
+ QSizeF videoSize;
+ if (nativeSize.isEmpty()) {
+ videoSize = rect.size();
+ } else if (aspectRatioMode == Qt::IgnoreAspectRatio) {
+ videoSize = rect.size();
+ } else {
+ // KeepAspectRatio or KeepAspectRatioByExpanding
+ videoSize = nativeSize;
+ videoSize.scale(rect.size(), aspectRatioMode);
+ }
+ displayRect = QRectF(QPointF(0, 0), videoSize);
+ displayRect.moveCenter(rect.center());
+ boundingRect = displayRect.intersected(rect);
+}
+
+void QGraphicsVideoItemPrivate::updateLastFrame()
+{
+}
+
+void QGraphicsVideoItemPrivate::updateEventFilters()
+{
+ // In order to determine when the absolute screen position of the item
+ // changes, we need to receive move events sent to m_currentView
+ // or any of its ancestors.
+ foreach (QPointer<QObject> target, eventFilterTargets)
+ if (target)
+ target->removeEventFilter(this);
+ eventFilterTargets.clear();
+ QObject *target = currentView;
+ while (target) {
+ target->installEventFilter(this);
+ eventFilterTargets.append(target);
+ target = target->parent();
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_updateNativeSize()
+{
+ const QSize size = windowControl->nativeSize();
+ if (nativeSize != size) {
+ nativeSize = size;
+
+ updateRects();
+ emit q_ptr->nativeSizeChanged(nativeSize);
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_serviceDestroyed()
+{
+ windowControl = 0;
+ service = 0;
+}
+
+void QGraphicsVideoItemPrivate::_q_mediaObjectDestroyed()
+{
+ mediaObject = 0;
+
+ clearService();
+}
+
+QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent)
+ : QGraphicsObject(parent)
+ , d_ptr(new QGraphicsVideoItemPrivate)
+{
+ d_ptr->q_ptr = this;
+
+ setCacheMode(NoCache);
+ setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
+ setFlag(QGraphicsItem::ItemSendsGeometryChanges);
+ setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
+}
+
+QGraphicsVideoItem::~QGraphicsVideoItem()
+{
+ if (d_ptr->windowControl) {
+ d_ptr->service->releaseControl(d_ptr->windowControl);
+ }
+
+ if (d_ptr->currentView)
+ d_ptr->currentView->setViewportUpdateMode(d_ptr->savedViewportUpdateMode);
+
+ delete d_ptr;
+}
+
+QMediaObject *QGraphicsVideoItem::mediaObject() const
+{
+ return d_func()->mediaObject;
+}
+
+bool QGraphicsVideoItem::setMediaObject(QMediaObject *object)
+{
+ Q_D(QGraphicsVideoItem);
+
+ if (object == d->mediaObject)
+ return true;
+
+ d->clearService();
+
+ d->mediaObject = object;
+
+ if (d->mediaObject) {
+ d->service = d->mediaObject->service();
+
+ if (d->service) {
+ d->windowControl = qobject_cast<QVideoWindowControl *>(
+ d->service->requestControl(QVideoWindowControl_iid));
+
+ if (d->windowControl != 0) {
+ connect(d->service, SIGNAL(destroyed()), SLOT(_q_serviceDestroyed()));
+ connect(d->windowControl, SIGNAL(nativeSizeChanged()), SLOT(_q_updateNativeSize()));
+ d->windowControl->setAspectRatioMode(Qt::IgnoreAspectRatio);
+ //d->windowControl->setProperty("colorKey", QVariant(QColor(16,7,2)));
+ d->windowControl->setProperty("autopaintColorKey", QVariant(false));
+
+ d->updateRects();
+ return true;
+ } else {
+ qWarning() << "Service doesn't support QVideoWindowControl, overlay item failed";
+ }
+ }
+ }
+
+ d->mediaObject = 0;
+ return false;
+}
+
+Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode() const
+{
+ return d_func()->aspectRatioMode;
+}
+
+void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->aspectRatioMode = mode;
+ d->updateRects();
+}
+
+QPointF QGraphicsVideoItem::offset() const
+{
+ return d_func()->rect.topLeft();
+}
+
+void QGraphicsVideoItem::setOffset(const QPointF &offset)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.moveTo(offset);
+ d->updateRects();
+}
+
+QSizeF QGraphicsVideoItem::size() const
+{
+ return d_func()->rect.size();
+}
+
+void QGraphicsVideoItem::setSize(const QSizeF &size)
+{
+ Q_D(QGraphicsVideoItem);
+
+ d->rect.setSize(size.isValid() ? size : QSizeF(0, 0));
+ d->updateRects();
+}
+
+QSizeF QGraphicsVideoItem::nativeSize() const
+{
+ return d_func()->nativeSize;
+}
+
+QRectF QGraphicsVideoItem::boundingRect() const
+{
+ return d_func()->boundingRect;
+}
+
+void QGraphicsVideoItem::paint(
+ QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+#ifdef DEBUG_GFX_VIDEO_ITEM
+ qDebug() << "QGraphicsVideoItem::paint";
+#endif
+
+ Q_UNUSED(option);
+ Q_D(QGraphicsVideoItem);
+
+ QGraphicsView *view = 0;
+ if (scene() && !scene()->views().isEmpty())
+ view = scene()->views().first();
+
+ //it's necessary to switch vieport update mode to FullViewportUpdate
+ //otherwise the video item area can be just scrolled without notifying overlay
+ //about geometry changes
+ if (view != d->currentView) {
+ if (d->currentView) {
+ d->currentView->setViewportUpdateMode(d->savedViewportUpdateMode);
+ }
+
+ d->currentView = view;
+ if (view) {
+ d->savedViewportUpdateMode = view->viewportUpdateMode();
+ view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
+ }
+ d->updateEventFilters();
+ }
+
+ QColor colorKey = Qt::black;
+
+ if (d->windowControl != 0 && widget != 0) {
+ d->setWidget(widget);
+
+ QTransform transform = painter->combinedTransform();
+ QRect overlayRect = transform.mapRect(d->displayRect).toRect();
+ QRect currentSurfaceRect = d->windowControl->displayRect();
+
+ if (currentSurfaceRect != overlayRect) {
+#ifdef DEBUG_GFX_VIDEO_ITEM
+ qDebug() << "set video display rect:" << overlayRect;
+#endif
+ d->windowControl->setDisplayRect(overlayRect);
+ }
+
+ colorKey = d->windowControl->property("colorKey").value<QColor>();
+#ifdef QGRAPHICSVIDEOITEM_ROTATION_SUPPORT
+ const qreal angle = transform.map(QLineF(0, 0, 1, 0)).angle();
+ d->windowControl->setProperty("rotation", QVariant::fromValue<qreal>(angle));
+#endif
+ }
+
+ if (colorKey.alpha() != 255)
+ painter->setCompositionMode(QPainter::CompositionMode_Source);
+ painter->fillRect(d->boundingRect, colorKey);
+}
+
+QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ Q_D(QGraphicsVideoItem);
+
+ switch (change) {
+ case ItemScenePositionHasChanged:
+ update(boundingRect());
+ break;
+ case ItemVisibleChange:
+ //move overlay out of the screen if video item becomes invisible
+ if (d->windowControl != 0 && !value.toBool())
+ d->windowControl->setDisplayRect(QRect(-1,-1,1,1));
+ break;
+ default:
+ break;
+ }
+
+ return QGraphicsItem::itemChange(change, value);
+}
+
+void QGraphicsVideoItem::timerEvent(QTimerEvent *event)
+{
+ QGraphicsObject::timerEvent(event);
+}
+
+#include "moc_qgraphicsvideoitem.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediakit/qgraphicsvideoitem_symbian.cpp b/src/multimediakit/qgraphicsvideoitem_symbian.cpp
new file mode 100644
index 000000000..48b2f5daa
--- /dev/null
+++ b/src/multimediakit/qgraphicsvideoitem_symbian.cpp
@@ -0,0 +1,604 @@
+/****************************************************************************
+**
+** 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/qglobal.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QEvent>
+#include <QtCore/QPointer>
+#include <QtGui/QApplication>
+#include <QtGui/QGraphicsScene>
+#include <QtGui/QGraphicsView>
+
+#include "qgraphicsvideoitem.h"
+
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qvideowidgetcontrol.h>
+
+Q_DECLARE_METATYPE(WId)
+
+static const QEvent::Type UpdateViewportTransparencyEvent =
+ static_cast<QEvent::Type>(QEvent::registerEventType());
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsVideoItemPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QGraphicsVideoItemPrivate(QGraphicsVideoItem *parent);
+ ~QGraphicsVideoItemPrivate();
+ QMediaObject *mediaObject() const;
+ bool setMediaObject(QMediaObject *mediaObject);
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+ QPointF offset() const;
+ void setOffset(const QPointF &offset);
+ QSizeF size() const;
+ void setSize(const QSizeF &size);
+ QRectF rect() const;
+ QRectF boundingRect() const;
+ QSize nativeSize() const;
+ void setCurrentView(QGraphicsView *view);
+ void setVisible(bool visible);
+ void setZValue(int zValue);
+ void setTransform(const QTransform &transform);
+ void setWithinViewBounds(bool within);
+
+ bool eventFilter(QObject *watched, QEvent *event);
+ void customEvent(QEvent *event);
+
+ void _q_present();
+ void _q_updateNativeSize();
+ void _q_serviceDestroyed();
+ void _q_mediaObjectDestroyed();
+
+public slots:
+ void updateWidgetOrdinalPosition();
+ void updateItemAncestors();
+
+private:
+ void clearService();
+ QWidget *videoWidget() const;
+ void updateGeometry();
+ void updateViewportAncestorEventFilters();
+ void updateWidgetVisibility();
+ void updateTopWinId();
+
+private:
+ QGraphicsVideoItem *q_ptr;
+ QMediaService *m_service;
+ QMediaObject *m_mediaObject;
+ QVideoWidgetControl *m_widgetControl;
+ QPointer<QGraphicsView> m_currentView;
+ QList<QPointer<QObject> > m_viewportAncestors;
+ QList<QPointer<QObject> > m_itemAncestors;
+ QGraphicsView::ViewportUpdateMode m_savedViewportUpdateMode;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QRectF m_rect;
+ QRectF m_boundingRect;
+ QSize m_nativeSize;
+ QPointF m_offset;
+ QTransform m_transform;
+ bool m_visible;
+ bool m_withinViewBounds;
+};
+
+
+QGraphicsVideoItemPrivate::QGraphicsVideoItemPrivate(QGraphicsVideoItem *parent)
+: q_ptr(parent)
+, m_service(0)
+, m_mediaObject(0)
+, m_widgetControl(0)
+, m_savedViewportUpdateMode(QGraphicsView::FullViewportUpdate)
+, m_aspectRatioMode(Qt::KeepAspectRatio)
+, m_rect(0.0, 0.0, 320.0, 240.0)
+, m_visible(false)
+, m_withinViewBounds(false)
+{
+ qRegisterMetaType<WId>("WId");
+ updateItemAncestors();
+}
+
+QGraphicsVideoItemPrivate::~QGraphicsVideoItemPrivate()
+{
+ if (m_widgetControl)
+ m_service->releaseControl(m_widgetControl);
+ setCurrentView(0);
+}
+
+QMediaObject *QGraphicsVideoItemPrivate::mediaObject() const
+{
+ return m_mediaObject;
+}
+
+bool QGraphicsVideoItemPrivate::setMediaObject(QMediaObject *mediaObject)
+{
+ bool bound = false;
+ if (m_mediaObject != mediaObject) {
+ clearService();
+ m_mediaObject = mediaObject;
+ if (m_mediaObject) {
+ m_service = m_mediaObject->service();
+ if (m_service) {
+ connect(m_service, SIGNAL(destroyed()), q_ptr, SLOT(_q_serviceDestroyed()));
+ m_widgetControl = qobject_cast<QVideoWidgetControl *>(
+ m_service->requestControl(QVideoWidgetControl_iid));
+ if (m_widgetControl) {
+ connect(m_widgetControl, SIGNAL(nativeSizeChanged()), q_ptr, SLOT(_q_updateNativeSize()));
+ m_widgetControl->setAspectRatioMode(Qt::IgnoreAspectRatio);
+ updateGeometry();
+ updateTopWinId();
+ updateWidgetOrdinalPosition();
+ updateWidgetVisibility();
+ bound = true;
+ }
+ }
+ }
+ }
+ return bound;
+}
+
+Qt::AspectRatioMode QGraphicsVideoItemPrivate::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void QGraphicsVideoItemPrivate::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ if (mode != m_aspectRatioMode) {
+ m_aspectRatioMode = mode;
+ updateGeometry();
+ }
+}
+
+QPointF QGraphicsVideoItemPrivate::offset() const
+{
+ return m_rect.topLeft();
+}
+
+void QGraphicsVideoItemPrivate::setOffset(const QPointF &offset)
+{
+ if (m_offset != offset) {
+ m_offset = offset;
+ updateGeometry();
+ }
+}
+
+QSizeF QGraphicsVideoItemPrivate::size() const
+{
+ return m_rect.size();
+}
+
+void QGraphicsVideoItemPrivate::setSize(const QSizeF &size)
+{
+ if (m_rect.size() != size) {
+ m_rect.setSize(size.isValid() ? size : QSizeF(0, 0));
+ updateGeometry();
+ }
+}
+
+QRectF QGraphicsVideoItemPrivate::rect() const
+{
+ return m_rect;
+}
+
+QRectF QGraphicsVideoItemPrivate::boundingRect() const
+{
+ return m_boundingRect;
+}
+
+QSize QGraphicsVideoItemPrivate::nativeSize() const
+{
+ return m_nativeSize;
+}
+
+void QGraphicsVideoItemPrivate::setCurrentView(QGraphicsView *view)
+{
+ if (m_currentView != view) {
+ if (m_currentView)
+ m_currentView->setViewportUpdateMode(m_savedViewportUpdateMode);
+ m_currentView = view;
+ updateTopWinId();
+ if (m_currentView) {
+ m_savedViewportUpdateMode = m_currentView->viewportUpdateMode();
+ m_currentView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
+ updateWidgetOrdinalPosition();
+ updateGeometry();
+ }
+ updateViewportAncestorEventFilters();
+ }
+}
+
+void QGraphicsVideoItemPrivate::setVisible(bool visible)
+{
+ if (m_visible != visible) {
+ m_visible = visible;
+ updateWidgetVisibility();
+ }
+}
+
+void QGraphicsVideoItemPrivate::setTransform(const QTransform &transform)
+{
+ if (m_transform != transform) {
+ m_transform = transform;
+ updateGeometry();
+ }
+}
+
+void QGraphicsVideoItemPrivate::setWithinViewBounds(bool within)
+{
+ if (m_withinViewBounds != within) {
+ m_withinViewBounds = within;
+ updateWidgetVisibility();
+ }
+}
+
+bool QGraphicsVideoItemPrivate::eventFilter(QObject *watched, QEvent *event)
+{
+ bool updateViewportAncestorEventFiltersRequired = false;
+ bool updateGeometryRequired = false;
+ foreach (QPointer<QObject> target, m_viewportAncestors) {
+ if (watched == target.data()) {
+ switch (event->type()) {
+ case QEvent::ParentChange:
+ updateViewportAncestorEventFiltersRequired = true;
+ break;
+ case QEvent::WinIdChange:
+ updateViewportAncestorEventFiltersRequired = true;
+ updateTopWinId();
+ break;
+ case QEvent::Move:
+ case QEvent::Resize:
+ updateGeometryRequired = true;
+ break;
+ }
+ }
+ }
+ if (updateViewportAncestorEventFiltersRequired)
+ updateViewportAncestorEventFilters();
+ if (updateGeometryRequired)
+ updateGeometry();
+ if (watched == m_currentView) {
+ switch (event->type()) {
+ case QEvent::Show:
+ setVisible(true);
+ break;
+ case QEvent::Hide:
+ setVisible(false);
+ break;
+ }
+ }
+ return QObject::eventFilter(watched, event);
+}
+
+void QGraphicsVideoItemPrivate::customEvent(QEvent *event)
+{
+ if (event->type() == UpdateViewportTransparencyEvent && m_currentView) {
+ m_currentView->window()->setAttribute(Qt::WA_TranslucentBackground);
+ m_currentView->window()->update();
+ }
+ QObject::customEvent(event);
+}
+
+void QGraphicsVideoItemPrivate::clearService()
+{
+ if (m_widgetControl) {
+ m_service->releaseControl(m_widgetControl);
+ m_widgetControl = 0;
+ }
+ if (m_service) {
+ m_service->disconnect(q_ptr);
+ m_service = 0;
+ }
+}
+
+QWidget *QGraphicsVideoItemPrivate::videoWidget() const
+{
+ return m_widgetControl ? m_widgetControl->videoWidget() : 0;
+}
+
+void QGraphicsVideoItemPrivate::updateViewportAncestorEventFilters()
+{
+ // In order to determine when the absolute screen position of the item
+ // changes, we need to receive move events sent to m_currentView
+ // or any of its ancestors.
+ foreach (QPointer<QObject> target, m_viewportAncestors)
+ if (target)
+ target->removeEventFilter(this);
+ m_viewportAncestors.clear();
+ QObject *target = m_currentView;
+ while (target) {
+ target->installEventFilter(this);
+ m_viewportAncestors.append(target);
+ target = target->parent();
+ }
+}
+
+void QGraphicsVideoItemPrivate::updateItemAncestors()
+{
+ // We need to monitor the ancestors of this item to check for zOrder
+ // changes and reparenting, both of which influence the stacking order
+ // of this item and so require changes to the backend window ordinal position.
+ foreach (QPointer<QObject> target, m_itemAncestors) {
+ if (target) {
+ disconnect(target, SIGNAL(zChanged()), this, SLOT(updateWidgetOrdinalPosition()));
+ disconnect(target, SIGNAL(parentChanged()), this, SLOT(updateItemAncestors()));
+ disconnect(target, SIGNAL(parentChanged()), this, SLOT(updateWidgetOrdinalPosition()));
+ }
+ }
+ m_itemAncestors.clear();
+ QGraphicsItem *item = q_ptr;
+ while (item) {
+ if (QGraphicsObject *object = item->toGraphicsObject()) {
+ connect(object, SIGNAL(zChanged()), this, SLOT(updateWidgetOrdinalPosition()));
+ connect(object, SIGNAL(parentChanged()), this, SLOT(updateItemAncestors()));
+ connect(object, SIGNAL(parentChanged()), this, SLOT(updateWidgetOrdinalPosition()));
+ m_itemAncestors.append(object);
+ }
+ item = item->parentItem();
+ }
+}
+
+void QGraphicsVideoItemPrivate::updateGeometry()
+{
+ q_ptr->prepareGeometryChange();
+ QSizeF videoSize;
+ if (m_nativeSize.isEmpty()) {
+ videoSize = m_rect.size();
+ } else if (m_aspectRatioMode == Qt::IgnoreAspectRatio) {
+ videoSize = m_rect.size();
+ } else {
+ // KeepAspectRatio or KeepAspectRatioByExpanding
+ videoSize = m_nativeSize;
+ videoSize.scale(m_rect.size(), m_aspectRatioMode);
+ }
+ QRectF displayRect(QPointF(0, 0), videoSize);
+ displayRect.moveCenter(m_rect.center());
+ m_boundingRect = displayRect.intersected(m_rect);
+ if (QWidget *widget = videoWidget()) {
+ QRect widgetGeometry;
+ QRect extent;
+ if (m_currentView) {
+ const QRectF viewRectF = m_transform.mapRect(displayRect);
+ const QRect viewRect(viewRectF.topLeft().toPoint(), viewRectF.size().toSize());
+ // Without this, a line of transparent pixels is visible round the edge of the
+ // item. This is probably down to an error in conversion between scene and
+ // screen coordinates, but the root cause has not yet been tracked down.
+ static const QPoint positionFudgeFactor(-1, -1);
+ static const QSize sizeFudgeFactor(4, 4);
+ const QRect videoGeometry(m_currentView->mapToGlobal(viewRect.topLeft()) + positionFudgeFactor,
+ viewRect.size() + sizeFudgeFactor);
+ QRect viewportGeometry = QRect(m_currentView->viewport()->mapToGlobal(QPoint(0, 0)),
+ m_currentView->viewport()->size());
+ widgetGeometry = videoGeometry.intersected(viewportGeometry);
+ extent = QRect(videoGeometry.topLeft() - widgetGeometry.topLeft(),
+ videoGeometry.size());
+ }
+ setWithinViewBounds(!widgetGeometry.size().isEmpty());
+ widget->setGeometry(widgetGeometry);
+ m_widgetControl->setProperty("extentRect", QVariant::fromValue<QRect>(extent));
+ const qreal angle = m_transform.map(QLineF(0, 0, 1, 0)).angle();
+ m_widgetControl->setProperty("rotation", QVariant::fromValue<qreal>(angle));
+ }
+}
+
+void QGraphicsVideoItemPrivate::updateWidgetVisibility()
+{
+ if (QWidget *widget = videoWidget())
+ widget->setVisible(m_visible && m_withinViewBounds);
+}
+
+void QGraphicsVideoItemPrivate::updateTopWinId()
+{
+ if (m_widgetControl) {
+ WId topWinId = m_currentView ? m_currentView->effectiveWinId() : 0;
+ // Set custom property
+ m_widgetControl->setProperty("topWinId", QVariant::fromValue<WId>(topWinId));
+ }
+}
+
+void QGraphicsVideoItemPrivate::updateWidgetOrdinalPosition()
+{
+ if (m_currentView) {
+ QGraphicsScene *scene = m_currentView->scene();
+ const QGraphicsScene::ItemIndexMethod indexMethod = scene->itemIndexMethod();
+ scene->setItemIndexMethod(QGraphicsScene::BspTreeIndex);
+ const QList<QGraphicsItem*> items = m_currentView->items();
+ QList<QGraphicsVideoItem*> graphicsVideoItems;
+ foreach (QGraphicsItem *item, items)
+ if (QGraphicsVideoItem *x = qobject_cast<QGraphicsVideoItem *>(item->toGraphicsObject()))
+ graphicsVideoItems.append(x);
+ int ordinalPosition = 1;
+ foreach (QGraphicsVideoItem *item, graphicsVideoItems)
+ if (QVideoWidgetControl *widgetControl = item->d_ptr->m_widgetControl)
+ widgetControl->setProperty("ordinalPosition", ordinalPosition++);
+ scene->setItemIndexMethod(indexMethod);
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_present()
+{
+ // Not required for this implementation of QGraphicsVideoItem
+}
+
+void QGraphicsVideoItemPrivate::_q_updateNativeSize()
+{
+ const QSize size = m_widgetControl ? m_widgetControl->property("nativeSize").value<QSize>() : QSize();
+ if (!size.isEmpty() && m_nativeSize != size) {
+ m_nativeSize = size;
+ updateGeometry();
+ emit q_ptr->nativeSizeChanged(m_nativeSize);
+ }
+}
+
+void QGraphicsVideoItemPrivate::_q_serviceDestroyed()
+{
+ m_widgetControl = 0;
+ m_service = 0;
+}
+
+void QGraphicsVideoItemPrivate::_q_mediaObjectDestroyed()
+{
+ m_mediaObject = 0;
+ clearService();
+}
+
+QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent)
+: QGraphicsObject(parent)
+, d_ptr(new QGraphicsVideoItemPrivate(this))
+{
+ setCacheMode(NoCache);
+ setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
+ setFlag(QGraphicsItem::ItemSendsGeometryChanges);
+ setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
+}
+
+QGraphicsVideoItem::~QGraphicsVideoItem()
+{
+ delete d_ptr;
+}
+
+QMediaObject *QGraphicsVideoItem::mediaObject() const
+{
+ return d_func()->mediaObject();
+}
+
+bool QGraphicsVideoItem::setMediaObject(QMediaObject *object)
+{
+ return d_func()->setMediaObject(object);
+}
+
+Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode() const
+{
+ return d_func()->aspectRatioMode();
+}
+
+void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ d_func()->setAspectRatioMode(mode);
+}
+
+QPointF QGraphicsVideoItem::offset() const
+{
+ return d_func()->offset();
+}
+
+void QGraphicsVideoItem::setOffset(const QPointF &offset)
+{
+ d_func()->setOffset(offset);
+}
+
+QSizeF QGraphicsVideoItem::size() const
+{
+ return d_func()->size();
+}
+
+void QGraphicsVideoItem::setSize(const QSizeF &size)
+{
+ d_func()->setSize(size);
+}
+
+QSizeF QGraphicsVideoItem::nativeSize() const
+{
+ return d_func()->nativeSize();
+}
+
+QRectF QGraphicsVideoItem::boundingRect() const
+{
+ return d_func()->boundingRect();
+}
+
+void QGraphicsVideoItem::paint(
+ QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ Q_UNUSED(option);
+ Q_D(QGraphicsVideoItem);
+ QGraphicsView *view = 0;
+ if (scene() && !scene()->views().isEmpty())
+ view = scene()->views().first();
+ d->setCurrentView(view);
+ d->setTransform(painter->combinedTransform());
+ if (widget && !widget->window()->testAttribute(Qt::WA_TranslucentBackground)) {
+ // On Symbian, setting Qt::WA_TranslucentBackground can cause the
+ // current window surface to be replaced. Because of this, it cannot
+ // safely be changed from the context of the viewport paintEvent(), so we
+ // queue a custom event to set the attribute.
+ QEvent *event = new QEvent(UpdateViewportTransparencyEvent);
+ QCoreApplication::instance()->postEvent(d, event);
+ }
+ const QPainter::CompositionMode oldCompositionMode = painter->compositionMode();
+ painter->setCompositionMode(QPainter::CompositionMode_Source);
+ painter->fillRect(d->boundingRect(), Qt::transparent);
+ painter->setCompositionMode(oldCompositionMode);
+}
+
+QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ Q_D(QGraphicsVideoItem);
+ switch (change) {
+ case ItemScenePositionHasChanged:
+ update(boundingRect());
+ break;
+ case ItemVisibleChange:
+ d->setVisible(value.toBool());
+ break;
+ case ItemZValueHasChanged:
+ d->updateWidgetOrdinalPosition();
+ break;
+ default:
+ break;
+ }
+ return QGraphicsItem::itemChange(change, value);
+}
+
+void QGraphicsVideoItem::timerEvent(QTimerEvent *event)
+{
+ QGraphicsObject::timerEvent(event);
+}
+
+#include "qgraphicsvideoitem_symbian.moc"
+#include "moc_qgraphicsvideoitem.cpp"
+
+QT_END_NAMESPACE
diff --git a/src/multimediakit/qimageencodercontrol.cpp b/src/multimediakit/qimageencodercontrol.cpp
new file mode 100644
index 000000000..3c05bab88
--- /dev/null
+++ b/src/multimediakit/qimageencodercontrol.cpp
@@ -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$
+**
+****************************************************************************/
+
+#include "qimageencodercontrol.h"
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QImageEncoderControl
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ \brief The QImageEncoderControl class provides access to the settings of a media service that
+ performs image encoding.
+
+ If a QMediaService supports encoding image data it will implement QImageEncoderControl.
+ This control allows to \l {setImageSettings()}{set image encoding settings} and
+ provides functions for quering supported image \l {supportedImageCodecs()}{codecs} and
+ \l {supportedResolutions()}{resolutions}.
+
+ The interface name of QImageEncoderControl is \c com.nokia.Qt.QImageEncoderControl/1.0 as
+ defined in QImageEncoderControl_iid.
+
+ \sa QImageEncoderSettings, QMediaService::requestControl()
+*/
+
+/*!
+ \macro QImageEncoderControl_iid
+
+ \c com.nokia.Qt.QImageEncoderControl/1.0
+
+ Defines the interface name of the QImageEncoderControl class.
+
+ \relates QImageEncoderControl
+*/
+
+/*!
+ Constructs a new image encoder control object with the given \a parent
+*/
+QImageEncoderControl::QImageEncoderControl(QObject *parent)
+ :QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys the image encoder control.
+*/
+QImageEncoderControl::~QImageEncoderControl()
+{
+}
+
+/*!
+ \fn QImageEncoderControl::supportedResolutions(const QImageEncoderSettings &settings = QImageEncoderSettings(),
+ bool *continuous = 0) const
+
+ Returns a list of supported resolutions.
+
+ If non null image \a settings parameter is passed,
+ the returned list is reduced to resolutions supported with partial settings applied.
+ It can be used to query the list of resolutions, supported by specific image codec.
+
+ If the encoder supports arbitrary resolutions within the supported resolutions range,
+ *\a continuous is set to true, otherwise *\a continuous is set to false.
+ \since 1.0
+*/
+
+/*!
+ \fn QImageEncoderControl::supportedImageCodecs() const
+
+ Returns a list of supported image codecs.
+ \since 1.0
+*/
+
+/*!
+ \fn QImageEncoderControl::imageCodecDescription(const QString &codec) const
+
+ Returns a description of an image \a codec.
+ \since 1.0
+*/
+
+/*!
+ \fn QImageEncoderControl::imageSettings() const
+
+ Returns the currently used image encoder settings.
+
+ The returned value may be different tha passed to QImageEncoderControl::setImageSettings()
+ if the settings contains the default or undefined parameters.
+ In this case if the undefined parameters are already resolved, they should be returned.
+ \since 1.0
+*/
+
+/*!
+ \fn QImageEncoderControl::setImageSettings(const QImageEncoderSettings &settings)
+
+ Sets the selected image encoder \a settings.
+ \since 1.0
+*/
+
+#include "moc_qimageencodercontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qimageencodercontrol.h b/src/multimediakit/qimageencodercontrol.h
new file mode 100644
index 000000000..71bf65729
--- /dev/null
+++ b/src/multimediakit/qimageencodercontrol.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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 QIMAGEENCODERCONTROL_H
+#define QIMAGEENCODERCONTROL_H
+
+#include "qmediacontrol.h"
+#include "qmediarecorder.h"
+#include "qmediaencodersettings.h"
+
+#include <QtCore/qsize.h>
+
+QT_BEGIN_NAMESPACE
+class QByteArray;
+class QStringList;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QImageEncoderControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ virtual ~QImageEncoderControl();
+
+ virtual QStringList supportedImageCodecs() const = 0;
+ virtual QString imageCodecDescription(const QString &codecName) const = 0;
+
+ virtual QList<QSize> supportedResolutions(const QImageEncoderSettings &settings,
+ bool *continuous = 0) const = 0;
+
+ virtual QImageEncoderSettings imageSettings() const = 0;
+ virtual void setImageSettings(const QImageEncoderSettings &settings) = 0;
+
+protected:
+ QImageEncoderControl(QObject *parent = 0);
+};
+
+#define QImageEncoderControl_iid "com.nokia.Qt.QImageEncoderControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QImageEncoderControl, QImageEncoderControl_iid)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qlocalmediaplaylistprovider.cpp b/src/multimediakit/qlocalmediaplaylistprovider.cpp
new file mode 100644
index 000000000..1bbb2ff64
--- /dev/null
+++ b/src/multimediakit/qlocalmediaplaylistprovider.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qlocalmediaplaylistprovider.h"
+#include "qmediaplaylistprovider_p.h"
+#include "qmediacontent.h"
+
+QT_BEGIN_NAMESPACE
+
+class QLocalMediaPlaylistProviderPrivate: public QMediaPlaylistProviderPrivate
+{
+public:
+ QList<QMediaContent> resources;
+};
+
+QLocalMediaPlaylistProvider::QLocalMediaPlaylistProvider(QObject *parent)
+ :QMediaPlaylistProvider(*new QLocalMediaPlaylistProviderPrivate, parent)
+{
+}
+
+QLocalMediaPlaylistProvider::~QLocalMediaPlaylistProvider()
+{
+}
+
+bool QLocalMediaPlaylistProvider::isReadOnly() const
+{
+ return false;
+}
+
+int QLocalMediaPlaylistProvider::mediaCount() const
+{
+ return d_func()->resources.size();
+}
+
+QMediaContent QLocalMediaPlaylistProvider::media(int pos) const
+{
+ return d_func()->resources.value(pos);
+}
+
+bool QLocalMediaPlaylistProvider::addMedia(const QMediaContent &content)
+{
+ Q_D(QLocalMediaPlaylistProvider);
+
+ int pos = d->resources.count();
+
+ emit mediaAboutToBeInserted(pos, pos);
+ d->resources.append(content);
+ emit mediaInserted(pos, pos);
+
+ return true;
+}
+
+bool QLocalMediaPlaylistProvider::addMedia(const QList<QMediaContent> &items)
+{
+ Q_D(QLocalMediaPlaylistProvider);
+
+ if (items.isEmpty())
+ return true;
+
+ int pos = d->resources.count();
+ int end = pos+items.count()-1;
+
+ emit mediaAboutToBeInserted(pos, end);
+ d->resources.append(items);
+ emit mediaInserted(pos, end);
+
+ return true;
+}
+
+
+bool QLocalMediaPlaylistProvider::insertMedia(int pos, const QMediaContent &content)
+{
+ Q_D(QLocalMediaPlaylistProvider);
+
+ emit mediaAboutToBeInserted(pos, pos);
+ d->resources.insert(pos, content);
+ emit mediaInserted(pos,pos);
+
+ return true;
+}
+
+bool QLocalMediaPlaylistProvider::insertMedia(int pos, const QList<QMediaContent> &items)
+{
+ Q_D(QLocalMediaPlaylistProvider);
+
+ if (items.isEmpty())
+ return true;
+
+ const int last = pos+items.count()-1;
+
+ emit mediaAboutToBeInserted(pos, last);
+ for (int i=0; i<items.count(); i++)
+ d->resources.insert(pos+i, items.at(i));
+ emit mediaInserted(pos, last);
+
+ return true;
+}
+
+bool QLocalMediaPlaylistProvider::removeMedia(int fromPos, int toPos)
+{
+ Q_D(QLocalMediaPlaylistProvider);
+
+ Q_ASSERT(fromPos >= 0);
+ Q_ASSERT(fromPos <= toPos);
+ Q_ASSERT(toPos < mediaCount());
+
+ emit mediaAboutToBeRemoved(fromPos, toPos);
+ d->resources.erase(d->resources.begin()+fromPos, d->resources.begin()+toPos+1);
+ emit mediaRemoved(fromPos, toPos);
+
+ return true;
+}
+
+bool QLocalMediaPlaylistProvider::removeMedia(int pos)
+{
+ Q_D(QLocalMediaPlaylistProvider);
+
+ emit mediaAboutToBeRemoved(pos, pos);
+ d->resources.removeAt(pos);
+ emit mediaRemoved(pos, pos);
+
+ return true;
+}
+
+bool QLocalMediaPlaylistProvider::clear()
+{
+ Q_D(QLocalMediaPlaylistProvider);
+ if (!d->resources.isEmpty()) {
+ int lastPos = mediaCount()-1;
+ emit mediaAboutToBeRemoved(0, lastPos);
+ d->resources.clear();
+ emit mediaRemoved(0, lastPos);
+ }
+
+ return true;
+}
+
+void QLocalMediaPlaylistProvider::shuffle()
+{
+ Q_D(QLocalMediaPlaylistProvider);
+ if (!d->resources.isEmpty()) {
+ QList<QMediaContent> resources;
+
+ while (!d->resources.isEmpty()) {
+ resources.append(d->resources.takeAt(qrand() % d->resources.size()));
+ }
+
+ d->resources = resources;
+ emit mediaChanged(0, mediaCount()-1);
+ }
+
+}
+
+#include "moc_qlocalmediaplaylistprovider.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qlocalmediaplaylistprovider.h b/src/multimediakit/qlocalmediaplaylistprovider.h
new file mode 100644
index 000000000..9ce590f25
--- /dev/null
+++ b/src/multimediakit/qlocalmediaplaylistprovider.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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 QLOCALMEDIAPAYLISTPROVIDER_H
+#define QLOCALMEDIAPAYLISTPROVIDER_H
+
+#include "qmediaplaylistprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+class QLocalMediaPlaylistProviderPrivate;
+class Q_MULTIMEDIA_EXPORT QLocalMediaPlaylistProvider : public QMediaPlaylistProvider
+{
+ Q_OBJECT
+public:
+ QLocalMediaPlaylistProvider(QObject *parent=0);
+ virtual ~QLocalMediaPlaylistProvider();
+
+ virtual int mediaCount() const;
+ virtual QMediaContent media(int pos) const;
+
+ virtual bool isReadOnly() const;
+
+ virtual bool addMedia(const QMediaContent &content);
+ virtual bool addMedia(const QList<QMediaContent> &items);
+ virtual bool insertMedia(int pos, const QMediaContent &content);
+ virtual bool insertMedia(int pos, const QList<QMediaContent> &items);
+ virtual bool removeMedia(int pos);
+ virtual bool removeMedia(int start, int end);
+ virtual bool clear();
+
+public Q_SLOTS:
+ virtual void shuffle();
+
+private:
+ Q_DECLARE_PRIVATE(QLocalMediaPlaylistProvider)
+};
+
+QT_END_NAMESPACE
+
+#endif // QLOCALMEDIAPAYLISTSOURCE_H
diff --git a/src/multimediakit/qmediabindableinterface.cpp b/src/multimediakit/qmediabindableinterface.cpp
new file mode 100644
index 000000000..391d00d2b
--- /dev/null
+++ b/src/multimediakit/qmediabindableinterface.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <qmediabindableinterface.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMediaBindableInterface
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+
+ \brief The QMediaBindableInterface class is the base class for objects extending media objects functionality.
+
+ \sa
+*/
+
+/*!
+ Destroys a media helper object.
+*/
+
+QMediaBindableInterface::~QMediaBindableInterface()
+{
+}
+
+/*!
+ \fn QMediaBindableInterface::mediaObject() const;
+
+ Return the currently attached media object.
+ \since 1.0
+*/
+
+
+/*!
+ \fn QMediaBindableInterface::setMediaObject(QMediaObject *object);
+
+ Attaches to the media \a object.
+ Returns true if attached successfully, otherwise returns false.
+ \since 1.0
+*/
+
+
+
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediabindableinterface.h b/src/multimediakit/qmediabindableinterface.h
new file mode 100644
index 000000000..09f6d6e3a
--- /dev/null
+++ b/src/multimediakit/qmediabindableinterface.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMEDIABINDABLEINTERFACE_H
+#define QMEDIABINDABLEINTERFACE_H
+
+#include <qmediaobject.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMediaObject;
+
+class Q_MULTIMEDIA_EXPORT QMediaBindableInterface
+{
+public:
+ virtual ~QMediaBindableInterface();
+
+ virtual QMediaObject *mediaObject() const = 0;
+
+protected:
+ friend class QMediaObject;
+ virtual bool setMediaObject(QMediaObject *object) = 0;
+};
+
+#define QMediaBindableInterface_iid \
+ "com.nokia.Qt.QMediaBindableInterface/1.0"
+Q_DECLARE_INTERFACE(QMediaBindableInterface, QMediaBindableInterface_iid)
+
+QT_END_NAMESPACE
+
+#endif // QMEDIABINDABLEINTERFACE_H
diff --git a/src/multimediakit/qmediacontainercontrol.cpp b/src/multimediakit/qmediacontainercontrol.cpp
new file mode 100644
index 000000000..512c96211
--- /dev/null
+++ b/src/multimediakit/qmediacontainercontrol.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qmediacontainercontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMediaContainerControl
+
+ \brief The QMediaContainerControl class provides access to the output container format of a QMediaService
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ If a QMediaService supports writing encoded data it will implement
+ QMediaContainerControl. This control provides information about the output
+ containers supported by a media service and allows one to be selected as
+ the current output containers.
+
+ The functionality provided by this control is exposed to application code
+ through the QMediaRecorder class.
+
+ The interface name of QMediaContainerControl is \c com.nokia.Qt.QMediaContainerControl/1.0 as
+ defined in QMediaContainerControl_iid.
+
+ \sa QMediaService::requestControl(), QMediaRecorder
+*/
+
+/*!
+ \macro QMediaContainerControl_iid
+
+ \c com.nokia.Qt.QMediaContainerControl/1.0
+
+ Defines the interface name of the QMediaContainerControl class.
+
+ \relates QMediaContainerControl
+*/
+
+/*!
+ Constructs a new media container control with the given \a parent.
+*/
+QMediaContainerControl::QMediaContainerControl(QObject *parent)
+ :QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys a media container control.
+*/
+QMediaContainerControl::~QMediaContainerControl()
+{
+}
+
+
+/*!
+ \fn QMediaContainerControl::supportedContainers() const
+
+ Returns a list of MIME types of supported container formats.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaContainerControl::containerMimeType() const
+
+ Returns the MIME type of the selected container format.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaContainerControl::setContainerMimeType(const QString &mimeType)
+
+ Sets the current container format to the format identified by the given \a mimeType.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaContainerControl::containerDescription(const QString &mimeType) const
+
+ Returns a description of the container format identified by the given \a mimeType.
+ \since 1.0
+*/
+
+#include "moc_qmediacontainercontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediacontainercontrol.h b/src/multimediakit/qmediacontainercontrol.h
new file mode 100644
index 000000000..de26fc480
--- /dev/null
+++ b/src/multimediakit/qmediacontainercontrol.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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 QMEDIACONTAINERCONTROL_H
+#define QMEDIACONTAINERCONTROL_H
+
+#include "qmediacontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QMediaContainerControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ virtual ~QMediaContainerControl();
+
+ virtual QStringList supportedContainers() const = 0;
+ virtual QString containerMimeType() const = 0;
+ virtual void setContainerMimeType(const QString &formatMimeType) = 0;
+
+ virtual QString containerDescription(const QString &formatMimeType) const = 0;
+
+protected:
+ QMediaContainerControl(QObject *parent = 0);
+};
+
+#define QMediaContainerControl_iid "com.nokia.Qt.QMediaContainerControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QMediaContainerControl, QMediaContainerControl_iid)
+
+QT_END_NAMESPACE
+
+#endif // QMEDIACONTAINERCONTROL_H
diff --git a/src/multimediakit/qmediacontent.cpp b/src/multimediakit/qmediacontent.cpp
new file mode 100644
index 000000000..d8ead6326
--- /dev/null
+++ b/src/multimediakit/qmediacontent.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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/qurl.h>
+#include <QtCore/qvariant.h>
+
+#include "qmediacontent.h"
+
+QT_BEGIN_NAMESPACE
+
+
+class QMediaContentPrivate : public QSharedData
+{
+public:
+ QMediaContentPrivate() {}
+ QMediaContentPrivate(const QMediaResourceList &r):
+ resources(r) {}
+
+ QMediaContentPrivate(const QMediaContentPrivate &other):
+ QSharedData(other),
+ resources(other.resources)
+ {}
+
+ bool operator ==(const QMediaContentPrivate &other) const
+ {
+ return resources == other.resources;
+ }
+
+ QMediaResourceList resources;
+private:
+ QMediaContentPrivate& operator=(const QMediaContentPrivate &other);
+};
+
+
+/*!
+ \class QMediaContent
+
+ \brief The QMediaContent class provides access to the resources relating to a media content.
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ QMediaContent is used within the multimedia framework as the logical handle
+ to media content. A QMediaContent object is composed of one or more
+ \l {QMediaResource}s where each resource provides the URL and format
+ information of a different encoding of the content.
+
+ A non-null QMediaContent will always have a primary or canonical reference to
+ the content available through the canonicalUrl() or canonicalResource()
+ methods, any additional resources are optional.
+*/
+
+
+/*!
+ Constructs a null QMediaContent.
+*/
+
+QMediaContent::QMediaContent()
+{
+}
+
+/*!
+ Constructs a media content with \a url providing a reference to the content.
+ \since 1.0
+*/
+
+QMediaContent::QMediaContent(const QUrl &url):
+ d(new QMediaContentPrivate)
+{
+ d->resources << QMediaResource(url);
+}
+
+/*!
+ Constructs a media content with \a request providing a reference to the content.
+
+ This constructor can be used to reference media content via network protocols such as HTTP.
+ This may include additional information required to obtain the resource, such as Cookies or HTTP headers.
+ \since 1.0
+*/
+
+QMediaContent::QMediaContent(const QNetworkRequest &request):
+ d(new QMediaContentPrivate)
+{
+ d->resources << QMediaResource(request);
+}
+
+/*!
+ Constructs a media content with \a resource providing a reference to the content.
+ \since 1.0
+*/
+
+QMediaContent::QMediaContent(const QMediaResource &resource):
+ d(new QMediaContentPrivate)
+{
+ d->resources << resource;
+}
+
+/*!
+ Constructs a media content with \a resources providing a reference to the content.
+ \since 1.0
+*/
+
+QMediaContent::QMediaContent(const QMediaResourceList &resources):
+ d(new QMediaContentPrivate(resources))
+{
+}
+
+/*!
+ Constructs a copy of the media content \a other.
+ \since 1.0
+*/
+
+QMediaContent::QMediaContent(const QMediaContent &other):
+ d(other.d)
+{
+}
+
+/*!
+ Destroys the media content object.
+*/
+
+QMediaContent::~QMediaContent()
+{
+}
+
+/*!
+ Assigns the value of \a other to this media content.
+ \since 1.0
+*/
+
+QMediaContent& QMediaContent::operator=(const QMediaContent &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns true if \a other is equivalent to this media content; false otherwise.
+ \since 1.0
+*/
+
+bool QMediaContent::operator==(const QMediaContent &other) const
+{
+ return (d.constData() == 0 && other.d.constData() == 0) ||
+ (d.constData() != 0 && other.d.constData() != 0 &&
+ *d.constData() == *other.d.constData());
+}
+
+/*!
+ Returns true if \a other is not equivalent to this media content; false otherwise.
+ \since 1.0
+*/
+
+bool QMediaContent::operator!=(const QMediaContent &other) const
+{
+ return !(*this == other);
+}
+
+/*!
+ Returns true if this media content is null (uninitialized); false otherwise.
+ \since 1.0
+*/
+
+bool QMediaContent::isNull() const
+{
+ return d.constData() == 0;
+}
+
+/*!
+ Returns a QUrl that represents that canonical resource for this media content.
+ \since 1.0
+*/
+
+QUrl QMediaContent::canonicalUrl() const
+{
+ return canonicalResource().url();
+}
+
+/*!
+ Returns a QNetworkRequest that represents that canonical resource for this media content.
+ \since 1.0
+*/
+
+QNetworkRequest QMediaContent::canonicalRequest() const
+{
+ return canonicalResource().request();
+}
+
+/*!
+ Returns a QMediaResource that represents that canonical resource for this media content.
+ \since 1.0
+*/
+
+QMediaResource QMediaContent::canonicalResource() const
+{
+ return d.constData() != 0
+ ? d->resources.value(0)
+ : QMediaResource();
+}
+
+/*!
+ Returns a list of alternative resources for this media content. The first item in this list
+ is always the canonical resource.
+ \since 1.0
+*/
+
+QMediaResourceList QMediaContent::resources() const
+{
+ return d.constData() != 0
+ ? d->resources
+ : QMediaResourceList();
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediacontent.h b/src/multimediakit/qmediacontent.h
new file mode 100644
index 000000000..66db3d02f
--- /dev/null
+++ b/src/multimediakit/qmediacontent.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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 QMEDIACONTENT_H
+#define QMEDIACONTENT_H
+
+#include <QtCore/qmetatype.h>
+#include <QtCore/qshareddata.h>
+
+#include "qmediaresource.h"
+
+#include <qmobilityglobal.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QMediaContentPrivate;
+class Q_MULTIMEDIA_EXPORT QMediaContent
+{
+public:
+ QMediaContent();
+ QMediaContent(const QUrl &contentUrl);
+ QMediaContent(const QNetworkRequest &contentRequest);
+ QMediaContent(const QMediaResource &contentResource);
+ QMediaContent(const QMediaResourceList &resources);
+ QMediaContent(const QMediaContent &other);
+ ~QMediaContent();
+
+ QMediaContent& operator=(const QMediaContent &other);
+
+ bool operator==(const QMediaContent &other) const;
+ bool operator!=(const QMediaContent &other) const;
+
+ bool isNull() const;
+
+ QUrl canonicalUrl() const;
+ QNetworkRequest canonicalRequest() const;
+ QMediaResource canonicalResource() const;
+
+ QMediaResourceList resources() const;
+
+private:
+ QSharedDataPointer<QMediaContentPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QMediaContent)
+
+
+
+#endif // QMEDIACONTENT_H
diff --git a/src/multimediakit/qmediacontrol.cpp b/src/multimediakit/qmediacontrol.cpp
new file mode 100644
index 000000000..2e624d2df
--- /dev/null
+++ b/src/multimediakit/qmediacontrol.cpp
@@ -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$
+**
+****************************************************************************/
+
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qtimer.h>
+
+#include "qmediacontrol.h"
+#include "qmediacontrol_p.h"
+
+
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMediaControl
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+
+ \brief The QMediaControl class provides a base interface for media service controls.
+
+ Media controls provide an interface to individual features provided by a
+ media service. Most services implement a principal control which exposes
+ the core functionality of the service and a number of optional controls which
+ expose any additional functionality.
+
+ XXX concrete example of this relationship
+
+ A pointer to a control implemented by a media service can be obtained using
+ the \l {QMediaService::requestControl()} member of QMediaService. If the
+ service doesn't implement a control it will instead return a null pointer.
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Request control
+
+ Alternatively if the IId of the control has been declared using
+ Q_MEDIA_DECLARE_CONTROL the template version of
+ QMediaService::requestControl() can be used to request the service without
+ explicitly passing the IId or using qobject_cast().
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Request control templated
+
+ Most application code will not interface directly with a media service's
+ controls, instead the QMediaObject which owns the service acts as an
+ intermediary between one or more controls and the application.
+
+ \sa QMediaService, QMediaObject
+*/
+
+/*!
+ \macro Q_MEDIA_DECLARE_CONTROL(Class, IId)
+ \relates QMediaControl
+
+ The Q_MEDIA_DECLARE_CONTROL macro declares an \a IId for a \a Class that
+ inherits from QMediaControl.
+
+ Declaring an IId for a QMediaControl allows an instance of that control to
+ be requested from QMediaService::requestControl() without explicitly
+ passing the IId.
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Request control templated
+
+ \sa QMediaService::requestControl()
+*/
+
+/*!
+ Destroys a media control.
+*/
+
+QMediaControl::~QMediaControl()
+{
+ delete d_ptr;
+}
+
+/*!
+ Constructs a media control with the given \a parent.
+ \since 1.0
+*/
+
+QMediaControl::QMediaControl(QObject *parent)
+ : QObject(parent)
+ , d_ptr(new QMediaControlPrivate)
+{
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+
+QMediaControl::QMediaControl(QMediaControlPrivate &dd, QObject *parent)
+ : QObject(parent)
+ , d_ptr(&dd)
+
+{
+ d_ptr->q_ptr = this;
+}
+
+#include "moc_qmediacontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediacontrol.h b/src/multimediakit/qmediacontrol.h
new file mode 100644
index 000000000..f330122d8
--- /dev/null
+++ b/src/multimediakit/qmediacontrol.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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 QABSTRACTMEDIACONTROL_H
+#define QABSTRACTMEDIACONTROL_H
+
+#include <qmobilityglobal.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qvariant.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QMediaControlPrivate;
+class Q_MULTIMEDIA_EXPORT QMediaControl : public QObject
+{
+ Q_OBJECT
+
+public:
+ ~QMediaControl();
+
+protected:
+ QMediaControl(QObject *parent = 0);
+ QMediaControl(QMediaControlPrivate &dd, QObject *parent = 0);
+
+ QMediaControlPrivate *d_ptr;
+
+private:
+ Q_DECLARE_PRIVATE(QMediaControl)
+};
+
+template <typename T> const char *qmediacontrol_iid() { return 0; }
+
+#define Q_MEDIA_DECLARE_CONTROL(Class, IId) \
+ template <> inline const char *qmediacontrol_iid<Class *>() { return IId; }
+
+QT_END_NAMESPACE
+
+#endif // QABSTRACTMEDIACONTROL_H
diff --git a/src/multimediakit/qmediacontrol_p.h b/src/multimediakit/qmediacontrol_p.h
new file mode 100644
index 000000000..e7e5b6160
--- /dev/null
+++ b/src/multimediakit/qmediacontrol_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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 QABSTRACTMEDIACONTROL_P_H
+#define QABSTRACTMEDIACONTROL_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>
+
+QT_BEGIN_NAMESPACE
+
+class QMediaControl;
+
+class QMediaControlPrivate
+{
+public:
+ virtual ~QMediaControlPrivate() {}
+
+ QMediaControl *q_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qmediaencodersettings.cpp b/src/multimediakit/qmediaencodersettings.cpp
new file mode 100644
index 000000000..b67324fc5
--- /dev/null
+++ b/src/multimediakit/qmediaencodersettings.cpp
@@ -0,0 +1,822 @@
+/****************************************************************************
+**
+** 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 "qmediaencodersettings.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAudioEncoderSettingsPrivate : public QSharedData
+{
+public:
+ QAudioEncoderSettingsPrivate() :
+ isNull(true),
+ encodingMode(QtMultimediaKit::ConstantQualityEncoding),
+ bitrate(-1),
+ sampleRate(-1),
+ channels(-1),
+ quality(QtMultimediaKit::NormalQuality)
+ {
+ }
+
+ QAudioEncoderSettingsPrivate(const QAudioEncoderSettingsPrivate &other):
+ QSharedData(other),
+ isNull(other.isNull),
+ encodingMode(other.encodingMode),
+ codec(other.codec),
+ bitrate(other.bitrate),
+ sampleRate(other.sampleRate),
+ channels(other.channels),
+ quality(other.quality)
+ {
+ }
+
+ bool isNull;
+ QtMultimediaKit::EncodingMode encodingMode;
+ QString codec;
+ int bitrate;
+ int sampleRate;
+ int channels;
+ QtMultimediaKit::EncodingQuality quality;
+
+private:
+ QAudioEncoderSettingsPrivate& operator=(const QAudioEncoderSettingsPrivate &other);
+};
+
+/*!
+ \class QAudioEncoderSettings
+
+ \brief The QAudioEncoderSettings class provides a set of audio encoder settings.
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ A audio encoder settings object is used to specify the audio encoder
+ settings used by QMediaRecorder. Audio encoder settings are selected by
+ constructing a QAudioEncoderSettings object, setting the desired properties
+ and then passing it to a QMediaRecorder instance using the
+ QMediaRecorder::setEncodingSettings() function.
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Audio encoder settings
+
+ \sa QMediaRecorder, QAudioEncoderControl
+*/
+
+/*!
+ Construct a null audio encoder settings object.
+*/
+QAudioEncoderSettings::QAudioEncoderSettings()
+ :d(new QAudioEncoderSettingsPrivate)
+{
+}
+
+/*!
+ Constructs a copy of the audio encoder settings object \a other.
+ \since 1.0
+*/
+
+QAudioEncoderSettings::QAudioEncoderSettings(const QAudioEncoderSettings& other)
+ :d(other.d)
+{
+}
+
+/*!
+ Destroys an audio encoder settings object.
+*/
+
+QAudioEncoderSettings::~QAudioEncoderSettings()
+{
+}
+
+/*!
+ Assigns the value of \a other to an audio encoder settings object.
+ \since 1.0
+*/
+
+QAudioEncoderSettings& QAudioEncoderSettings::operator=(const QAudioEncoderSettings &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Determines if \a other is of equal value to an audio encoder settings
+ object.
+
+ Returns true if the settings objects are of equal value, and false if they
+ are not of equal value.
+ \since 1.0
+*/
+
+bool QAudioEncoderSettings::operator==(const QAudioEncoderSettings &other) const
+{
+ return (d == other.d) ||
+ (d->isNull == other.d->isNull &&
+ d->encodingMode == other.d->encodingMode &&
+ d->bitrate == other.d->bitrate &&
+ d->sampleRate == other.d->sampleRate &&
+ d->channels == other.d->channels &&
+ d->quality == other.d->quality &&
+ d->codec == other.d->codec);
+}
+
+/*!
+ Determines if \a other is of equal value to an audio encoder settings
+ object.
+
+ Returns true if the settings objects are not of equal value, and true if
+ they are of equal value.
+ \since 1.0
+*/
+
+bool QAudioEncoderSettings::operator!=(const QAudioEncoderSettings &other) const
+{
+ return !(*this == other);
+}
+
+/*!
+ Identifies if an audio settings object is initialized.
+
+ Returns true if the settings object is null, and false if it is not.
+ \since 1.0
+*/
+
+bool QAudioEncoderSettings::isNull() const
+{
+ return d->isNull;
+}
+
+/*!
+ Returns the audio encoding mode.
+
+ \since 1.0
+ \sa QtMultimediaKit::EncodingMode
+*/
+QtMultimediaKit::EncodingMode QAudioEncoderSettings::encodingMode() const
+{
+ return d->encodingMode;
+}
+
+/*!
+ Sets the audio encoding \a mode setting.
+
+ If QtMultimediaKit::ConstantQualityEncoding is set, the quality
+ encoding parameter is used and bit rate is ignored,
+ otherwise the bitrate is used.
+
+ The audio codec, channels count and sample rate settings are used in all
+ the encoding modes.
+
+ \since 1.0
+ \sa encodingMode(), QtMultimediaKit::EncodingMode
+*/
+void QAudioEncoderSettings::setEncodingMode(QtMultimediaKit::EncodingMode mode)
+{
+ d->encodingMode = mode;
+}
+
+/*!
+ Returns the audio codec.
+ \since 1.0
+*/
+QString QAudioEncoderSettings::codec() const
+{
+ return d->codec;
+}
+
+/*!
+ Sets the audio \a codec.
+ \since 1.0
+*/
+void QAudioEncoderSettings::setCodec(const QString& codec)
+{
+ d->isNull = false;
+ d->codec = codec;
+}
+
+/*!
+ Returns the bit rate of the compressed audio stream in bits per second.
+ \since 1.0
+*/
+int QAudioEncoderSettings::bitRate() const
+{
+ return d->bitrate;
+}
+
+/*!
+ Returns the number of audio channels.
+ \since 1.0
+*/
+int QAudioEncoderSettings::channelCount() const
+{
+ return d->channels;
+}
+
+/*!
+ Sets the number of audio \a channels.
+
+ A value of -1 indicates the encoder should make an optimal choice based on
+ what is available from the audio source and the limitations of the codec.
+ \since 1.0
+*/
+void QAudioEncoderSettings::setChannelCount(int channels)
+{
+ d->isNull = false;
+ d->channels = channels;
+}
+
+/*!
+ Sets the audio bit \a rate in bits per second.
+ \since 1.0
+*/
+void QAudioEncoderSettings::setBitRate(int rate)
+{
+ d->isNull = false;
+ d->bitrate = rate;
+}
+
+/*!
+ Returns the audio sample rate in Hz.
+ \since 1.0
+*/
+int QAudioEncoderSettings::sampleRate() const
+{
+ return d->sampleRate;
+}
+
+/*!
+ Sets the audio sample \a rate in Hz.
+
+ A value of -1 indicates the encoder should make an optimal choice based on what is avaialbe
+ from the audio source and the limitations of the codec.
+ \since 1.0
+ */
+void QAudioEncoderSettings::setSampleRate(int rate)
+{
+ d->isNull = false;
+ d->sampleRate = rate;
+}
+
+/*!
+ Returns the audio encoding quality.
+ \since 1.0
+*/
+
+QtMultimediaKit::EncodingQuality QAudioEncoderSettings::quality() const
+{
+ return d->quality;
+}
+
+/*!
+ Set the audio encoding \a quality.
+
+ Setting the audio quality parameter allows backend to choose the balanced
+ set of encoding parameters to achieve the desired quality level.
+
+ The \a quality settings parameter is only used in the
+ \l {QtMultimediaKit::ConstantQualityEncoding}{constant quality} \l{encodingMode()}{encoding mode}.
+ \since 1.0
+*/
+void QAudioEncoderSettings::setQuality(QtMultimediaKit::EncodingQuality quality)
+{
+ d->isNull = false;
+ d->quality = quality;
+}
+
+class QVideoEncoderSettingsPrivate : public QSharedData
+{
+public:
+ QVideoEncoderSettingsPrivate() :
+ isNull(true),
+ encodingMode(QtMultimediaKit::ConstantQualityEncoding),
+ bitrate(-1),
+ frameRate(0),
+ quality(QtMultimediaKit::NormalQuality)
+ {
+ }
+
+ QVideoEncoderSettingsPrivate(const QVideoEncoderSettingsPrivate &other):
+ QSharedData(other),
+ isNull(other.isNull),
+ encodingMode(other.encodingMode),
+ codec(other.codec),
+ bitrate(other.bitrate),
+ resolution(other.resolution),
+ frameRate(other.frameRate),
+ quality(other.quality)
+ {
+ }
+
+ bool isNull;
+ QtMultimediaKit::EncodingMode encodingMode;
+ QString codec;
+ int bitrate;
+ QSize resolution;
+ qreal frameRate;
+ QtMultimediaKit::EncodingQuality quality;
+
+private:
+ QVideoEncoderSettingsPrivate& operator=(const QVideoEncoderSettingsPrivate &other);
+};
+
+/*!
+ \class QVideoEncoderSettings
+
+ \brief The QVideoEncoderSettings class provides a set of video encoder settings.
+ \since 1.0
+
+ A video encoder settings object is used to specify the video encoder
+ settings used by QMediaRecorder. Video encoder settings are selected by
+ constructing a QVideoEncoderSettings object, setting the desired properties
+ and then passing it to a QMediaRecorder instance using the
+ QMediaRecorder::setEncodingSettings() function.
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Video encoder settings
+
+ \sa QMediaRecorder, QVideoEncoderControl
+*/
+
+/*!
+ Constructs a null video encoder settings object.
+*/
+
+QVideoEncoderSettings::QVideoEncoderSettings()
+ :d(new QVideoEncoderSettingsPrivate)
+{
+}
+
+/*!
+ Constructs a copy of the video encoder settings object \a other.
+ \since 1.0
+*/
+
+QVideoEncoderSettings::QVideoEncoderSettings(const QVideoEncoderSettings& other)
+ :d(other.d)
+{
+}
+
+/*!
+ Destroys a video encoder settings object.
+*/
+
+QVideoEncoderSettings::~QVideoEncoderSettings()
+{
+}
+
+/*!
+ Assigns the value of \a other to a video encoder settings object.
+ \since 1.0
+*/
+QVideoEncoderSettings &QVideoEncoderSettings::operator=(const QVideoEncoderSettings &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Determines if \a other is of equal value to a video encoder settings object.
+
+ Returns true if the settings objects are of equal value, and false if they
+ are not of equal value.
+ \since 1.0
+*/
+bool QVideoEncoderSettings::operator==(const QVideoEncoderSettings &other) const
+{
+ return (d == other.d) ||
+ (d->isNull == other.d->isNull &&
+ d->encodingMode == other.d->encodingMode &&
+ d->bitrate == other.d->bitrate &&
+ d->quality == other.d->quality &&
+ d->codec == other.d->codec &&
+ d->resolution == other.d->resolution &&
+ qFuzzyCompare(d->frameRate, other.d->frameRate));
+}
+
+/*!
+ Determines if \a other is of equal value to a video encoder settings object.
+
+ Returns true if the settings objects are not of equal value, and false if
+ they are of equal value.
+ \since 1.0
+*/
+bool QVideoEncoderSettings::operator!=(const QVideoEncoderSettings &other) const
+{
+ return !(*this == other);
+}
+
+/*!
+ Identifies if a video encoder settings object is uninitalized.
+
+ Returns true if the settings are null, and false if they are not.
+ \since 1.0
+*/
+bool QVideoEncoderSettings::isNull() const
+{
+ return d->isNull;
+}
+
+/*!
+ Returns the video encoding mode.
+
+ \since 1.0
+ \sa QtMultimediaKit::EncodingMode
+*/
+QtMultimediaKit::EncodingMode QVideoEncoderSettings::encodingMode() const
+{
+ return d->encodingMode;
+}
+
+/*!
+ Sets the video encoding \a mode.
+
+ If QtMultimediaKit::ConstantQualityEncoding is set,
+ the quality encoding parameter is used and bit rate is ignored,
+ otherwise the bitrate is used.
+
+ The rest of encoding settings are respected regardless of encoding mode.
+
+ \since 1.0
+ \sa QtMultimediaKit::EncodingMode
+*/
+void QVideoEncoderSettings::setEncodingMode(QtMultimediaKit::EncodingMode mode)
+{
+ d->isNull = false;
+ d->encodingMode = mode;
+}
+
+/*!
+ Returns the video codec.
+ \since 1.0
+*/
+
+QString QVideoEncoderSettings::codec() const
+{
+ return d->codec;
+}
+
+/*!
+ Sets the video \a codec.
+ \since 1.0
+*/
+void QVideoEncoderSettings::setCodec(const QString& codec)
+{
+ d->isNull = false;
+ d->codec = codec;
+}
+
+/*!
+ Returns bit rate of the encoded video stream in bits per second.
+ \since 1.0
+*/
+int QVideoEncoderSettings::bitRate() const
+{
+ return d->bitrate;
+}
+
+/*!
+ Sets the bit rate of the encoded video stream to \a value.
+ \since 1.0
+*/
+
+void QVideoEncoderSettings::setBitRate(int value)
+{
+ d->isNull = false;
+ d->bitrate = value;
+}
+
+/*!
+ Returns the video frame rate.
+ \since 1.0
+*/
+qreal QVideoEncoderSettings::frameRate() const
+{
+ return d->frameRate;
+}
+
+/*!
+ \fn QVideoEncoderSettings::setFrameRate(qreal rate)
+
+ Sets the video frame \a rate.
+
+ A value of 0 indicates the encoder should make an optimal choice based on what is available
+ from the video source and the limitations of the codec.
+ \since 1.0
+*/
+
+void QVideoEncoderSettings::setFrameRate(qreal rate)
+{
+ d->isNull = false;
+ d->frameRate = rate;
+}
+
+/*!
+ Returns the resolution of the encoded video.
+ \since 1.0
+*/
+
+QSize QVideoEncoderSettings::resolution() const
+{
+ return d->resolution;
+}
+
+/*!
+ Sets the \a resolution of the encoded video.
+
+ An empty QSize indicates the encoder should make an optimal choice based on
+ what is available from the video source and the limitations of the codec.
+ \since 1.0
+*/
+
+void QVideoEncoderSettings::setResolution(const QSize &resolution)
+{
+ d->isNull = false;
+ d->resolution = resolution;
+}
+
+/*!
+ Sets the \a width and \a height of the resolution of the encoded video.
+
+ \overload
+ \since 1.0
+*/
+
+void QVideoEncoderSettings::setResolution(int width, int height)
+{
+ d->isNull = false;
+ d->resolution = QSize(width, height);
+}
+
+/*!
+ Returns the video encoding quality.
+ \since 1.0
+*/
+
+QtMultimediaKit::EncodingQuality QVideoEncoderSettings::quality() const
+{
+ return d->quality;
+}
+
+/*!
+ Sets the video encoding \a quality.
+
+ Setting the video quality parameter allows backend to choose the balanced
+ set of encoding parameters to achieve the desired quality level.
+
+ The \a quality settings parameter is only used in the
+ \l {QtMultimediaKit::ConstantQualityEncoding}{constant quality} \l{encodingMode()}{encoding mode}.
+ The \a quality settings parameter is only used in the \l
+ {QtMultimediaKit::ConstantQualityEncoding}{constant quality}
+ \l{encodingMode()}{encoding mode}.
+ \since 1.0
+*/
+
+void QVideoEncoderSettings::setQuality(QtMultimediaKit::EncodingQuality quality)
+{
+ d->isNull = false;
+ d->quality = quality;
+}
+
+
+
+class QImageEncoderSettingsPrivate : public QSharedData
+{
+public:
+ QImageEncoderSettingsPrivate() :
+ isNull(true),
+ quality(QtMultimediaKit::NormalQuality)
+ {
+ }
+
+ QImageEncoderSettingsPrivate(const QImageEncoderSettingsPrivate &other):
+ QSharedData(other),
+ isNull(other.isNull),
+ codec(other.codec),
+ resolution(other.resolution),
+ quality(other.quality)
+ {
+ }
+
+ bool isNull;
+ QString codec;
+ QSize resolution;
+ QtMultimediaKit::EncodingQuality quality;
+
+private:
+ QImageEncoderSettingsPrivate& operator=(const QImageEncoderSettingsPrivate &other);
+};
+
+/*!
+ \class QImageEncoderSettings
+
+
+ \brief The QImageEncoderSettings class provides a set of image encoder
+ settings.
+ \since 1.0
+
+ A image encoder settings object is used to specify the image encoder
+ settings used by QCameraImageCapture. Image encoder settings are selected
+ by constructing a QImageEncoderSettings object, setting the desired
+ properties and then passing it to a QCameraImageCapture instance using the
+ QCameraImageCapture::setImageSettings() function.
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Image encoder settings
+
+ \sa QImageEncoderControl
+*/
+
+/*!
+ Constructs a null image encoder settings object.
+*/
+
+QImageEncoderSettings::QImageEncoderSettings()
+ :d(new QImageEncoderSettingsPrivate)
+{
+}
+
+/*!
+ Constructs a copy of the image encoder settings object \a other.
+ \since 1.0
+*/
+
+QImageEncoderSettings::QImageEncoderSettings(const QImageEncoderSettings& other)
+ :d(other.d)
+{
+}
+
+/*!
+ Destroys a image encoder settings object.
+*/
+
+QImageEncoderSettings::~QImageEncoderSettings()
+{
+}
+
+/*!
+ Assigns the value of \a other to a image encoder settings object.
+ \since 1.0
+*/
+QImageEncoderSettings &QImageEncoderSettings::operator=(const QImageEncoderSettings &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Determines if \a other is of equal value to a image encoder settings
+ object.
+
+ Returns true if the settings objects are of equal value, and false if they
+ are not of equal value.
+ \since 1.0
+*/
+bool QImageEncoderSettings::operator==(const QImageEncoderSettings &other) const
+{
+ return (d == other.d) ||
+ (d->isNull == other.d->isNull &&
+ d->quality == other.d->quality &&
+ d->codec == other.d->codec &&
+ d->resolution == other.d->resolution);
+
+}
+
+/*!
+ Determines if \a other is of equal value to a image encoder settings
+ object.
+
+ Returns true if the settings objects are not of equal value, and false if
+ they are of equal value.
+ \since 1.0
+*/
+bool QImageEncoderSettings::operator!=(const QImageEncoderSettings &other) const
+{
+ return !(*this == other);
+}
+
+/*!
+ Identifies if a image encoder settings object is uninitalized.
+
+ Returns true if the settings are null, and false if they are not.
+ \since 1.0
+*/
+bool QImageEncoderSettings::isNull() const
+{
+ return d->isNull;
+}
+
+/*!
+ Returns the image codec.
+ \since 1.0
+*/
+
+QString QImageEncoderSettings::codec() const
+{
+ return d->codec;
+}
+
+/*!
+ Sets the image \a codec.
+ \since 1.0
+*/
+void QImageEncoderSettings::setCodec(const QString& codec)
+{
+ d->isNull = false;
+ d->codec = codec;
+}
+
+/*!
+ Returns the resolution of the encoded image.
+ \since 1.0
+*/
+
+QSize QImageEncoderSettings::resolution() const
+{
+ return d->resolution;
+}
+
+/*!
+ Sets the \a resolution of the encoded image.
+
+ An empty QSize indicates the encoder should make an optimal choice based on
+ what is available from the image source and the limitations of the codec.
+ \since 1.0
+*/
+
+void QImageEncoderSettings::setResolution(const QSize &resolution)
+{
+ d->isNull = false;
+ d->resolution = resolution;
+}
+
+/*!
+ Sets the \a width and \a height of the resolution of the encoded image.
+
+ \overload
+ \since 1.0
+*/
+
+void QImageEncoderSettings::setResolution(int width, int height)
+{
+ d->isNull = false;
+ d->resolution = QSize(width, height);
+}
+
+/*!
+ Returns the image encoding quality.
+ \since 1.0
+*/
+
+QtMultimediaKit::EncodingQuality QImageEncoderSettings::quality() const
+{
+ return d->quality;
+}
+
+/*!
+ Sets the image encoding \a quality.
+ \since 1.0
+*/
+
+void QImageEncoderSettings::setQuality(QtMultimediaKit::EncodingQuality quality)
+{
+ d->isNull = false;
+ d->quality = quality;
+}
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaencodersettings.h b/src/multimediakit/qmediaencodersettings.h
new file mode 100644
index 000000000..1662b59c3
--- /dev/null
+++ b/src/multimediakit/qmediaencodersettings.h
@@ -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 QMEDIAENCODERSETTINGS_H
+#define QMEDIAENCODERSETTINGS_H
+
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qsize.h>
+#include <qmobilityglobal.h>
+#include "qtmedianamespace.h"
+
+QT_BEGIN_NAMESPACE
+
+
+class QAudioEncoderSettingsPrivate;
+class Q_MULTIMEDIA_EXPORT QAudioEncoderSettings
+{
+public:
+ QAudioEncoderSettings();
+ QAudioEncoderSettings(const QAudioEncoderSettings& other);
+
+ ~QAudioEncoderSettings();
+
+ QAudioEncoderSettings& operator=(const QAudioEncoderSettings &other);
+ bool operator==(const QAudioEncoderSettings &other) const;
+ bool operator!=(const QAudioEncoderSettings &other) const;
+
+ bool isNull() const;
+
+ QtMultimediaKit::EncodingMode encodingMode() const;
+ void setEncodingMode(QtMultimediaKit::EncodingMode);
+
+ QString codec() const;
+ void setCodec(const QString& codec);
+
+ int bitRate() const;
+ void setBitRate(int bitrate);
+
+ int channelCount() const;
+ void setChannelCount(int channels);
+
+ int sampleRate() const;
+ void setSampleRate(int rate);
+
+ QtMultimediaKit::EncodingQuality quality() const;
+ void setQuality(QtMultimediaKit::EncodingQuality quality);
+
+private:
+ QSharedDataPointer<QAudioEncoderSettingsPrivate> d;
+};
+
+class QVideoEncoderSettingsPrivate;
+class Q_MULTIMEDIA_EXPORT QVideoEncoderSettings
+{
+public:
+ QVideoEncoderSettings();
+ QVideoEncoderSettings(const QVideoEncoderSettings& other);
+
+ ~QVideoEncoderSettings();
+
+ QVideoEncoderSettings& operator=(const QVideoEncoderSettings &other);
+ bool operator==(const QVideoEncoderSettings &other) const;
+ bool operator!=(const QVideoEncoderSettings &other) const;
+
+ bool isNull() const;
+
+ QtMultimediaKit::EncodingMode encodingMode() const;
+ void setEncodingMode(QtMultimediaKit::EncodingMode);
+
+ QString codec() const;
+ void setCodec(const QString &);
+
+ QSize resolution() const;
+ void setResolution(const QSize &);
+ void setResolution(int width, int height);
+
+ qreal frameRate() const;
+ void setFrameRate(qreal rate);
+
+ int bitRate() const;
+ void setBitRate(int bitrate);
+
+ QtMultimediaKit::EncodingQuality quality() const;
+ void setQuality(QtMultimediaKit::EncodingQuality quality);
+
+private:
+ QSharedDataPointer<QVideoEncoderSettingsPrivate> d;
+};
+
+class QImageEncoderSettingsPrivate;
+class Q_MULTIMEDIA_EXPORT QImageEncoderSettings
+{
+public:
+ QImageEncoderSettings();
+ QImageEncoderSettings(const QImageEncoderSettings& other);
+
+ ~QImageEncoderSettings();
+
+ QImageEncoderSettings& operator=(const QImageEncoderSettings &other);
+ bool operator==(const QImageEncoderSettings &other) const;
+ bool operator!=(const QImageEncoderSettings &other) const;
+
+ bool isNull() const;
+
+ QString codec() const;
+ void setCodec(const QString &);
+
+ QSize resolution() const;
+ void setResolution(const QSize &);
+ void setResolution(int width, int height);
+
+ QtMultimediaKit::EncodingQuality quality() const;
+ void setQuality(QtMultimediaKit::EncodingQuality quality);
+
+private:
+ QSharedDataPointer<QImageEncoderSettingsPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qmediaenumdebug.h b/src/multimediakit/qmediaenumdebug.h
new file mode 100644
index 000000000..60530e3fd
--- /dev/null
+++ b/src/multimediakit/qmediaenumdebug.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** 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 QMEDIAENUMDEBUG_H
+#define QMEDIAENUMDEBUG_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/qmetaobject.h>
+#include <QtCore/qdebug.h>
+
+#ifndef QT_NO_DEBUG_STREAM
+
+#define Q_MEDIA_ENUM_DEBUG(Class,Enum) \
+inline QDebug operator<<(QDebug dbg, Class::Enum value) \
+{ \
+ int index = Class::staticMetaObject.indexOfEnumerator(#Enum); \
+ dbg.nospace() << #Class << "::" << Class::staticMetaObject.enumerator(index).valueToKey(value); \
+ return dbg.space(); \
+}
+
+#else
+
+#define Q_MEDIA_ENUM_DEBUG(Class,Enum)
+
+#endif //QT_NO_DEBUG_STREAM
+
+
+#endif
+
diff --git a/src/multimediakit/qmediaimageviewer.cpp b/src/multimediakit/qmediaimageviewer.cpp
new file mode 100644
index 000000000..4baaf6bad
--- /dev/null
+++ b/src/multimediakit/qmediaimageviewer.cpp
@@ -0,0 +1,599 @@
+/****************************************************************************
+**
+** 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 "qmediaimageviewer.h"
+
+#include "qmediaobject_p.h"
+#include "qmediaimageviewerservice_p.h"
+
+#include <qgraphicsvideoitem.h>
+#include <qmediaplaylist.h>
+#include <qmediaplaylistsourcecontrol.h>
+#include <qmediacontent.h>
+#include <qmediaresource.h>
+#include <qvideowidget.h>
+#include <qvideosurfaceoutput_p.h>
+
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/qtextstream.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMediaImageViewerPrivate : public QMediaObjectPrivate
+{
+ Q_DECLARE_NON_CONST_PUBLIC(QMediaImageViewer)
+public:
+ QMediaImageViewerPrivate():
+ viewerControl(0), playlist(0),
+ state(QMediaImageViewer::StoppedState), timeout(3000), pauseTime(0)
+ {
+ }
+
+ void _q_mediaStatusChanged(QMediaImageViewer::MediaStatus status);
+ void _q_playlistMediaChanged(const QMediaContent &content);
+ void _q_playlistDestroyed();
+
+ QMediaImageViewerControl *viewerControl;
+ QMediaPlaylist *playlist;
+ QPointer<QObject> videoOutput;
+ QVideoSurfaceOutput surfaceOutput;
+ QMediaImageViewer::State state;
+ int timeout;
+ int pauseTime;
+ QTime time;
+ QBasicTimer timer;
+ QMediaContent media;
+};
+
+void QMediaImageViewerPrivate::_q_mediaStatusChanged(QMediaImageViewer::MediaStatus status)
+{
+ switch (status) {
+ case QMediaImageViewer::NoMedia:
+ case QMediaImageViewer::LoadingMedia:
+ emit q_func()->mediaStatusChanged(status);
+ break;
+ case QMediaImageViewer::LoadedMedia:
+ if (state == QMediaImageViewer::PlayingState) {
+ time.start();
+ timer.start(qMax(0, timeout), q_func());
+ q_func()->addPropertyWatch("elapsedTime");
+ }
+ emit q_func()->mediaStatusChanged(status);
+ emit q_func()->elapsedTimeChanged(0);
+ break;
+ case QMediaImageViewer::InvalidMedia:
+ emit q_func()->mediaStatusChanged(status);
+
+ if (state == QMediaImageViewer::PlayingState) {
+ playlist->next();
+ if (playlist->currentIndex() < 0)
+ emit q_func()->stateChanged(state = QMediaImageViewer::StoppedState);
+ }
+ break;
+ }
+}
+
+void QMediaImageViewerPrivate::_q_playlistMediaChanged(const QMediaContent &content)
+{
+ media = content;
+ pauseTime = 0;
+
+ viewerControl->showMedia(media);
+
+ emit q_func()->mediaChanged(media);
+}
+
+void QMediaImageViewerPrivate::_q_playlistDestroyed()
+{
+ playlist = 0;
+ timer.stop();
+
+ if (state != QMediaImageViewer::StoppedState)
+ emit q_func()->stateChanged(state = QMediaImageViewer::StoppedState);
+
+ q_func()->setMedia(QMediaContent());
+}
+
+/*!
+ \class QMediaImageViewer
+ \brief The QMediaImageViewer class provides a means of viewing image media.
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+
+ QMediaImageViewer is used together with a media display object such as
+ QVideoWidget to present an image. A display object is attached to the
+ image viewer by means of the bind function.
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Binding
+
+ QMediaImageViewer can be paired with a QMediaPlaylist to create a slide
+ show of images. Constructing a QMediaPlaylist with a pointer to an
+ instance of QMediaImageViewer will attach it to the image viewer;
+ changing the playlist's selection will then change the media displayed
+ by the image viewer. With a playlist attached QMediaImageViewer's
+ play(), pause(), and stop() slots can be control the progression of the
+ playlist. The \l timeout property determines how long an image is
+ displayed for before progressing to the next in the playlist, and the
+ \l elapsedTime property holds how the duration the current image has
+ been displayed for.
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Playlist
+*/
+
+/*!
+ \enum QMediaImageViewer::State
+
+ Enumerates the possible control states an image viewer may be in. The
+ control state of an image viewer determines whether the image viewer is
+ automatically progressing through images in an attached playlist.
+
+ \value StoppedState The image viewer is stopped, and will not automatically move to the next
+ image. The \l elapsedTime is fixed at 0.
+ \value PlayingState The slide show is playing, and will move to the next image when the
+ \l elapsedTime reaches the \l timeout. The \l elapsedTime is being incremented.
+ \value PausedState The image viewer is paused, and will not automatically move the to next
+ image. The \l elapsedTime is fixed at the time the image viewer was paused.
+*/
+
+/*!
+ \enum QMediaImageViewer::MediaStatus
+
+ Enumerates the status of an image viewer's current media.
+
+ \value NoMedia There is no current media.
+ \value LoadingMedia The image viewer is loading the current media.
+ \value LoadedMedia The image viewer has loaded the current media.
+ \value InvalidMedia The current media cannot be loaded.
+*/
+
+/*!
+ Constructs a new image viewer with the given \a parent.
+*/
+QMediaImageViewer::QMediaImageViewer(QObject *parent)
+ : QMediaObject(*new QMediaImageViewerPrivate, parent, new QMediaImageViewerService)
+{
+ Q_D(QMediaImageViewer);
+
+ d->viewerControl = qobject_cast<QMediaImageViewerControl*>(
+ d->service->requestControl(QMediaImageViewerControl_iid));
+
+ connect(d->viewerControl, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)),
+ this, SLOT(_q_mediaStatusChanged(QMediaImageViewer::MediaStatus)));
+}
+
+/*!
+ Destroys an image viewer.
+*/
+QMediaImageViewer::~QMediaImageViewer()
+{
+ Q_D(QMediaImageViewer);
+
+ delete d->service;
+}
+
+/*!
+ \property QMediaImageViewer::state
+ \brief the playlist control state of a slide show.
+ \since 1.0
+*/
+
+QMediaImageViewer::State QMediaImageViewer::state() const
+{
+ return d_func()->state;
+}
+
+/*!
+ \fn QMediaImageViewer::stateChanged(QMediaImageViewer::State state)
+
+ Signals that the playlist control \a state of an image viewer has changed.
+ \since 1.0
+*/
+
+/*!
+ \property QMediaImageViewer::mediaStatus
+ \brief the status of the current media.
+ \since 1.0
+*/
+
+QMediaImageViewer::MediaStatus QMediaImageViewer::mediaStatus() const
+{
+ return d_func()->viewerControl->mediaStatus();
+}
+
+/*!
+ \fn QMediaImageViewer::mediaStatusChanged(QMediaImageViewer::MediaStatus status)
+
+ Signals the the \a status of the current media has changed.
+ \since 1.0
+*/
+
+/*!
+ \property QMediaImageViewer::media
+ \brief the media an image viewer is presenting.
+ \since 1.0
+*/
+
+QMediaContent QMediaImageViewer::media() const
+{
+ Q_D(const QMediaImageViewer);
+
+ return d->media;
+}
+
+void QMediaImageViewer::setMedia(const QMediaContent &media)
+{
+ Q_D(QMediaImageViewer);
+
+ if (d->playlist && d->playlist->currentMedia() != media) {
+ disconnect(d->playlist, SIGNAL(currentMediaChanged(QMediaContent)),
+ this, SLOT(_q_playlistMediaChanged(QMediaContent)));
+ disconnect(d->playlist, SIGNAL(destroyed()), this, SLOT(_q_playlistDestroyed()));
+
+ d->playlist = 0;
+ }
+
+ d->media = media;
+
+ if (d->timer.isActive()) {
+ d->pauseTime = 0;
+ d->timer.stop();
+ removePropertyWatch("elapsedTime");
+ emit elapsedTimeChanged(0);
+ }
+
+ if (d->state != QMediaImageViewer::StoppedState)
+ emit stateChanged(d->state = QMediaImageViewer::StoppedState);
+
+ d->viewerControl->showMedia(d->media);
+
+ emit mediaChanged(d->media);
+}
+
+/*!
+ Use \a playlist as the source of images to be displayed in the viewer.
+ \since 1.0
+*/
+void QMediaImageViewer::setPlaylist(QMediaPlaylist *playlist)
+{
+ Q_D(QMediaImageViewer);
+
+ if (d->playlist) {
+ disconnect(d->playlist, SIGNAL(currentMediaChanged(QMediaContent)),
+ this, SLOT(_q_playlistMediaChanged(QMediaContent)));
+ disconnect(d->playlist, SIGNAL(destroyed()), this, SLOT(_q_playlistDestroyed()));
+
+ QMediaObject::unbind(d->playlist);
+ }
+
+ d->playlist = playlist;
+
+ if (d->playlist) {
+ connect(d->playlist, SIGNAL(currentMediaChanged(QMediaContent)),
+ this, SLOT(_q_playlistMediaChanged(QMediaContent)));
+ connect(d->playlist, SIGNAL(destroyed()), this, SLOT(_q_playlistDestroyed()));
+
+ QMediaObject::bind(d->playlist);
+
+ setMedia(d->playlist->currentMedia());
+ } else {
+ setMedia(QMediaContent());
+ }
+}
+
+/*!
+ Returns the current playlist, or 0 if none.
+ \since 1.0
+*/
+QMediaPlaylist *QMediaImageViewer::playlist() const
+{
+ return d_func()->playlist;
+}
+
+/*!
+ \fn QMediaImageViewer::mediaChanged(const QMediaContent &media)
+
+ Signals that the \a media an image viewer is presenting has changed.
+ \since 1.0
+*/
+
+/*!
+ \property QMediaImageViewer::timeout
+ \brief the amount of time in milliseconds an image is displayed for before moving to the next
+ image.
+
+ The timeout only applies if the image viewer has a playlist attached and is in the PlayingState.
+ \since 1.0
+*/
+
+int QMediaImageViewer::timeout() const
+{
+ return d_func()->timeout;
+}
+
+void QMediaImageViewer::setTimeout(int timeout)
+{
+ Q_D(QMediaImageViewer);
+
+ d->timeout = qMax(0, timeout);
+
+ if (d->timer.isActive())
+ d->timer.start(qMax(0, d->timeout - d->pauseTime - d->time.elapsed()), this);
+}
+
+/*!
+ \property QMediaImageViewer::elapsedTime
+ \brief the amount of time in milliseconds that has elapsed since the current image was loaded.
+
+ The elapsed time only increases while the image viewer is in the PlayingState. If stopped the
+ elapsed time will be reset to 0.
+ \since 1.0
+*/
+
+int QMediaImageViewer::elapsedTime() const
+{
+ Q_D(const QMediaImageViewer);
+
+ int elapsedTime = d->pauseTime;
+
+ if (d->timer.isActive())
+ elapsedTime += d->time.elapsed();
+
+ return elapsedTime;
+}
+
+/*!
+ \fn QMediaImageViewer::elapsedTimeChanged(int time)
+
+ Signals that the amount of \a time in milliseconds since the current
+ image was loaded has changed.
+
+ This signal is emitted at a regular interval when the image viewer is
+ in the PlayingState and an image is loaded. The notification interval
+ is controlled by the QMediaObject::notifyInterval property.
+
+ \since 1.0
+ \sa timeout, QMediaObject::notifyInterval
+*/
+
+/*!
+ Sets a video \a widget as the current video output.
+
+ This will unbind any previous video output bound with setVideoOutput().
+ \since 1.1
+*/
+
+void QMediaImageViewer::setVideoOutput(QVideoWidget *widget)
+{
+ Q_D(QMediaImageViewer);
+
+ if (d->videoOutput)
+ unbind(d->videoOutput);
+
+ d->videoOutput = bind(widget) ? widget : 0;
+}
+
+/*!
+ Sets a video \a item as the current video output.
+
+ This will unbind any previous video output bound with setVideoOutput().
+ \since 1.1
+*/
+
+void QMediaImageViewer::setVideoOutput(QGraphicsVideoItem *item)
+{
+ Q_D(QMediaImageViewer);
+
+ if (d->videoOutput)
+ unbind(d->videoOutput);
+
+ d->videoOutput = bind(item) ? item : 0;
+}
+
+/*!
+ Sets a video \a surface as the video output of a image viewer.
+
+ If a video output has already been set on the image viewer the new surface
+ will replace it.
+ \since 1.2
+*/
+
+void QMediaImageViewer::setVideoOutput(QAbstractVideoSurface *surface)
+{
+ Q_D(QMediaImageViewer);
+
+ d->surfaceOutput.setVideoSurface(surface);
+
+ if (d->videoOutput != &d->surfaceOutput) {
+ if (d->videoOutput)
+ unbind(d->videoOutput);
+
+ d->videoOutput = bind(&d->surfaceOutput) ? &d->surfaceOutput : 0;
+ }
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+bool QMediaImageViewer::bind(QObject *object)
+{
+ if (QMediaPlaylist *playlist = qobject_cast<QMediaPlaylist *>(object)) {
+ setPlaylist(playlist);
+
+ return true;
+ } else {
+ return QMediaObject::bind(object);
+ }
+}
+
+/*!
+ \internal
+ \since 1.0
+ */
+void QMediaImageViewer::unbind(QObject *object)
+{
+ if (object == d_func()->playlist)
+ setPlaylist(0);
+ else
+ QMediaObject::unbind(object);
+}
+
+/*!
+ Starts a slide show.
+
+ If the playlist has no current media this will start at the beginning of the playlist, otherwise
+ it will resume from the current media.
+
+ If no playlist is attached to an image viewer this will do nothing.
+ \since 1.0
+*/
+void QMediaImageViewer::play()
+{
+ Q_D(QMediaImageViewer);
+
+ if (d->playlist && d->playlist->mediaCount() > 0 && d->state != PlayingState) {
+ d->state = PlayingState;
+
+ switch (d->viewerControl->mediaStatus()) {
+ case NoMedia:
+ case InvalidMedia:
+ d->playlist->next();
+ if (d->playlist->currentIndex() < 0)
+ d->state = StoppedState;
+ break;
+ case LoadingMedia:
+ break;
+ case LoadedMedia:
+ d->time.start();
+ d->timer.start(qMax(0, d->timeout - d->pauseTime), this);
+ break;
+ }
+
+ if (d->state == PlayingState)
+ emit stateChanged(d->state);
+ }
+}
+
+/*!
+ Pauses a slide show.
+
+ The current media and elapsed time are retained. If resumed, the current image will be
+ displayed for the remainder of the time out period before the next image is loaded.
+ \since 1.0
+*/
+void QMediaImageViewer::pause()
+{
+ Q_D(QMediaImageViewer);
+
+ if (d->state == PlayingState) {
+ if (d->viewerControl->mediaStatus() == LoadedMedia) {
+ d->pauseTime += d->timeout - d->time.elapsed();
+ d->timer.stop();
+ removePropertyWatch("elapsedTime");
+ }
+
+ emit stateChanged(d->state = PausedState);
+ emit elapsedTimeChanged(d->pauseTime);
+ }
+}
+
+/*!
+ Stops a slide show.
+
+ The current media is retained, but the elapsed time is discarded. If resumed, the current
+ image will be displayed for the full time out period before the next image is loaded.
+ \since 1.0
+*/
+void QMediaImageViewer::stop()
+{
+ Q_D(QMediaImageViewer);
+
+ switch (d->state) {
+ case PlayingState:
+ d->timer.stop();
+ removePropertyWatch("elapsedTime");
+ // fall through.
+ case PausedState:
+ d->pauseTime = 0;
+ d->state = QMediaImageViewer::StoppedState;
+
+ emit stateChanged(d->state);
+ emit elapsedTimeChanged(0);
+ break;
+ case StoppedState:
+ break;
+ }
+}
+
+/*!
+ \reimp
+
+ \internal
+ \since 1.0
+*/
+void QMediaImageViewer::timerEvent(QTimerEvent *event)
+{
+ Q_D(QMediaImageViewer);
+
+ if (event->timerId() == d->timer.timerId()) {
+ d->timer.stop();
+ removePropertyWatch("elapsedTime");
+ emit elapsedTimeChanged(d->pauseTime = d->timeout);
+
+ d->playlist->next();
+
+ if (d->playlist->currentIndex() < 0) {
+ d->pauseTime = 0;
+ emit stateChanged(d->state = StoppedState);
+ emit elapsedTimeChanged(0);
+ }
+ } else {
+ QMediaObject::timerEvent(event);
+ }
+}
+
+#include "moc_qmediaimageviewer.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaimageviewer.h b/src/multimediakit/qmediaimageviewer.h
new file mode 100644
index 000000000..f277f8520
--- /dev/null
+++ b/src/multimediakit/qmediaimageviewer.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** 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 QMEDIAIMAGEVIEWER_H
+#define QMEDIAIMAGEVIEWER_H
+
+#include "qmediaobject.h"
+#include "qmediacontent.h"
+#include <qmediaenumdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractVideoSurface;
+class QGraphicsVideoItem;
+class QMediaPlaylist;
+class QVideoWidget;
+
+class QMediaImageViewerPrivate;
+class Q_MULTIMEDIA_EXPORT QMediaImageViewer : public QMediaObject
+{
+ Q_OBJECT
+ Q_PROPERTY(State state READ state NOTIFY stateChanged)
+ Q_PROPERTY(MediaStatus mediaStatus READ mediaStatus NOTIFY mediaStatusChanged)
+ Q_PROPERTY(QMediaContent media READ media WRITE setMedia NOTIFY mediaChanged)
+ Q_PROPERTY(int timeout READ timeout WRITE setTimeout)
+ Q_PROPERTY(int elapsedTime READ elapsedTime NOTIFY elapsedTimeChanged)
+ Q_ENUMS(State MediaStatus)
+
+public:
+ enum State
+ {
+ StoppedState,
+ PlayingState,
+ PausedState
+ };
+
+ enum MediaStatus
+ {
+ NoMedia,
+ LoadingMedia,
+ LoadedMedia,
+ InvalidMedia
+ };
+
+ explicit QMediaImageViewer(QObject *parent = 0);
+ ~QMediaImageViewer();
+
+ State state() const;
+ MediaStatus mediaStatus() const;
+
+ QMediaContent media() const;
+ QMediaPlaylist *playlist() const;
+
+ int timeout() const;
+ int elapsedTime() const;
+
+ void setVideoOutput(QVideoWidget *widget);
+ void setVideoOutput(QGraphicsVideoItem *item);
+ void setVideoOutput(QAbstractVideoSurface *surface);
+
+ bool bind(QObject *);
+ void unbind(QObject *);
+
+public Q_SLOTS:
+ void setMedia(const QMediaContent &media);
+ void setPlaylist(QMediaPlaylist *playlist);
+
+ void play();
+ void pause();
+ void stop();
+
+ void setTimeout(int timeout);
+
+Q_SIGNALS:
+ void stateChanged(QMediaImageViewer::State state);
+ void mediaStatusChanged(QMediaImageViewer::MediaStatus status);
+ void mediaChanged(const QMediaContent &media);
+ void elapsedTimeChanged(int time);
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private:
+ Q_DECLARE_PRIVATE(QMediaImageViewer)
+ Q_PRIVATE_SLOT(d_func(), void _q_mediaStatusChanged(QMediaImageViewer::MediaStatus))
+ Q_PRIVATE_SLOT(d_func(), void _q_playlistMediaChanged(const QMediaContent &))
+ Q_PRIVATE_SLOT(d_func(), void _q_playlistDestroyed())
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QMediaImageViewer::State)
+Q_DECLARE_METATYPE(QMediaImageViewer::MediaStatus)
+
+Q_MEDIA_ENUM_DEBUG(QMediaImageViewer, State)
+Q_MEDIA_ENUM_DEBUG(QMediaImageViewer, MediaStatus)
+
+#endif
diff --git a/src/multimediakit/qmediaimageviewerservice.cpp b/src/multimediakit/qmediaimageviewerservice.cpp
new file mode 100644
index 000000000..9d00fd0b9
--- /dev/null
+++ b/src/multimediakit/qmediaimageviewerservice.cpp
@@ -0,0 +1,465 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qmediaimageviewerservice_p.h"
+
+#include "qmediacontrol_p.h"
+#include "qmediaservice_p.h"
+
+#include <qmediacontent.h>
+#include <qmediaresource.h>
+#include <qmediaobject_p.h>
+#include <qvideorenderercontrol.h>
+#include <qvideowidgetcontrol.h>
+
+#include <QtCore/qdebug.h>
+
+#include <QtCore/qurl.h>
+#include <QtGui/qimagereader.h>
+#include <QtGui/qpainter.h>
+
+#include <QtNetwork/qnetworkaccessmanager.h>
+#include <QtNetwork/qnetworkreply.h>
+#include <QtNetwork/qnetworkrequest.h>
+
+#include <qabstractvideosurface.h>
+#include <qvideosurfaceformat.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMediaImageViewerServicePrivate : public QMediaServicePrivate
+{
+public:
+ QMediaImageViewerServicePrivate()
+ : viewerControl(0)
+ , rendererControl(0)
+ , network(0)
+ , internalNetwork(0)
+ {
+ }
+
+ bool load(QIODevice *device);
+ void clear();
+
+ QMediaImageViewerControl *viewerControl;
+ QMediaImageViewerRenderer *rendererControl;
+ QNetworkAccessManager *network;
+ QNetworkAccessManager *internalNetwork;
+ QImage m_image;
+};
+
+
+QMediaImageViewerRenderer::QMediaImageViewerRenderer(QObject *parent)
+ : QVideoRendererControl(parent)
+ , m_surface(0)
+{
+}
+
+QMediaImageViewerRenderer::~QMediaImageViewerRenderer()
+{
+ if (m_surface)
+ m_surface->stop();
+}
+
+QAbstractVideoSurface *QMediaImageViewerRenderer::surface() const
+{
+ return m_surface;
+}
+
+void QMediaImageViewerRenderer::setSurface(QAbstractVideoSurface *surface)
+{
+ if (m_surface)
+ m_surface->stop();
+
+ m_surface = surface;
+
+ if (m_surface && !m_image.isNull())
+ showImage(m_image);
+}
+
+void QMediaImageViewerRenderer::showImage(const QImage &image)
+{
+ m_image = image;
+
+ if (m_surface) {
+ if (m_image.isNull()) {
+ m_surface->stop();
+ } else {
+ QVideoSurfaceFormat format(
+ image.size(), QVideoFrame::pixelFormatFromImageFormat(image.format()));
+
+ if (!m_surface->isFormatSupported(format)) {
+ foreach (QVideoFrame::PixelFormat pixelFormat, m_surface->supportedPixelFormats()) {
+ const QImage::Format imageFormat
+ = QVideoFrame::imageFormatFromPixelFormat(pixelFormat);
+
+ if (imageFormat != QImage::Format_Invalid) {
+ format = QVideoSurfaceFormat(image.size(), pixelFormat);
+
+ if (m_surface->isFormatSupported(format) && m_surface->start(format)) {
+ m_image = image.convertToFormat(imageFormat);
+
+ m_surface->present(QVideoFrame(m_image));
+
+ return;
+ }
+ }
+ }
+ } else if (m_surface->start(format)) {
+ m_surface->present(QVideoFrame(image));
+ }
+ }
+ }
+}
+
+bool QMediaImageViewerServicePrivate::load(QIODevice *device)
+{
+ QImageReader reader(device);
+
+ if (!reader.canRead()) {
+ m_image = QImage();
+ } else {
+ m_image = reader.read();
+ }
+
+ if (rendererControl)
+ rendererControl->showImage(m_image);
+
+ return !m_image.isNull();
+}
+
+void QMediaImageViewerServicePrivate::clear()
+{
+ m_image = QImage();
+
+ if (rendererControl)
+ rendererControl->showImage(m_image);
+}
+
+/*!
+ \class QMediaImageViewerService
+ \since 1.0
+ \internal
+*/
+
+/*!
+*/
+QMediaImageViewerService::QMediaImageViewerService(QObject *parent)
+ : QMediaService(*new QMediaImageViewerServicePrivate, parent)
+{
+ Q_D(QMediaImageViewerService);
+
+ d->viewerControl = new QMediaImageViewerControl(this);
+}
+
+/*!
+*/
+QMediaImageViewerService::~QMediaImageViewerService()
+{
+ Q_D(QMediaImageViewerService);
+
+ delete d->rendererControl;
+ delete d->viewerControl;
+}
+
+/*!
+*/
+QMediaControl *QMediaImageViewerService::requestControl(const char *name)
+{
+ Q_D(QMediaImageViewerService);
+
+ if (qstrcmp(name, QMediaImageViewerControl_iid) == 0) {
+ return d->viewerControl;
+ } else if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+ if (!d->rendererControl) {
+ d->rendererControl = new QMediaImageViewerRenderer;
+ d->rendererControl->showImage(d->m_image);
+
+ return d->rendererControl;
+ }
+ }
+ return 0;
+}
+
+void QMediaImageViewerService::releaseControl(QMediaControl *control)
+{
+ Q_D(QMediaImageViewerService);
+
+ if (!control) {
+ qWarning("QMediaService::releaseControl():"
+ " Attempted release of null control");
+ } else if (control == d->rendererControl) {
+ delete d->rendererControl;
+
+ d->rendererControl = 0;
+ }
+}
+
+/*!
+*/
+QNetworkAccessManager *QMediaImageViewerService::networkManager() const
+{
+ Q_D(const QMediaImageViewerService);
+
+ if (!d->network) {
+ QMediaImageViewerServicePrivate *_d = const_cast<QMediaImageViewerServicePrivate *>(d);
+
+ if (!_d->internalNetwork)
+ _d->internalNetwork = new QNetworkAccessManager(
+ const_cast<QMediaImageViewerService *>(this));
+
+ _d->network = d->internalNetwork;
+ }
+
+ return d->network;
+}
+
+
+void QMediaImageViewerService::setNetworkManager(QNetworkAccessManager *manager)
+{
+ d_func()->network = manager;
+}
+
+class QMediaImageViewerControlPrivate : public QMediaControlPrivate
+{
+ Q_DECLARE_NON_CONST_PUBLIC(QMediaImageViewerControl)
+public:
+ QMediaImageViewerControlPrivate()
+ : service(0)
+ , getReply(0)
+ , headReply(0)
+ , status(QMediaImageViewer::NoMedia)
+ {
+ foreach (const QByteArray &format, QImageReader::supportedImageFormats()) {
+ supportedExtensions.append(
+ QLatin1Char('.') + QString::fromLatin1(format.data(), format.size()));
+ }
+ }
+
+ bool isImageType(const QUrl &url, const QString &mimeType) const;
+
+ void loadImage();
+ void cancelRequests();
+
+ void _q_getFinished();
+ void _q_headFinished();
+
+ QMediaImageViewerService *service;
+ QNetworkReply *getReply;
+ QNetworkReply *headReply;
+ QMediaImageViewer::MediaStatus status;
+ QMediaContent media;
+ QMediaResource currentMedia;
+ QList<QMediaResource> possibleResources;
+ QStringList supportedExtensions;
+};
+
+bool QMediaImageViewerControlPrivate::isImageType(const QUrl &url, const QString &mimeType) const
+{
+ if (!mimeType.isEmpty()) {
+ return mimeType.startsWith(QLatin1String("image/"))
+ || mimeType == QLatin1String("application/xml+svg");
+ } else if (url.scheme() == QLatin1String("file")) {
+ QString path = url.path();
+
+ foreach (const QString &extension, supportedExtensions) {
+ if (path.endsWith(extension, Qt::CaseInsensitive))
+ return true;
+ }
+ }
+ return false;
+}
+
+void QMediaImageViewerControlPrivate::loadImage()
+{
+ cancelRequests();
+
+ QMediaImageViewer::MediaStatus currentStatus = status;
+ status = QMediaImageViewer::InvalidMedia;
+
+ QNetworkAccessManager *network = service->networkManager();
+
+ while (!possibleResources.isEmpty() && !headReply && !getReply) {
+ currentMedia = possibleResources.takeFirst();
+
+ QUrl url = currentMedia.url();
+ QString mimeType = currentMedia.mimeType();
+
+ if (isImageType(url, mimeType)) {
+ getReply = network->get(QNetworkRequest(url));
+ QObject::connect(getReply, SIGNAL(finished()), q_func(), SLOT(_q_getFinished()));
+
+ status = QMediaImageViewer::LoadingMedia;
+ } else if (mimeType.isEmpty() && url.scheme() != QLatin1String("file")) {
+ headReply = network->head(QNetworkRequest(currentMedia.url()));
+ QObject::connect(headReply, SIGNAL(finished()), q_func(), SLOT(_q_headFinished()));
+
+ status = QMediaImageViewer::LoadingMedia;
+ }
+ }
+
+ if (status == QMediaImageViewer::InvalidMedia)
+ currentMedia = QMediaResource();
+
+ if (status != currentStatus)
+ emit q_func()->mediaStatusChanged(status);
+}
+
+void QMediaImageViewerControlPrivate::cancelRequests()
+{
+ if (getReply) {
+ getReply->abort();
+ getReply->deleteLater();
+ getReply = 0;
+ }
+
+ if (headReply) {
+ headReply->abort();
+ headReply->deleteLater();
+ headReply = 0;
+ }
+}
+
+void QMediaImageViewerControlPrivate::_q_getFinished()
+{
+ if (getReply != q_func()->sender())
+ return;
+
+ QImage image;
+
+ if (service->d_func()->load(getReply)) {
+ possibleResources.clear();
+
+ status = QMediaImageViewer::LoadedMedia;
+
+ emit q_func()->mediaStatusChanged(status);
+ } else {
+ loadImage();
+ }
+}
+
+void QMediaImageViewerControlPrivate::_q_headFinished()
+{
+ if (headReply != q_func()->sender())
+ return;
+
+ QString mimeType = headReply->header(QNetworkRequest::ContentTypeHeader)
+ .toString().section(QLatin1Char(';'), 0, 0);
+ QUrl url = headReply->url();
+ if (url.isEmpty())
+ url = headReply->request().url();
+
+ headReply->deleteLater();
+ headReply = 0;
+
+ if (isImageType(url, mimeType) || mimeType.isEmpty()) {
+ QNetworkAccessManager *network = service->networkManager();
+
+ getReply = network->get(QNetworkRequest(url));
+
+ QObject::connect(getReply, SIGNAL(finished()), q_func(), SLOT(_q_getFinished()));
+ } else {
+ loadImage();
+ }
+}
+
+/*!
+ \class QMediaImageViewerControl
+ \internal
+ \since 1.1
+*/
+QMediaImageViewerControl::QMediaImageViewerControl(QMediaImageViewerService *parent)
+ : QMediaControl(*new QMediaImageViewerControlPrivate, parent)
+{
+ Q_D(QMediaImageViewerControl);
+
+ d->service = parent;
+}
+
+/*!
+*/
+QMediaImageViewerControl::~QMediaImageViewerControl()
+{
+ Q_D(QMediaImageViewerControl);
+
+ delete d->getReply;
+}
+
+/*!
+ \since 1.1
+*/
+QMediaImageViewer::MediaStatus QMediaImageViewerControl::mediaStatus() const
+{
+ return d_func()->status;
+}
+
+/*!
+ \fn QMediaImageViewerControl::mediaStatusChanged(QMediaImageViewer::MediaStatus status);
+ \since 1.1
+*/
+
+/*!
+ \since 1.1
+*/
+void QMediaImageViewerControl::showMedia(const QMediaContent &media)
+{
+ Q_D(QMediaImageViewerControl);
+
+ d->media = media;
+ d->currentMedia = QMediaResource();
+ d->cancelRequests();
+
+ if (media.isNull()) {
+ d->service->d_func()->clear();
+ if (d->status != QMediaImageViewer::NoMedia) {
+ d->status = QMediaImageViewer::NoMedia;
+ emit mediaStatusChanged(d->status);
+ }
+ } else {
+ d->possibleResources = media.resources();
+ d->loadImage();
+ }
+}
+
+
+#include "moc_qmediaimageviewerservice_p.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaimageviewerservice_p.h b/src/multimediakit/qmediaimageviewerservice_p.h
new file mode 100644
index 000000000..5d4811da9
--- /dev/null
+++ b/src/multimediakit/qmediaimageviewerservice_p.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QMEDIASLIDESHOWSERVICE_P_H
+#define QMEDIASLIDESHOWSERVICE_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 <qmediaservice.h>
+#include <qmediaimageviewer.h>
+#include <qvideorenderercontrol.h>
+#include <qvideowidget.h>
+#include <qvideowidgetcontrol.h>
+
+#include <QtCore/qpointer.h>
+#include <QtGui/qimage.h>
+
+QT_BEGIN_NAMESPACE
+class QAbstractVideoSurface;
+class QNetworkAccessManager;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class QMediaImageViewerServicePrivate;
+
+class Q_AUTOTEST_EXPORT QMediaImageViewerService : public QMediaService
+{
+ Q_OBJECT
+public:
+ explicit QMediaImageViewerService(QObject *parent = 0);
+ ~QMediaImageViewerService();
+
+ QMediaControl *requestControl(const char *name);
+ void releaseControl(QMediaControl *);
+
+ QNetworkAccessManager *networkManager() const;
+ void setNetworkManager(QNetworkAccessManager *manager);
+
+private:
+ Q_DECLARE_PRIVATE(QMediaImageViewerService)
+ friend class QMediaImageViewerControl;
+ friend class QMediaImageViewerControlPrivate;
+};
+
+class QMediaImageViewerControlPrivate;
+
+class QMediaImageViewerControl : public QMediaControl
+{
+ Q_OBJECT
+public:
+ explicit QMediaImageViewerControl(QMediaImageViewerService *parent);
+ ~QMediaImageViewerControl();
+
+ QMediaImageViewer::MediaStatus mediaStatus() const;
+
+ void showMedia(const QMediaContent &media);
+
+Q_SIGNALS:
+ void mediaStatusChanged(QMediaImageViewer::MediaStatus status);
+
+private:
+ Q_DECLARE_PRIVATE(QMediaImageViewerControl)
+ Q_PRIVATE_SLOT(d_func(), void _q_headFinished())
+ Q_PRIVATE_SLOT(d_func(), void _q_getFinished())
+};
+
+#define QMediaImageViewerControl_iid "com.nokia.Qt.QMediaImageViewerControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QMediaImageViewerControl, QMediaImageViewerControl_iid)
+
+class QMediaImageViewerRenderer : public QVideoRendererControl
+{
+ Q_OBJECT
+public:
+ QMediaImageViewerRenderer(QObject *parent = 0);
+ ~QMediaImageViewerRenderer();
+
+ QAbstractVideoSurface *surface() const;
+ void setSurface(QAbstractVideoSurface *surface);
+
+ void showImage(const QImage &image);
+
+Q_SIGNALS:
+ void surfaceChanged(QAbstractVideoSurface *surface);
+
+private:
+ QPointer<QAbstractVideoSurface> m_surface;
+ QImage m_image;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qmedianetworkaccesscontrol.cpp b/src/multimediakit/qmedianetworkaccesscontrol.cpp
new file mode 100644
index 000000000..e5bdc840f
--- /dev/null
+++ b/src/multimediakit/qmedianetworkaccesscontrol.cpp
@@ -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 "qmedianetworkaccesscontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMediaNetworkAccessControl
+ \preliminary
+ \brief The QMediaNetworkAccessControl class allows the setting of the Network Access Point for media related activities.
+ \ingroup multimedia
+ \inmodule QtMultimediaKit
+ \since 1.2
+
+ The functionality provided by this control allows the
+ setting of a Network Access Point.
+
+ This control can be used to set a network access for various
+ network related activities. the exact nature in dependant on the underlying
+ usage by the supported QMediaObject
+*/
+
+QMediaNetworkAccessControl::QMediaNetworkAccessControl(QObject *parent) :
+ QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys a network access control.
+*/
+QMediaNetworkAccessControl::~QMediaNetworkAccessControl()
+{
+}
+
+/*!
+ \fn void QMediaNetworkAccessControl::setConfigurations(const QList<QNetworkConfiguration> &configurations);
+
+ \a configurations contains a list of network configurations to be used for network access.
+
+ It is assumed the list is given in highest to lowest preference order.
+ By calling this function all previous configurations will be invalidated
+ and replaced with the new list.
+ \since 1.2
+*/
+
+/*
+ \fn QNetworkConfiguration QMediaNetworkAccessControl::currentConfiguration() const
+
+ Returns the current active configuration in use.
+ A default constructed QNetworkConfigration is returned if no user supplied configuration are in use.
+*/
+
+
+/*!
+ \fn QMediaNetworkAccessControl::configurationChanged(const QNetworkConfiguration &configuration)
+ This signal is emitted when the current active network configuration changes
+ to \a configuration.
+ \since 1.2
+*/
+
+
+
+#include "moc_qmedianetworkaccesscontrol.cpp"
+QT_END_NAMESPACE
diff --git a/src/multimediakit/qmedianetworkaccesscontrol.h b/src/multimediakit/qmedianetworkaccesscontrol.h
new file mode 100644
index 000000000..65d693bb9
--- /dev/null
+++ b/src/multimediakit/qmedianetworkaccesscontrol.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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 QMEDIANETWORKACCESSCONTROL_H
+#define QMEDIANETWORKACCESSCONTROL_H
+
+#include "qmediacontrol.h"
+
+#include <QtCore/qlist.h>
+#include <QtNetwork/qnetworkconfiguration.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QMediaNetworkAccessControl : public QMediaControl
+{
+ Q_OBJECT
+public:
+
+ virtual ~QMediaNetworkAccessControl();
+
+ virtual void setConfigurations(const QList<QNetworkConfiguration> &configuration) = 0;
+ virtual QNetworkConfiguration currentConfiguration() const = 0;
+
+Q_SIGNALS:
+ void configurationChanged(const QNetworkConfiguration& configuration);
+
+protected:
+ QMediaNetworkAccessControl(QObject *parent = 0);
+};
+
+#define QMediaNetworkAccessControl_iid "com.nokia.Qt.QMediaNetworkAccessControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QMediaNetworkAccessControl, QMediaNetworkAccessControl_iid)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qmediaobject.cpp b/src/multimediakit/qmediaobject.cpp
new file mode 100644
index 000000000..a3c9007c5
--- /dev/null
+++ b/src/multimediakit/qmediaobject.cpp
@@ -0,0 +1,427 @@
+/****************************************************************************
+**
+** 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/qmetaobject.h>
+#include <QtCore/qdebug.h>
+
+#include "qmediaobject_p.h"
+
+#include <qmediaservice.h>
+#include <qmetadatareadercontrol.h>
+#include <qmediabindableinterface.h>
+
+
+QT_BEGIN_NAMESPACE
+
+void QMediaObjectPrivate::_q_notify()
+{
+ Q_Q(QMediaObject);
+
+ const QMetaObject* m = q->metaObject();
+
+ foreach (int pi, notifyProperties) {
+ QMetaProperty p = m->property(pi);
+ p.notifySignal().invoke(
+ q, QGenericArgument(QMetaType::typeName(p.userType()), p.read(q).data()));
+ }
+}
+
+
+/*!
+ \class QMediaObject
+
+ \brief The QMediaObject class provides a common base for multimedia objects.
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ XXX why do I care
+
+ QMediaObject derived classes provide access to the functionality of a
+ QMediaService. Each media object hosts a QMediaService and uses the
+ QMediaControl interfaces implemented by the service to implement its
+ API. Most media objects when constructed will request a new
+ QMediaService instance from a QMediaServiceProvider, but some like
+ QMediaRecorder will share a service with another object.
+
+ QMediaObject itself provides an API for accessing a media
+ service's \l {metaData()}{meta-data} and a means of connecting other media objects,
+ and peripheral classes like QVideoWidget and QMediaPlaylist.
+
+ \sa QMediaService, QMediaControl
+*/
+
+/*!
+ Destroys this media object.
+*/
+
+QMediaObject::~QMediaObject()
+{
+ delete d_ptr;
+}
+
+/*!
+ Returns the service availability error state.
+ \since 1.0
+*/
+
+QtMultimediaKit::AvailabilityError QMediaObject::availabilityError() const
+{
+ return d_func()->service == 0 ? QtMultimediaKit::ServiceMissingError : QtMultimediaKit::NoError;
+}
+
+/*!
+ Returns true if the service is available for use.
+ \since 1.0
+*/
+
+bool QMediaObject::isAvailable() const
+{
+ return d_func()->service != 0;
+}
+
+/*!
+ Returns the media service that provides the functionality of this multimedia object.
+ \since 1.0
+*/
+
+QMediaService* QMediaObject::service() const
+{
+ return d_func()->service;
+}
+
+int QMediaObject::notifyInterval() const
+{
+ return d_func()->notifyTimer->interval();
+}
+
+void QMediaObject::setNotifyInterval(int milliSeconds)
+{
+ Q_D(QMediaObject);
+
+ if (d->notifyTimer->interval() != milliSeconds) {
+ d->notifyTimer->setInterval(milliSeconds);
+
+ emit notifyIntervalChanged(milliSeconds);
+ }
+}
+
+/*!
+ Bind \a object to this QMediaObject instance.
+
+ This method establishes a relationship between this media object and a
+ helper object. The nature of the relationship depends on both parties. This
+ methods returns true if the helper was successfully bound, false otherwise.
+
+ Most subclasses of QMediaObject provide more convenient functions
+ that wrap this functionality, so this function rarely needs to be
+ called directly.
+
+ XXX for example
+
+ The object passed must implement the QMediaBindableInterface interface.
+
+ \since 1.0
+ \sa QMediaBindableInterface
+*/
+bool QMediaObject::bind(QObject *object)
+{
+ QMediaBindableInterface *helper = qobject_cast<QMediaBindableInterface*>(object);
+ if (!helper)
+ return false;
+
+ QMediaObject *currentObject = helper->mediaObject();
+
+ if (currentObject == this)
+ return true;
+
+ if (currentObject)
+ currentObject->unbind(object);
+
+ return helper->setMediaObject(this);
+}
+
+/*!
+ Detach \a object from the QMediaObject instance.
+
+ Unbind the helper object from this media object. A warning
+ will be generated if the object was not previously bound to this
+ object.
+
+ \since 1.0
+ \sa QMediaBindableInterface
+*/
+void QMediaObject::unbind(QObject *object)
+{
+ QMediaBindableInterface *helper = qobject_cast<QMediaBindableInterface*>(object);
+
+ if (helper && helper->mediaObject() == this)
+ helper->setMediaObject(0);
+ else
+ qWarning() << "QMediaObject: Trying to unbind not connected helper object";
+}
+
+/*!
+ Constructs a media object which uses the functionality provided by a media \a service.
+
+ The \a parent is passed to QObject.
+
+ This class is meant as a base class for multimedia objects so this
+ constructor is protected.
+ \since 1.0
+*/
+
+QMediaObject::QMediaObject(QObject *parent, QMediaService *service):
+ QObject(parent),
+ d_ptr(new QMediaObjectPrivate)
+
+{
+ Q_D(QMediaObject);
+
+ d->q_ptr = this;
+
+ d->notifyTimer = new QTimer(this);
+ d->notifyTimer->setInterval(1000);
+ connect(d->notifyTimer, SIGNAL(timeout()), SLOT(_q_notify()));
+
+ d->service = service;
+
+ setupMetaData();
+}
+
+/*!
+ \internal
+*/
+
+QMediaObject::QMediaObject(QMediaObjectPrivate &dd, QObject *parent,
+ QMediaService *service):
+ QObject(parent),
+ d_ptr(&dd)
+{
+ Q_D(QMediaObject);
+ d->q_ptr = this;
+
+ d->notifyTimer = new QTimer(this);
+ d->notifyTimer->setInterval(1000);
+ connect(d->notifyTimer, SIGNAL(timeout()), SLOT(_q_notify()));
+
+ d->service = service;
+
+ setupMetaData();
+}
+
+/*!
+ Watch the property \a name. The property's notify signal will be emitted
+ once every \code notifyInterval milliseconds.
+
+ \since 1.0
+ \sa notifyInterval
+*/
+
+void QMediaObject::addPropertyWatch(QByteArray const &name)
+{
+ Q_D(QMediaObject);
+
+ const QMetaObject* m = metaObject();
+
+ int index = m->indexOfProperty(name.constData());
+
+ if (index != -1 && m->property(index).hasNotifySignal()) {
+ d->notifyProperties.insert(index);
+
+ if (!d->notifyTimer->isActive())
+ d->notifyTimer->start();
+ }
+}
+
+/*!
+ Remove property \a name from the list of properties whose changes are
+ regularly signaled.
+
+ \since 1.0
+ \sa notifyInterval
+*/
+
+void QMediaObject::removePropertyWatch(QByteArray const &name)
+{
+ Q_D(QMediaObject);
+
+ int index = metaObject()->indexOfProperty(name.constData());
+
+ if (index != -1) {
+ d->notifyProperties.remove(index);
+
+ if (d->notifyProperties.isEmpty())
+ d->notifyTimer->stop();
+ }
+}
+
+/*!
+ \property QMediaObject::notifyInterval
+
+ The interval at which notifiable properties will update.
+
+ The interval is expressed in milliseconds, the default value is 1000.
+
+ \since 1.0
+ \sa addPropertyWatch(), removePropertyWatch()
+*/
+
+/*!
+ \fn void QMediaObject::notifyIntervalChanged(int milliseconds)
+
+ Signal a change in the notify interval period to \a milliseconds.
+ \since 1.0
+*/
+
+/*!
+ Returns true if there is meta-data associated with this media object, else false.
+ \since 1.0
+*/
+
+bool QMediaObject::isMetaDataAvailable() const
+{
+ Q_D(const QMediaObject);
+
+ return d->metaDataControl
+ ? d->metaDataControl->isMetaDataAvailable()
+ : false;
+}
+
+/*!
+ \fn QMediaObject::metaDataAvailableChanged(bool available)
+
+ Signals that the \a available state of a media object's meta-data has changed.
+ \since 1.0
+*/
+
+/*!
+ Returns the value associated with a meta-data \a key.
+ \since 1.0
+*/
+QVariant QMediaObject::metaData(QtMultimediaKit::MetaData key) const
+{
+ Q_D(const QMediaObject);
+
+ return d->metaDataControl
+ ? d->metaDataControl->metaData(key)
+ : QVariant();
+}
+
+/*!
+ Returns a list of keys there is meta-data available for.
+ \since 1.0
+*/
+QList<QtMultimediaKit::MetaData> QMediaObject::availableMetaData() const
+{
+ Q_D(const QMediaObject);
+
+ return d->metaDataControl
+ ? d->metaDataControl->availableMetaData()
+ : QList<QtMultimediaKit::MetaData>();
+}
+
+/*!
+ \fn QMediaObject::metaDataChanged()
+
+ Signals that this media object's meta-data has changed.
+ \since 1.0
+*/
+
+/*!
+ Returns the value associated with a meta-data \a key.
+
+ The naming and type of extended meta-data is not standardized, so the values and meaning
+ of keys may vary between backends.
+ \since 1.0
+*/
+QVariant QMediaObject::extendedMetaData(const QString &key) const
+{
+ Q_D(const QMediaObject);
+
+ return d->metaDataControl
+ ? d->metaDataControl->extendedMetaData(key)
+ : QVariant();
+}
+
+/*!
+ Returns a list of keys there is extended meta-data available for.
+ \since 1.0
+*/
+QStringList QMediaObject::availableExtendedMetaData() const
+{
+ Q_D(const QMediaObject);
+
+ return d->metaDataControl
+ ? d->metaDataControl->availableExtendedMetaData()
+ : QStringList();
+}
+
+
+void QMediaObject::setupMetaData()
+{
+ Q_D(QMediaObject);
+
+ if (d->service != 0) {
+ d->metaDataControl = qobject_cast<QMetaDataReaderControl*>(
+ d->service->requestControl(QMetaDataReaderControl_iid));
+
+ if (d->metaDataControl) {
+ connect(d->metaDataControl, SIGNAL(metaDataChanged()), SIGNAL(metaDataChanged()));
+ connect(d->metaDataControl,
+ SIGNAL(metaDataAvailableChanged(bool)),
+ SIGNAL(metaDataAvailableChanged(bool)));
+ }
+ }
+}
+
+/*!
+ \fn QMediaObject::availabilityChanged(bool available)
+
+ Signal emitted when the availability state has changed to \a available
+ \since 1.0
+*/
+
+
+#include "moc_qmediaobject.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaobject.h b/src/multimediakit/qmediaobject.h
new file mode 100644
index 000000000..604544b6b
--- /dev/null
+++ b/src/multimediakit/qmediaobject.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** 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 QABSTRACTMEDIAOBJECT_H
+#define QABSTRACTMEDIAOBJECT_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstringlist.h>
+
+#include <qmobilityglobal.h>
+#include "qtmedianamespace.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMediaService;
+class QMediaBindableInterface;
+
+class QMediaObjectPrivate;
+class Q_MULTIMEDIA_EXPORT QMediaObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int notifyInterval READ notifyInterval WRITE setNotifyInterval NOTIFY notifyIntervalChanged)
+public:
+ ~QMediaObject();
+
+ virtual bool isAvailable() const;
+ virtual QtMultimediaKit::AvailabilityError availabilityError() const;
+
+ virtual QMediaService* service() const;
+
+ int notifyInterval() const;
+ void setNotifyInterval(int milliSeconds);
+
+ virtual bool bind(QObject *);
+ virtual void unbind(QObject *);
+
+ bool isMetaDataAvailable() const;
+
+ QVariant metaData(QtMultimediaKit::MetaData key) const;
+ QList<QtMultimediaKit::MetaData> availableMetaData() const;
+
+ QVariant extendedMetaData(const QString &key) const;
+ QStringList availableExtendedMetaData() const;
+
+Q_SIGNALS:
+ void notifyIntervalChanged(int milliSeconds);
+
+ void metaDataAvailableChanged(bool available);
+ void metaDataChanged();
+
+ void availabilityChanged(bool available);
+
+protected:
+ QMediaObject(QObject *parent, QMediaService *service);
+ QMediaObject(QMediaObjectPrivate &dd, QObject *parent, QMediaService *service);
+
+ void addPropertyWatch(QByteArray const &name);
+ void removePropertyWatch(QByteArray const &name);
+
+ QMediaObjectPrivate *d_ptr;
+
+private:
+ void setupMetaData();
+
+ Q_DECLARE_PRIVATE(QMediaObject)
+ Q_PRIVATE_SLOT(d_func(), void _q_notify())
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QABSTRACTMEDIAOBJECT_H
diff --git a/src/multimediakit/qmediaobject_p.h b/src/multimediakit/qmediaobject_p.h
new file mode 100644
index 000000000..a0d307227
--- /dev/null
+++ b/src/multimediakit/qmediaobject_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QABSTRACTMEDIAOBJECT_P_H
+#define QABSTRACTMEDIAOBJECT_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/qbytearray.h>
+#include <QtCore/qset.h>
+#include <QtCore/qtimer.h>
+
+#include "qmediaobject.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMetaDataReaderControl;
+
+#define Q_DECLARE_NON_CONST_PUBLIC(Class) \
+ inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
+ friend class Class;
+
+
+class QMediaObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QMediaObject)
+
+public:
+ QMediaObjectPrivate():metaDataControl(0), notifyTimer(0) {}
+ virtual ~QMediaObjectPrivate() {}
+
+ void _q_notify();
+
+ QMediaService *service;
+ QMetaDataReaderControl *metaDataControl;
+ QTimer* notifyTimer;
+ QSet<int> notifyProperties;
+
+ QMediaObject *q_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qmediaplayer.cpp b/src/multimediakit/qmediaplayer.cpp
new file mode 100644
index 000000000..be3825861
--- /dev/null
+++ b/src/multimediakit/qmediaplayer.cpp
@@ -0,0 +1,1134 @@
+/****************************************************************************
+**
+** 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/qcoreevent.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qpointer.h>
+
+
+#include "qmediaplayer.h"
+
+#include <qmediaobject_p.h>
+#include <qmediaservice.h>
+#include <qmediaplayercontrol.h>
+#include <qmediaserviceprovider.h>
+#include <qmediaplaylist.h>
+#include <qmediaplaylistcontrol.h>
+#include <qmediaplaylistsourcecontrol.h>
+#include <qvideowidget.h>
+#include <qvideosurfaceoutput_p.h>
+#include <qgraphicsvideoitem.h>
+#include <qmedianetworkaccesscontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMediaPlayer
+ \brief The QMediaPlayer class allows the playing of a media source.
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+
+
+ The QMediaPlayer class is a high level media playback class. It can be used
+ to playback such content as songs, movies and internet radio. The content
+ to playback is specified as a QMediaContent, which can be thought of as a
+ main or canonical URL with addition information attached. When provided
+ with a QMediaContent playback may be able to commence.
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Player
+
+ QVideoWidget can be used with QMediaPlayer for video rendering and QMediaPlaylist
+ for accessing playlist functionality.
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Movie playlist
+
+ \sa QMediaObject, QMediaService, QVideoWidget, QMediaPlaylist
+*/
+
+namespace
+{
+class MediaPlayerRegisterMetaTypes
+{
+public:
+ MediaPlayerRegisterMetaTypes()
+ {
+ qRegisterMetaType<QMediaPlayer::State>("QMediaPlayer::State");
+ qRegisterMetaType<QMediaPlayer::MediaStatus>("QMediaPlayer::MediaStatus");
+ qRegisterMetaType<QMediaPlayer::Error>("QMediaPlayer::Error");
+ }
+} _registerPlayerMetaTypes;
+}
+
+class QMediaPlayerPrivate : public QMediaObjectPrivate
+{
+ Q_DECLARE_NON_CONST_PUBLIC(QMediaPlayer)
+
+public:
+ QMediaPlayerPrivate()
+ : provider(0)
+ , control(0)
+ , playlistSourceControl(0)
+ , state(QMediaPlayer::StoppedState)
+ , error(QMediaPlayer::NoError)
+ , filterStates(false)
+ , playlist(0)
+ {}
+
+ QMediaServiceProvider *provider;
+ QMediaPlayerControl* control;
+ QMediaPlaylistSourceControl* playlistSourceControl;
+ QMediaPlayer::State state;
+ QMediaPlayer::Error error;
+ QString errorString;
+ bool filterStates;
+
+ QPointer<QObject> videoOutput;
+ QMediaPlaylist *playlist;
+ QMediaNetworkAccessControl *networkAccessControl;
+ QVideoSurfaceOutput surfaceOutput;
+
+ void _q_stateChanged(QMediaPlayer::State state);
+ void _q_mediaStatusChanged(QMediaPlayer::MediaStatus status);
+ void _q_error(int error, const QString &errorString);
+ void _q_updateMedia(const QMediaContent&);
+ void _q_playlistDestroyed();
+};
+
+void QMediaPlayerPrivate::_q_stateChanged(QMediaPlayer::State ps)
+{
+ Q_Q(QMediaPlayer);
+
+ if (filterStates)
+ return;
+
+ if (playlist
+ && ps != state && ps == QMediaPlayer::StoppedState
+ && (control->mediaStatus() == QMediaPlayer::EndOfMedia ||
+ control->mediaStatus() == QMediaPlayer::InvalidMedia)) {
+ playlist->next();
+ ps = control->state();
+ }
+
+ if (ps != state) {
+ state = ps;
+
+ if (ps == QMediaPlayer::PlayingState)
+ q->addPropertyWatch("position");
+ else
+ q->removePropertyWatch("position");
+
+ emit q->stateChanged(ps);
+ }
+}
+
+void QMediaPlayerPrivate::_q_mediaStatusChanged(QMediaPlayer::MediaStatus status)
+{
+ Q_Q(QMediaPlayer);
+
+ switch (status) {
+ case QMediaPlayer::StalledMedia:
+ case QMediaPlayer::BufferingMedia:
+ q->addPropertyWatch("bufferStatus");
+ emit q->mediaStatusChanged(status);
+ break;
+ default:
+ q->removePropertyWatch("bufferStatus");
+ emit q->mediaStatusChanged(status);
+ break;
+ }
+
+}
+
+void QMediaPlayerPrivate::_q_error(int error, const QString &errorString)
+{
+ Q_Q(QMediaPlayer);
+
+ this->error = QMediaPlayer::Error(error);
+ this->errorString = errorString;
+
+ emit q->error(this->error);
+}
+
+void QMediaPlayerPrivate::_q_updateMedia(const QMediaContent &media)
+{
+ Q_Q(QMediaPlayer);
+
+ if (!control)
+ return;
+
+ const QMediaPlayer::State currentState = state;
+
+ filterStates = true;
+ control->setMedia(media, 0);
+
+ if (!media.isNull()) {
+ switch (currentState) {
+ case QMediaPlayer::PlayingState:
+ control->play();
+ break;
+ case QMediaPlayer::PausedState:
+ control->pause();
+ break;
+ default:
+ break;
+ }
+ }
+ filterStates = false;
+
+ state = control->state();
+
+ if (state != currentState) {
+ if (state == QMediaPlayer::PlayingState)
+ q->addPropertyWatch("position");
+ else
+ q->removePropertyWatch("position");
+
+ emit q->stateChanged(state);
+ }
+}
+
+void QMediaPlayerPrivate::_q_playlistDestroyed()
+{
+ playlist = 0;
+
+ if (!control)
+ return;
+
+ if (playlistSourceControl)
+ playlistSourceControl->setPlaylist(0);
+
+ control->setMedia(QMediaContent(), 0);
+}
+
+static QMediaService *playerService(QMediaPlayer::Flags flags, QMediaServiceProvider *provider)
+{
+ if (flags) {
+ QMediaServiceProviderHint::Features features = 0;
+ if (flags & QMediaPlayer::LowLatency)
+ features |= QMediaServiceProviderHint::LowLatencyPlayback;
+
+ if (flags & QMediaPlayer::StreamPlayback)
+ features |= QMediaServiceProviderHint::StreamPlayback;
+
+ if (flags & QMediaPlayer::VideoSurface)
+ features |= QMediaServiceProviderHint::VideoSurface;
+
+ return provider->requestService(Q_MEDIASERVICE_MEDIAPLAYER,
+ QMediaServiceProviderHint(features));
+ } else
+ return provider->requestService(Q_MEDIASERVICE_MEDIAPLAYER);
+}
+
+
+/*!
+ Construct a QMediaPlayer that uses the playback service from \a provider,
+ parented to \a parent and with \a flags.
+
+ If a playback service is not specified the system default will be used.
+ \since 1.0
+*/
+
+QMediaPlayer::QMediaPlayer(QObject *parent, QMediaPlayer::Flags flags, QMediaServiceProvider *provider):
+ QMediaObject(*new QMediaPlayerPrivate,
+ parent,
+ playerService(flags,provider))
+{
+ Q_D(QMediaPlayer);
+
+ d->provider = provider;
+
+ if (d->service == 0) {
+ d->error = ServiceMissingError;
+ } else {
+ d->control = qobject_cast<QMediaPlayerControl*>(d->service->requestControl(QMediaPlayerControl_iid));
+ d->playlistSourceControl = qobject_cast<QMediaPlaylistSourceControl*>(d->service->requestControl(QMediaPlaylistSourceControl_iid));
+ d->networkAccessControl = qobject_cast<QMediaNetworkAccessControl*>(d->service->requestControl(QMediaNetworkAccessControl_iid));
+ if (d->control != 0) {
+ connect(d->control, SIGNAL(mediaChanged(QMediaContent)), SIGNAL(mediaChanged(QMediaContent)));
+ connect(d->control, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(_q_stateChanged(QMediaPlayer::State)));
+ connect(d->control, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
+ SLOT(_q_mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ connect(d->control, SIGNAL(error(int,QString)), SLOT(_q_error(int,QString)));
+
+ connect(d->control, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged(qint64)));
+ connect(d->control, SIGNAL(positionChanged(qint64)), SIGNAL(positionChanged(qint64)));
+ connect(d->control, SIGNAL(audioAvailableChanged(bool)), SIGNAL(audioAvailableChanged(bool)));
+ connect(d->control, SIGNAL(videoAvailableChanged(bool)), SIGNAL(videoAvailableChanged(bool)));
+ connect(d->control, SIGNAL(volumeChanged(int)), SIGNAL(volumeChanged(int)));
+ connect(d->control, SIGNAL(mutedChanged(bool)), SIGNAL(mutedChanged(bool)));
+ connect(d->control, SIGNAL(seekableChanged(bool)), SIGNAL(seekableChanged(bool)));
+ connect(d->control, SIGNAL(playbackRateChanged(qreal)), SIGNAL(playbackRateChanged(qreal)));
+ connect(d->control, SIGNAL(bufferStatusChanged(int)), SIGNAL(bufferStatusChanged(int)));
+
+ if (d->control->state() == PlayingState)
+ addPropertyWatch("position");
+
+ if (d->control->mediaStatus() == StalledMedia || d->control->mediaStatus() == BufferingMedia)
+ addPropertyWatch("bufferStatus");
+ }
+ if (d->networkAccessControl != 0) {
+ connect(d->networkAccessControl, SIGNAL(configurationChanged(QNetworkConfiguration)),
+ this, SIGNAL(networkConfigurationChanged(QNetworkConfiguration)));
+ }
+ }
+}
+
+
+/*!
+ Destroys the player object.
+*/
+
+QMediaPlayer::~QMediaPlayer()
+{
+ Q_D(QMediaPlayer);
+
+ if (d->service) {
+ if (d->control)
+ d->service->releaseControl(d->control);
+ }
+
+ d->provider->releaseService(d->service);
+}
+
+QMediaContent QMediaPlayer::media() const
+{
+ Q_D(const QMediaPlayer);
+
+ if (d->control != 0)
+ return d->control->media();
+
+ return QMediaContent();
+}
+
+/*!
+ Returns the stream source of media data.
+
+ This is only valid if a stream was passed to setMedia().
+
+ \since 1.0
+ \sa setMedia()
+*/
+
+const QIODevice *QMediaPlayer::mediaStream() const
+{
+ Q_D(const QMediaPlayer);
+
+ if (d->control != 0)
+ return d->control->mediaStream();
+
+ return 0;
+}
+
+QMediaPlaylist *QMediaPlayer::playlist() const
+{
+ return d_func()->playlistSourceControl ?
+ d_func()->playlistSourceControl->playlist() :
+ d_func()->playlist;
+}
+
+void QMediaPlayer::setPlaylist(QMediaPlaylist *playlist)
+{
+ Q_D(QMediaPlayer);
+
+ if (d->playlistSourceControl) {
+ if (d->playlistSourceControl->playlist())
+ disconnect(d->playlist, SIGNAL(destroyed()), this, SLOT(_q_playlistDestroyed()));
+
+ d->playlistSourceControl->setPlaylist(playlist);
+
+ if (playlist)
+ connect(d->playlist, SIGNAL(destroyed()), this, SLOT(_q_playlistDestroyed()));
+ } else {
+ if (d->playlist) {
+ disconnect(d->playlist, SIGNAL(currentMediaChanged(QMediaContent)),
+ this, SLOT(_q_updateMedia(QMediaContent)));
+ disconnect(d->playlist, SIGNAL(destroyed()), this, SLOT(_q_playlistDestroyed()));
+ }
+
+ d->playlist = playlist;
+
+ if (d->playlist) {
+ connect(d->playlist, SIGNAL(currentMediaChanged(QMediaContent)),
+ this, SLOT(_q_updateMedia(QMediaContent)));
+ connect(d->playlist, SIGNAL(destroyed()), this, SLOT(_q_playlistDestroyed()));
+
+ if (d->control != 0)
+ d->control->setMedia(playlist->currentMedia(), 0);
+ } else {
+ setMedia(QMediaContent(), 0);
+ }
+
+ }
+}
+
+/*!
+ Sets the network access points for remote media playback.
+ \a configurations contains, in ascending preferential order, a list of
+ configuration that can be used for network access.
+
+ This will invalidate the choice of previous configurations.
+ \since 1.2
+*/
+void QMediaPlayer::setNetworkConfigurations(const QList<QNetworkConfiguration> &configurations)
+{
+ Q_D(QMediaPlayer);
+
+ if (d->networkAccessControl)
+ d->networkAccessControl->setConfigurations(configurations);
+}
+
+QMediaPlayer::State QMediaPlayer::state() const
+{
+ return d_func()->state;
+}
+
+QMediaPlayer::MediaStatus QMediaPlayer::mediaStatus() const
+{
+ Q_D(const QMediaPlayer);
+
+ if (d->control != 0)
+ return d->control->mediaStatus();
+
+ return QMediaPlayer::UnknownMediaStatus;
+}
+
+qint64 QMediaPlayer::duration() const
+{
+ Q_D(const QMediaPlayer);
+
+ if (d->control != 0)
+ return d->control->duration();
+
+ return -1;
+}
+
+qint64 QMediaPlayer::position() const
+{
+ Q_D(const QMediaPlayer);
+
+ if (d->control != 0)
+ return d->control->position();
+
+ return 0;
+}
+
+int QMediaPlayer::volume() const
+{
+ Q_D(const QMediaPlayer);
+
+ if (d->control != 0)
+ return d->control->volume();
+
+ return 0;
+}
+
+bool QMediaPlayer::isMuted() const
+{
+ Q_D(const QMediaPlayer);
+
+ if (d->control != 0)
+ return d->control->isMuted();
+
+ return false;
+}
+
+int QMediaPlayer::bufferStatus() const
+{
+ Q_D(const QMediaPlayer);
+
+ if (d->control != 0)
+ return d->control->bufferStatus();
+
+ return 0;
+}
+
+bool QMediaPlayer::isAudioAvailable() const
+{
+ Q_D(const QMediaPlayer);
+
+ if (d->control != 0)
+ return d->control->isAudioAvailable();
+
+ return false;
+}
+
+bool QMediaPlayer::isVideoAvailable() const
+{
+ Q_D(const QMediaPlayer);
+
+ if (d->control != 0)
+ return d->control->isVideoAvailable();
+
+ return false;
+}
+
+bool QMediaPlayer::isSeekable() const
+{
+ Q_D(const QMediaPlayer);
+
+ if (d->control != 0)
+ return d->control->isSeekable();
+
+ return false;
+}
+
+qreal QMediaPlayer::playbackRate() const
+{
+ Q_D(const QMediaPlayer);
+
+ if (d->control != 0)
+ return d->control->playbackRate();
+
+ return 0.0;
+}
+
+/*!
+ Returns the current error state.
+ \since 1.0
+*/
+
+QMediaPlayer::Error QMediaPlayer::error() const
+{
+ return d_func()->error;
+}
+
+QString QMediaPlayer::errorString() const
+{
+ return d_func()->errorString;
+}
+
+/*!
+ Returns the current network access point in use.
+ If a default contructed QNetworkConfiguration is returned
+ this feature is not available or that none of the
+ current supplied configurations are in use.
+ \since 1.2
+*/
+QNetworkConfiguration QMediaPlayer::currentNetworkConfiguration() const
+{
+ Q_D(const QMediaPlayer);
+
+ if (d->networkAccessControl)
+ return d_func()->networkAccessControl->currentConfiguration();
+
+ return QNetworkConfiguration();
+}
+
+//public Q_SLOTS:
+/*!
+ Start or resume playing the current source.
+ \since 1.0
+*/
+
+void QMediaPlayer::play()
+{
+ Q_D(QMediaPlayer);
+
+ if (d->control == 0) {
+ QMetaObject::invokeMethod(this, "_q_error", Qt::QueuedConnection,
+ Q_ARG(int, QMediaPlayer::ServiceMissingError),
+ Q_ARG(QString, tr("The QMediaPlayer object does not have a valid service")));
+ return;
+ }
+
+ //if playlist control is available, the service should advance itself
+ if (d->playlist && d->playlist->currentIndex() == -1 && !d->playlist->isEmpty())
+ d->playlist->setCurrentIndex(0);
+
+ // Reset error conditions
+ d->error = NoError;
+ d->errorString = QString();
+
+ d->control->play();
+}
+
+/*!
+ Pause playing the current source.
+ \since 1.0
+*/
+
+void QMediaPlayer::pause()
+{
+ Q_D(QMediaPlayer);
+
+ if (d->control != 0)
+ d->control->pause();
+}
+
+/*!
+ Stop playing, and reset the play position to the beginning.
+ \since 1.0
+*/
+
+void QMediaPlayer::stop()
+{
+ Q_D(QMediaPlayer);
+
+ if (d->control != 0)
+ d->control->stop();
+}
+
+void QMediaPlayer::setPosition(qint64 position)
+{
+ Q_D(QMediaPlayer);
+
+ if (d->control == 0 || !isSeekable())
+ return;
+
+ d->control->setPosition(qBound(qint64(0), position, duration()));
+}
+
+void QMediaPlayer::setVolume(int v)
+{
+ Q_D(QMediaPlayer);
+
+ if (d->control == 0)
+ return;
+
+ int clamped = qBound(0, v, 100);
+ if (clamped == volume())
+ return;
+
+ d->control->setVolume(clamped);
+}
+
+void QMediaPlayer::setMuted(bool muted)
+{
+ Q_D(QMediaPlayer);
+
+ if (d->control == 0 || muted == isMuted())
+ return;
+
+ d->control->setMuted(muted);
+}
+
+void QMediaPlayer::setPlaybackRate(qreal rate)
+{
+ Q_D(QMediaPlayer);
+
+ if (d->control != 0)
+ d->control->setPlaybackRate(rate);
+}
+
+/*!
+ Sets the current \a media source.
+
+ If a \a stream is supplied; media data will be read from it instead of resolving the media
+ source. In this case the media source may still be used to resolve additional information
+ about the media such as mime type.
+
+ Setting the media to a null QMediaContent will cause the player to discard all
+ information relating to the current media source and to cease all I/O operations related
+ to that media.
+ \since 1.0
+*/
+
+void QMediaPlayer::setMedia(const QMediaContent &media, QIODevice *stream)
+{
+ Q_D(QMediaPlayer);
+
+ if (playlist() && playlist()->currentMedia() != media)
+ setPlaylist(0);
+
+ if (d->control != 0)
+ d_func()->control->setMedia(media, stream);
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+
+bool QMediaPlayer::bind(QObject *obj)
+{
+ return QMediaObject::bind(obj);
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+
+void QMediaPlayer::unbind(QObject *obj)
+{
+ QMediaObject::unbind(obj);
+}
+
+/*!
+ Returns the level of support a media player has for a \a mimeType and a set of \a codecs.
+
+ The \a flags argument allows additional requirements such as performance indicators to be
+ specified.
+ \since 1.0
+*/
+QtMultimediaKit::SupportEstimate QMediaPlayer::hasSupport(const QString &mimeType,
+ const QStringList& codecs,
+ Flags flags)
+{
+ return QMediaServiceProvider::defaultServiceProvider()->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER),
+ mimeType,
+ codecs,
+ flags);
+}
+
+/*!
+ \deprecated
+ Returns a list of MIME types supported by the media player.
+
+ The \a flags argument causes the resultant list to be restricted to MIME types which can be supported
+ given additional requirements, such as performance indicators.
+
+ This function may not return useful results on some platforms, and support for a specific file of a
+ given mime type is not guaranteed even if the mime type is in general supported. In addition, in some
+ cases this function will need to load all available media plugins and query them for their support, which
+ may take some time.
+ \since 1.0
+*/
+QStringList QMediaPlayer::supportedMimeTypes(Flags flags)
+{
+ return QMediaServiceProvider::defaultServiceProvider()->supportedMimeTypes(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER),
+ flags);
+}
+
+/*!
+ \fn void QMediaPlayer::setVideoOutput(QVideoWidget* output)
+
+ Attach a QVideoWidget video \a output to the media player.
+
+ If the media player has already video output attached,
+ it will be replaced with a new one.
+ \since 1.0
+*/
+void QMediaPlayer::setVideoOutput(QVideoWidget *output)
+{
+ Q_D(QMediaPlayer);
+
+ if (d->videoOutput)
+ unbind(d->videoOutput);
+
+ d->videoOutput = output && bind(output) ? output : 0;
+}
+
+/*!
+ \fn void QMediaPlayer::setVideoOutput(QGraphicsVideoItem* output)
+
+ Attach a QGraphicsVideoItem video \a output to the media player.
+
+ If the media player has already video output attached,
+ it will be replaced with a new one.
+ \since 1.0
+*/
+void QMediaPlayer::setVideoOutput(QGraphicsVideoItem *output)
+{
+ Q_D(QMediaPlayer);
+
+ if (d->videoOutput)
+ unbind(d->videoOutput);
+
+ d->videoOutput = output && bind(output) ? output : 0;
+}
+
+/*!
+ Sets a video \a surface as the video output of a media player.
+
+ If a video output has already been set on the media player the new surface
+ will replace it.
+ \since 1.2
+*/
+
+void QMediaPlayer::setVideoOutput(QAbstractVideoSurface *surface)
+{
+ Q_D(QMediaPlayer);
+
+ d->surfaceOutput.setVideoSurface(surface);
+
+ if (d->videoOutput != &d->surfaceOutput) {
+ if (d->videoOutput)
+ unbind(d->videoOutput);
+
+ d->videoOutput = bind(&d->surfaceOutput) ? &d->surfaceOutput : 0;
+ }
+}
+
+// Enums
+/*!
+ \enum QMediaPlayer::State
+
+ Defines the current state of a media player.
+
+ \value PlayingState The media player is currently playing content.
+ \value PausedState The media player has paused playback, playback of the current track will
+ resume from the position the player was paused at.
+ \value StoppedState The media player is not playing content, playback will begin from the start
+ of the current track.
+*/
+
+/*!
+ \enum QMediaPlayer::MediaStatus
+
+ Defines the status of a media player's current media.
+
+ \value UnknownMediaStatus The status of the media cannot be determined.
+ \value NoMedia The is no current media. The player is in the StoppedState.
+ \value LoadingMedia The current media is being loaded. The player may be in any state.
+ \value LoadedMedia The current media has been loaded. The player is in the StoppedState.
+ \value StalledMedia Playback of the current media has stalled due to insufficient buffering or
+ some other temporary interruption. The player is in the PlayingState or PausedState.
+ \value BufferingMedia The player is buffering data but has enough data buffered for playback to
+ continue for the immediate future. The player is in the PlayingState or PausedState.
+ \value BufferedMedia The player has fully buffered the current media. The player is in the
+ PlayingState or PausedState.
+ \value EndOfMedia Playback has reached the end of the current media. The player is in the
+ StoppedState.
+ \value InvalidMedia The current media cannot be played. The player is in the StoppedState.
+*/
+
+/*!
+ \enum QMediaPlayer::Error
+
+ Defines a media player error condition.
+
+ \value NoError No error has occurred.
+ \value ResourceError A media resource couldn't be resolved.
+ \value FormatError The format of a media resource isn't (fully) supported. Playback may still
+ be possible, but without an audio or video component.
+ \value NetworkError A network error occurred.
+ \value AccessDeniedError There are not the appropriate permissions to play a media resource.
+ \value ServiceMissingError A valid playback service was not found, playback cannot proceed.
+*/
+
+// Signals
+/*!
+ \fn QMediaPlayer::error(QMediaPlayer::Error error)
+
+ Signals that an \a error condition has occurred.
+
+ \since 1.0
+ \sa errorString()
+*/
+
+/*!
+ \fn void QMediaPlayer::stateChanged(State state)
+
+ \since 1.0
+ Signal the \a state of the Player object has changed.
+*/
+
+/*!
+ \fn QMediaPlayer::mediaStatusChanged(QMediaPlayer::MediaStatus status)
+
+ Signals that the \a status of the current media has changed.
+
+ \since 1.0
+ \sa mediaStatus()
+*/
+
+/*!
+ \fn void QMediaPlayer::mediaChanged(const QMediaContent &media);
+
+ Signals that the current playing content will be obtained from \a media.
+
+ \since 1.0
+ \sa media()
+*/
+
+/*!
+ \fn void QMediaPlayer::playbackRateChanged(qreal rate);
+
+ Signals the playbackRate has changed to \a rate.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlayer::seekableChanged(bool seekable);
+
+ Signals the \a seekable status of the player object has changed.
+ \since 1.0
+*/
+
+// Properties
+/*!
+ \property QMediaPlayer::state
+ \brief the media player's playback state.
+
+ By default this property is QMediaPlayer::Stopped
+
+ \since 1.0
+ \sa mediaStatus(), play(), pause(), stop()
+*/
+
+/*!
+ \property QMediaPlayer::error
+ \brief a string describing the last error condition.
+
+ \since 1.0
+ \sa error()
+*/
+
+/*!
+ \property QMediaPlayer::media
+ \brief the active media source being used by the player object.
+
+ The player object will use the QMediaContent for selection of the content to
+ be played.
+
+ By default this property has a null QMediaContent.
+
+ Setting this property to a null QMediaContent will cause the player to discard all
+ information relating to the current media source and to cease all I/O operations related
+ to that media.
+
+ \since 1.0
+ \sa QMediaContent
+*/
+
+/*!
+ \property QMediaPlayer::playlist
+ \brief the media playlist being used by the player object.
+
+ The player object will use the current playlist item for selection of the content to
+ be played.
+
+ By default this property is set to null.
+
+ If the media playlist is used as a source, QMediaPlayer::media is updated with
+ a current playlist item. The current source should be selected with
+ QMediaPlaylist::setCurrentIndex(int) instead of QMediaPlayer::setMedia(),
+ otherwise the current playlist will be discarded.
+
+ \since 1.0
+ \sa QMediaContent
+*/
+
+
+/*!
+ \property QMediaPlayer::mediaStatus
+ \brief the status of the current media stream.
+
+ The stream status describes how the playback of the current stream is
+ progressing.
+
+ By default this property is QMediaPlayer::NoMedia
+
+ \since 1.0
+ \sa state
+*/
+
+/*!
+ \property QMediaPlayer::duration
+ \brief the duration of the current media.
+
+ The value is the total playback time in milliseconds of the current media.
+ The value may change across the life time of the QMediaPlayer object and
+ may not be available when initial playback begins, connect to the
+ durationChanged() signal to receive status notifications.
+ \since 1.0
+*/
+
+/*!
+ \property QMediaPlayer::position
+ \brief the playback position of the current media.
+
+ The value is the current playback position, expressed in milliseconds since
+ the beginning of the media. Periodically changes in the position will be
+ indicated with the signal positionChanged(), the interval between updates
+ can be set with QMediaObject's method setNotifyInterval().
+ \since 1.0
+*/
+
+/*!
+ \property QMediaPlayer::volume
+ \brief the current playback volume.
+
+ The playback volume is a linear in effect and the value can range from 0 -
+ 100, values outside this range will be clamped.
+ \since 1.0
+*/
+
+/*!
+ \property QMediaPlayer::muted
+ \brief the muted state of the current media.
+
+ The value will be true if the playback volume is muted; otherwise false.
+ \since 1.0
+*/
+
+/*!
+ \property QMediaPlayer::bufferStatus
+ \brief the percentage of the temporary buffer filled before playback begins.
+
+ When the player object is buffering; this property holds the percentage of
+ the temporary buffer that is filled. The buffer will need to reach 100%
+ filled before playback can resume, at which time the MediaStatus will be
+ BufferedMedia.
+
+ \since 1.0
+ \sa mediaStatus()
+*/
+
+/*!
+ \property QMediaPlayer::audioAvailable
+ \brief the audio availabilty status for the current media.
+
+ As the life time of QMediaPlayer can be longer than the playback of one
+ QMediaContent, this property may change over time, the
+ audioAvailableChanged signal can be used to monitor it's status.
+ \since 1.0
+*/
+
+/*!
+ \property QMediaPlayer::videoAvailable
+ \brief the video availability status for the current media.
+
+ If available, the QVideoWidget class can be used to view the video. As the
+ life time of QMediaPlayer can be longer than the playback of one
+ QMediaContent, this property may change over time, the
+ videoAvailableChanged signal can be used to monitor it's status.
+
+ \since 1.0
+ \sa QVideoWidget, QMediaContent
+*/
+
+/*!
+ \property QMediaPlayer::seekable
+ \brief the seek-able status of the current media
+
+ If seeking is supported this property will be true; false otherwise. The
+ status of this property may change across the life time of the QMediaPlayer
+ object, use the seekableChanged signal to monitor changes.
+ \since 1.0
+*/
+
+/*!
+ \property QMediaPlayer::playbackRate
+ \brief the playback rate of the current media.
+
+ This value is a multiplier applied to the media's standard play rate. By
+ default this value is 1.0, indicating that the media is playing at the
+ standard pace. Values higher than 1.0 will increase the rate of play.
+ Values less than zero can be set and indicate the media will rewind at the
+ multiplier of the standard pace.
+
+ Not all playback services support change of the playback rate. It is
+ framework defined as to the status and quality of audio and video
+ while fast forwarding or rewinding.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlayer::durationChanged(qint64 duration)
+
+ Signal the duration of the content has changed to \a duration, expressed in milliseconds.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlayer::positionChanged(qint64 position)
+
+ Signal the position of the content has changed to \a position, expressed in
+ milliseconds.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlayer::volumeChanged(int volume)
+
+ Signal the playback volume has changed to \a volume.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlayer::mutedChanged(bool muted)
+
+ Signal the mute state has changed to \a muted.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlayer::videoAvailableChanged(bool videoAvailable)
+
+ Signal the availability of visual content has changed to \a videoAvailable.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlayer::audioAvailableChanged(bool available)
+
+ Signals the availability of audio content has changed to \a available.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlayer::bufferStatusChanged(int percentFilled)
+
+ Signal the amount of the local buffer filled as a percentage by \a percentFilled.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlayer::networkConfigurationChanged(const QNetworkConfiguration &configuration)
+
+ Signal that the active in use network access point has been changed to \a configuration and all subsequent network access will use this \a configuration.
+ \since 1.2
+*/
+
+/*!
+ \enum QMediaPlayer::Flag
+
+ \value LowLatency The player is expected to be used with simple audio formats,
+ but playback should start without significant delay.
+ Such playback service can be used for beeps, ringtones, etc.
+
+ \value StreamPlayback The player is expected to play QIODevice based streams.
+ If passed to QMediaPlayer constructor, the service supporting
+ streams playback will be chosen.
+
+ \value VideoSurface The player is expected to be able to render to a
+ QAbstractVideoSurface \l {setVideoOutput()}{output}.
+*/
+
+#include "moc_qmediaplayer.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaplayer.h b/src/multimediakit/qmediaplayer.h
new file mode 100644
index 000000000..444edb9ef
--- /dev/null
+++ b/src/multimediakit/qmediaplayer.h
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** 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 QMEDIAPLAYER_H
+#define QMEDIAPLAYER_H
+
+
+#include "qmediaserviceprovider.h"
+#include "qmediaobject.h"
+#include "qmediacontent.h"
+#include "qmediaenumdebug.h"
+
+#include <QtNetwork/qnetworkconfiguration.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractVideoSurface;
+class QMediaPlaylist;
+class QVideoWidget;
+class QGraphicsVideoItem;
+
+class QMediaPlayerPrivate;
+class Q_MULTIMEDIA_EXPORT QMediaPlayer : public QMediaObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QMediaContent media READ media WRITE setMedia NOTIFY mediaChanged)
+ Q_PROPERTY(QMediaPlaylist * playlist READ playlist WRITE setPlaylist)
+ Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged)
+ Q_PROPERTY(qint64 position READ position WRITE setPosition NOTIFY positionChanged)
+ Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged)
+ Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
+ Q_PROPERTY(int bufferStatus READ bufferStatus NOTIFY bufferStatusChanged)
+ Q_PROPERTY(bool audioAvailable READ isAudioAvailable NOTIFY audioAvailableChanged)
+ Q_PROPERTY(bool videoAvailable READ isVideoAvailable NOTIFY videoAvailableChanged)
+ Q_PROPERTY(bool seekable READ isSeekable NOTIFY seekableChanged)
+ Q_PROPERTY(qreal playbackRate READ playbackRate WRITE setPlaybackRate NOTIFY playbackRateChanged)
+ Q_PROPERTY(State state READ state NOTIFY stateChanged)
+ Q_PROPERTY(MediaStatus mediaStatus READ mediaStatus NOTIFY mediaStatusChanged)
+ Q_PROPERTY(QString error READ errorString)
+ Q_ENUMS(State)
+ Q_ENUMS(MediaStatus)
+ Q_ENUMS(Error)
+
+public:
+ enum State
+ {
+ StoppedState,
+ PlayingState,
+ PausedState
+ };
+
+ enum MediaStatus
+ {
+ UnknownMediaStatus,
+ NoMedia,
+ LoadingMedia,
+ LoadedMedia,
+ StalledMedia,
+ BufferingMedia,
+ BufferedMedia,
+ EndOfMedia,
+ InvalidMedia
+ };
+
+ enum Flag
+ {
+ LowLatency = 0x01,
+ StreamPlayback = 0x02,
+ VideoSurface = 0x04
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ enum Error
+ {
+ NoError,
+ ResourceError,
+ FormatError,
+ NetworkError,
+ AccessDeniedError,
+ ServiceMissingError
+ };
+
+ QMediaPlayer(QObject *parent = 0, Flags flags = 0, QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider());
+ ~QMediaPlayer();
+
+ static QtMultimediaKit::SupportEstimate hasSupport(const QString &mimeType,
+ const QStringList& codecs = QStringList(),
+ Flags flags = 0);
+ static QStringList supportedMimeTypes(Flags flags = 0);
+
+ void setVideoOutput(QVideoWidget *);
+ void setVideoOutput(QGraphicsVideoItem *);
+ void setVideoOutput(QAbstractVideoSurface *surface);
+
+ QMediaContent media() const;
+ const QIODevice *mediaStream() const;
+ QMediaPlaylist *playlist() const;
+
+ State state() const;
+ MediaStatus mediaStatus() const;
+
+ qint64 duration() const;
+ qint64 position() const;
+
+ int volume() const;
+ bool isMuted() const;
+ bool isAudioAvailable() const;
+ bool isVideoAvailable() const;
+
+ int bufferStatus() const;
+
+ bool isSeekable() const;
+ qreal playbackRate() const;
+
+ Error error() const;
+ QString errorString() const;
+
+ QNetworkConfiguration currentNetworkConfiguration() const;
+
+public Q_SLOTS:
+ void play();
+ void pause();
+ void stop();
+
+ void setPosition(qint64 position);
+ void setVolume(int volume);
+ void setMuted(bool muted);
+
+ void setPlaybackRate(qreal rate);
+
+ void setMedia(const QMediaContent &media, QIODevice *stream = 0);
+ void setPlaylist(QMediaPlaylist *playlist);
+
+ void setNetworkConfigurations(const QList<QNetworkConfiguration> &configurations);
+
+Q_SIGNALS:
+ void mediaChanged(const QMediaContent &media);
+
+ void stateChanged(QMediaPlayer::State newState);
+ void mediaStatusChanged(QMediaPlayer::MediaStatus status);
+
+ void durationChanged(qint64 duration);
+ void positionChanged(qint64 position);
+
+ void volumeChanged(int volume);
+ void mutedChanged(bool muted);
+ void audioAvailableChanged(bool available);
+ void videoAvailableChanged(bool videoAvailable);
+
+ void bufferStatusChanged(int percentFilled);
+
+ void seekableChanged(bool seekable);
+ void playbackRateChanged(qreal rate);
+
+ void error(QMediaPlayer::Error error);
+
+ void networkConfigurationChanged(const QNetworkConfiguration &configuration);
+public:
+ virtual bool bind(QObject *);
+ virtual void unbind(QObject *);
+
+private:
+ Q_DISABLE_COPY(QMediaPlayer)
+ Q_DECLARE_PRIVATE(QMediaPlayer)
+ Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(QMediaPlayer::State))
+ Q_PRIVATE_SLOT(d_func(), void _q_mediaStatusChanged(QMediaPlayer::MediaStatus))
+ Q_PRIVATE_SLOT(d_func(), void _q_error(int, const QString &))
+ Q_PRIVATE_SLOT(d_func(), void _q_updateMedia(const QMediaContent&))
+ Q_PRIVATE_SLOT(d_func(), void _q_playlistDestroyed())
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QMediaPlayer::State)
+Q_DECLARE_METATYPE(QMediaPlayer::MediaStatus)
+Q_DECLARE_METATYPE(QMediaPlayer::Error)
+
+Q_MEDIA_ENUM_DEBUG(QMediaPlayer, State)
+Q_MEDIA_ENUM_DEBUG(QMediaPlayer, MediaStatus)
+Q_MEDIA_ENUM_DEBUG(QMediaPlayer, Error)
+
+QT_END_HEADER
+
+#endif // QMEDIAPLAYER_H
diff --git a/src/multimediakit/qmediaplayercontrol.cpp b/src/multimediakit/qmediaplayercontrol.cpp
new file mode 100644
index 000000000..255a63438
--- /dev/null
+++ b/src/multimediakit/qmediaplayercontrol.cpp
@@ -0,0 +1,414 @@
+/****************************************************************************
+**
+** 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 "qmediaplayercontrol.h"
+#include "qmediacontrol_p.h"
+#include "qmediaplayer.h"
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ \class QMediaPlayerControl
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+
+ \brief The QMediaPlayerControl class provides access to the media playing
+ functionality of a QMediaService.
+
+ If a QMediaService can play media is will implement QMediaPlayerControl.
+ This control provides a means to set the \l {setMedia()}{media} to play,
+ \l {play()}{start}, \l {pause()} {pause} and \l {stop()}{stop} playback,
+ \l {setPosition()}{seek}, and control the \l {setVolume()}{volume}.
+ It also provides feedback on the \l {duration()}{duration} of the media,
+ the current \l {position()}{position}, and \l {bufferStatus()}{buffering}
+ progress.
+
+ The functionality provided by this control is exposed to application
+ code through the QMediaPlayer class.
+
+ The interface name of QMediaPlayerControl is \c com.nokia.Qt.QMediaPlayerControl/1.0 as
+ defined in QMediaPlayerControl_iid.
+
+ \sa QMediaService::requestControl(), QMediaPlayer
+*/
+
+/*!
+ \macro QMediaPlayerControl_iid
+
+ \c com.nokia.Qt.QMediaPlayerControl/1.0
+
+ Defines the interface name of the QMediaPlayerControl class.
+
+ \relates QMediaPlayerControl
+*/
+
+/*!
+ Destroys a media player control.
+*/
+QMediaPlayerControl::~QMediaPlayerControl()
+{
+}
+
+/*!
+ Constructs a new media player control with the given \a parent.
+*/
+QMediaPlayerControl::QMediaPlayerControl(QObject *parent):
+ QMediaControl(*new QMediaControlPrivate, parent)
+{
+}
+
+/*!
+ \fn QMediaPlayerControl::state() const
+
+ Returns the state of a player control.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::stateChanged(QMediaPlayer::State state)
+
+ Signals that the \a state of a player control has changed.
+
+ \since 1.0
+ \sa state()
+*/
+
+/*!
+ \fn QMediaPlayerControl::mediaStatus() const
+
+ Returns the status of the current media.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::mediaStatusChanged(QMediaPlayer::MediaStatus status)
+
+ Signals that the \a status of the current media has changed.
+
+ \since 1.0
+ \sa mediaStatus()
+*/
+
+
+/*!
+ \fn QMediaPlayerControl::duration() const
+
+ Returns the duration of the current media in milliseconds.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::durationChanged(qint64 duration)
+
+ Signals that the \a duration of the current media has changed.
+
+ \since 1.0
+ \sa duration()
+*/
+
+/*!
+ \fn QMediaPlayerControl::position() const
+
+ Returns the current playback position in milliseconds.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::setPosition(qint64 position)
+
+ Sets the playback \a position of the current media. This will initiate a seek and it may take
+ some time for playback to reach the position set.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::positionChanged(qint64 position)
+
+ Signals the playback \a position has changed.
+
+ This is only emitted in when there has been a discontinous change in the playback postion, such
+ as a seek or the position being reset.
+
+ \since 1.0
+ \sa position()
+*/
+
+/*!
+ \fn QMediaPlayerControl::volume() const
+
+ Returns the audio volume of a player control.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::setVolume(int volume)
+
+ Sets the audio \a volume of a player control.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::volumeChanged(int volume)
+
+ Signals the audio \a volume of a player control has changed.
+
+ \since 1.0
+ \sa volume()
+*/
+
+/*!
+ \fn QMediaPlayerControl::isMuted() const
+
+ Returns the mute state of a player control.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::setMuted(bool mute)
+
+ Sets the \a mute state of a player control.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::mutedChanged(bool mute)
+
+ Signals a change in the \a mute status of a player control.
+
+ \since 1.0
+ \sa isMuted()
+*/
+
+/*!
+ \fn QMediaPlayerControl::bufferStatus() const
+
+ Returns the buffering progress of the current media. Progress is measured in the percentage
+ of the buffer filled.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::bufferStatusChanged(int progress)
+
+ Signals that buffering \a progress has changed.
+
+ \since 1.0
+ \sa bufferStatus()
+*/
+
+/*!
+ \fn QMediaPlayerControl::isAudioAvailable() const
+
+ Identifies if there is audio output available for the current media.
+
+ Returns true if audio output is available and false otherwise.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::audioAvailableChanged(bool audio)
+
+ Signals that there has been a change in the availability of \a audio output.
+
+ \since 1.0
+ \sa isAudioAvailable()
+*/
+
+/*!
+ \fn QMediaPlayerControl::isVideoAvailable() const
+
+ Identifies if there is video output available for the current media.
+
+ Returns true if video output is available and false otherwise.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::videoAvailableChanged(bool video)
+
+ Signals that there has been a change in the availability of \a video output.
+
+ \since 1.0
+ \sa isVideoAvailable()
+*/
+
+/*!
+ \fn QMediaPlayerControl::isSeekable() const
+
+ Identifies if the current media is seekable.
+
+ Returns true if it possible to seek within the current media, and false otherwise.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::seekableChanged(bool seekable)
+
+ Signals that the \a seekable state of a player control has changed.
+
+ \since 1.0
+ \sa isSeekable()
+*/
+
+/*!
+ \fn QMediaPlayerControl::availablePlaybackRanges() const
+
+ Returns a range of times in milliseconds that can be played back.
+
+ Usually for local files this is a continuous interval equal to [0..duration()]
+ or an empty time range if seeking is not supported, but for network sources
+ it refers to the buffered parts of the media.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::availablePlaybackRangesChanged(const QMediaTimeRange &ranges)
+
+ Signals that the available media playback \a ranges have changed.
+
+ \since 1.0
+ \sa QMediaPlayerControl::availablePlaybackRanges()
+*/
+
+/*!
+ \fn qreal QMediaPlayerControl::playbackRate() const
+
+ Returns the rate of playback.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::setPlaybackRate(qreal rate)
+
+ Sets the \a rate of playback.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::media() const
+
+ Returns the current media source.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::mediaStream() const
+
+ Returns the current media stream. This is only a valid if a stream was passed to setMedia().
+
+ \since 1.0
+ \sa setMedia()
+*/
+
+/*!
+ \fn QMediaPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream)
+
+ Sets the current \a media source. If a \a stream is supplied; data will be read from that
+ instead of attempting to resolve the media source. The media source may still be used to
+ supply media information such as mime type.
+
+ Setting the media to a null QMediaContent will cause the control to discard all
+ information relating to the current media source and to cease all I/O operations related
+ to that media.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::mediaChanged(const QMediaContent& content)
+
+ Signals that the current media \a content has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::play()
+
+ Starts playback of the current media.
+
+ If successful the player control will immediately enter the \l {QMediaPlayer::PlayingState}
+ {playing} state.
+
+ \since 1.0
+ \sa state()
+*/
+
+/*!
+ \fn QMediaPlayerControl::pause()
+
+ Pauses playback of the current media.
+
+ If sucessful the player control will immediately enter the \l {QMediaPlayer::PausedState}
+ {paused} state.
+
+ \since 1.0
+ \sa state(), play(), stop()
+*/
+
+/*!
+ \fn QMediaPlayerControl::stop()
+
+ Stops playback of the current media.
+
+ If successful the player control will immediately enter the \l {QMediaPlayer::StoppedState}
+ {stopped} state.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::error(int error, const QString &errorString)
+
+ Signals that an \a error has occurred. The \a errorString provides a more detailed explanation.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlayerControl::playbackRateChanged(qreal rate)
+
+ Signal emitted when playback rate changes to \a rate.
+ \since 1.0
+*/
+
+#include "moc_qmediaplayercontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaplayercontrol.h b/src/multimediakit/qmediaplayercontrol.h
new file mode 100644
index 000000000..842371c62
--- /dev/null
+++ b/src/multimediakit/qmediaplayercontrol.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** 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 QMEDIAPLAYERCONTROL_H
+#define QMEDIAPLAYERCONTROL_H
+
+#include "qmediacontrol.h"
+#include "qmediaplayer.h"
+#include "qmediatimerange.h"
+
+#include <QtCore/qpair.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMediaPlaylist;
+
+class Q_MULTIMEDIA_EXPORT QMediaPlayerControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ ~QMediaPlayerControl();
+
+ virtual QMediaPlayer::State state() const = 0;
+
+ virtual QMediaPlayer::MediaStatus mediaStatus() const = 0;
+
+ virtual qint64 duration() const = 0;
+
+ virtual qint64 position() const = 0;
+ virtual void setPosition(qint64 position) = 0;
+
+ virtual int volume() const = 0;
+ virtual void setVolume(int volume) = 0;
+
+ virtual bool isMuted() const = 0;
+ virtual void setMuted(bool muted) = 0;
+
+ virtual int bufferStatus() const = 0;
+
+ virtual bool isAudioAvailable() const = 0;
+ virtual bool isVideoAvailable() const = 0;
+
+ virtual bool isSeekable() const = 0;
+
+ virtual QMediaTimeRange availablePlaybackRanges() const = 0;
+
+ virtual qreal playbackRate() const = 0;
+ virtual void setPlaybackRate(qreal rate) = 0;
+
+ virtual QMediaContent media() const = 0;
+ virtual const QIODevice *mediaStream() const = 0;
+ virtual void setMedia(const QMediaContent &media, QIODevice *stream) = 0;
+
+ virtual void play() = 0;
+ virtual void pause() = 0;
+ virtual void stop() = 0;
+
+Q_SIGNALS:
+ void mediaChanged(const QMediaContent& content);
+ void durationChanged(qint64 duration);
+ void positionChanged(qint64 position);
+ void stateChanged(QMediaPlayer::State newState);
+ void mediaStatusChanged(QMediaPlayer::MediaStatus status);
+ void volumeChanged(int volume);
+ void mutedChanged(bool muted);
+ void audioAvailableChanged(bool audioAvailable);
+ void videoAvailableChanged(bool videoAvailable);
+ void bufferStatusChanged(int percentFilled);
+ void seekableChanged(bool);
+ void availablePlaybackRangesChanged(const QMediaTimeRange&);
+ void playbackRateChanged(qreal rate);
+ void error(int error, const QString &errorString);
+
+protected:
+ QMediaPlayerControl(QObject* parent = 0);
+};
+
+#define QMediaPlayerControl_iid "com.nokia.Qt.QMediaPlayerControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QMediaPlayerControl, QMediaPlayerControl_iid)
+
+QT_END_NAMESPACE
+
+#endif // QMEDIAPLAYERCONTROL_H
+
diff --git a/src/multimediakit/qmediaplaylist.cpp b/src/multimediakit/qmediaplaylist.cpp
new file mode 100644
index 000000000..93a91847a
--- /dev/null
+++ b/src/multimediakit/qmediaplaylist.cpp
@@ -0,0 +1,756 @@
+/****************************************************************************
+**
+** 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 "qmediaplaylist.h"
+#include "qmediaplaylist_p.h"
+#include "qmediaplaylistprovider.h"
+#include "qlocalmediaplaylistprovider.h"
+#include "qmediaplaylistioplugin.h"
+#include "qmediaservice.h"
+#include "qmediaplaylistcontrol.h"
+#include "qmediaplayercontrol.h"
+
+#include <QtCore/qlist.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qcoreapplication.h>
+
+#include "qmediapluginloader_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, playlistIOLoader,
+ (QMediaPlaylistIOInterface_iid, QLatin1String("playlistformats"), Qt::CaseInsensitive))
+
+
+/*!
+ \class QMediaPlaylist
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+
+ \brief The QMediaPlaylist class provides a list of media content to play.
+
+ QMediaPlaylist is intended to be used with other media objects,
+ like QMediaPlayer or QMediaImageViewer.
+
+ QMediaPlaylist allows to access the service intrinsic playlist functionality
+ if available, otherwise it provides the the local memory playlist implementation.
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Movie playlist
+
+ Depending on playlist source implementation, most of the playlist mutating
+ operations can be asynchronous.
+
+ \sa QMediaContent
+*/
+
+
+/*!
+ \enum QMediaPlaylist::PlaybackMode
+
+ The QMediaPlaylist::PlaybackMode describes the order items in playlist are played.
+
+ \value CurrentItemOnce The current item is played only once.
+
+ \value CurrentItemInLoop The current item is played repeatedly in a loop.
+
+ \value Sequential Playback starts from the current and moves through each successive item until the last is reached and then stops.
+ The next item is a null item when the last one is currently playing.
+
+ \value Loop Playback restarts at the first item after the last has finished playing.
+
+ \value Random Play items in random order.
+*/
+
+
+
+/*!
+ Create a new playlist object for with the given \a parent.
+*/
+
+QMediaPlaylist::QMediaPlaylist(QObject *parent)
+ : QObject(parent)
+ , d_ptr(new QMediaPlaylistPrivate)
+{
+ Q_D(QMediaPlaylist);
+
+ d->q_ptr = this;
+ d->localPlaylistControl = new QLocalMediaPlaylistControl(this);
+
+ setMediaObject(0);
+}
+
+/*!
+ Destroys the playlist.
+ */
+
+QMediaPlaylist::~QMediaPlaylist()
+{
+ Q_D(QMediaPlaylist);
+
+ if (d->mediaObject)
+ d->mediaObject->unbind(this);
+
+ delete d_ptr;
+}
+
+/*!
+ Returns the QMediaObject instance that this QMediaPlaylist is bound too,
+ or 0 otherwise.
+ \since 1.0
+*/
+QMediaObject *QMediaPlaylist::mediaObject() const
+{
+ return d_func()->mediaObject;
+}
+
+/*!
+ \internal
+ If \a mediaObject is null or doesn't have an intrinsic playlist,
+ internal local memory playlist source will be created.
+ \since 1.0
+*/
+bool QMediaPlaylist::setMediaObject(QMediaObject *mediaObject)
+{
+ Q_D(QMediaPlaylist);
+
+ if (mediaObject && mediaObject == d->mediaObject)
+ return true;
+
+ QMediaService *service = mediaObject
+ ? mediaObject->service() : 0;
+
+ QMediaPlaylistControl *newControl = 0;
+
+ if (service)
+ newControl = qobject_cast<QMediaPlaylistControl*>(service->requestControl(QMediaPlaylistControl_iid));
+
+ if (!newControl)
+ newControl = d->localPlaylistControl;
+
+ if (d->control != newControl) {
+ int oldSize = 0;
+ if (d->control) {
+ QMediaPlaylistProvider *playlist = d->control->playlistProvider();
+ oldSize = playlist->mediaCount();
+ disconnect(playlist, SIGNAL(loadFailed(QMediaPlaylist::Error,QString)),
+ this, SLOT(_q_loadFailed(QMediaPlaylist::Error,QString)));
+
+ disconnect(playlist, SIGNAL(mediaChanged(int,int)), this, SIGNAL(mediaChanged(int,int)));
+ disconnect(playlist, SIGNAL(mediaAboutToBeInserted(int,int)), this, SIGNAL(mediaAboutToBeInserted(int,int)));
+ disconnect(playlist, SIGNAL(mediaInserted(int,int)), this, SIGNAL(mediaInserted(int,int)));
+ disconnect(playlist, SIGNAL(mediaAboutToBeRemoved(int,int)), this, SIGNAL(mediaAboutToBeRemoved(int,int)));
+ disconnect(playlist, SIGNAL(mediaRemoved(int,int)), this, SIGNAL(mediaRemoved(int,int)));
+
+ disconnect(playlist, SIGNAL(loaded()), this, SIGNAL(loaded()));
+
+ disconnect(d->control, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)),
+ this, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)));
+ disconnect(d->control, SIGNAL(currentIndexChanged(int)),
+ this, SIGNAL(currentIndexChanged(int)));
+ disconnect(d->control, SIGNAL(currentMediaChanged(QMediaContent)),
+ this, SIGNAL(currentMediaChanged(QMediaContent)));
+
+ if (d->mediaObject)
+ d->mediaObject->service()->releaseControl(d->control);
+ }
+
+ d->control = newControl;
+ QMediaPlaylistProvider *playlist = d->control->playlistProvider();
+ connect(playlist, SIGNAL(loadFailed(QMediaPlaylist::Error,QString)),
+ this, SLOT(_q_loadFailed(QMediaPlaylist::Error,QString)));
+
+ connect(playlist, SIGNAL(mediaChanged(int,int)), this, SIGNAL(mediaChanged(int,int)));
+ connect(playlist, SIGNAL(mediaAboutToBeInserted(int,int)), this, SIGNAL(mediaAboutToBeInserted(int,int)));
+ connect(playlist, SIGNAL(mediaInserted(int,int)), this, SIGNAL(mediaInserted(int,int)));
+ connect(playlist, SIGNAL(mediaAboutToBeRemoved(int,int)), this, SIGNAL(mediaAboutToBeRemoved(int,int)));
+ connect(playlist, SIGNAL(mediaRemoved(int,int)), this, SIGNAL(mediaRemoved(int,int)));
+
+ connect(playlist, SIGNAL(loaded()), this, SIGNAL(loaded()));
+
+ connect(d->control, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)),
+ this, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)));
+ connect(d->control, SIGNAL(currentIndexChanged(int)),
+ this, SIGNAL(currentIndexChanged(int)));
+ connect(d->control, SIGNAL(currentMediaChanged(QMediaContent)),
+ this, SIGNAL(currentMediaChanged(QMediaContent)));
+
+ if (oldSize)
+ emit mediaRemoved(0, oldSize-1);
+
+ if (playlist->mediaCount()) {
+ emit mediaAboutToBeInserted(0,playlist->mediaCount()-1);
+ emit mediaInserted(0,playlist->mediaCount()-1);
+ }
+ }
+
+ d->mediaObject = mediaObject;
+
+ return true;
+}
+
+/*!
+ \property QMediaPlaylist::playbackMode
+
+ This property defines the order, items in playlist are played.
+
+ \since 1.0
+ \sa QMediaPlaylist::PlaybackMode
+*/
+
+QMediaPlaylist::PlaybackMode QMediaPlaylist::playbackMode() const
+{
+ return d_func()->control->playbackMode();
+}
+
+void QMediaPlaylist::setPlaybackMode(QMediaPlaylist::PlaybackMode mode)
+{
+ Q_D(QMediaPlaylist);
+ d->control->setPlaybackMode(mode);
+}
+
+/*!
+ Returns position of the current media content in the playlist.
+ \since 1.0
+*/
+int QMediaPlaylist::currentIndex() const
+{
+ return d_func()->control->currentIndex();
+}
+
+/*!
+ Returns the current media content.
+ \since 1.0
+*/
+
+QMediaContent QMediaPlaylist::currentMedia() const
+{
+ return d_func()->playlist()->media(currentIndex());
+}
+
+/*!
+ Returns the index of the item, which would be current after calling next()
+ \a steps times.
+
+ Returned value depends on the size of playlist, current position
+ and playback mode.
+
+ \since 1.0
+ \sa QMediaPlaylist::playbackMode
+*/
+int QMediaPlaylist::nextIndex(int steps) const
+{
+ return d_func()->control->nextIndex(steps);
+}
+
+/*!
+ Returns the index of the item, which would be current after calling previous()
+ \a steps times.
+
+ \since 1.0
+ \sa QMediaPlaylist::playbackMode
+*/
+
+int QMediaPlaylist::previousIndex(int steps) const
+{
+ return d_func()->control->previousIndex(steps);
+}
+
+
+/*!
+ Returns the number of items in the playlist.
+
+ \since 1.0
+ \sa isEmpty()
+ */
+int QMediaPlaylist::mediaCount() const
+{
+ return d_func()->playlist()->mediaCount();
+}
+
+/*!
+ Returns true if the playlist contains no items; otherwise returns false.
+
+ \since 1.0
+ \sa mediaCount()
+ */
+bool QMediaPlaylist::isEmpty() const
+{
+ return mediaCount() == 0;
+}
+
+/*!
+ Returns true if the playlist can be modified; otherwise returns false.
+
+ \since 1.0
+ \sa mediaCount()
+ */
+bool QMediaPlaylist::isReadOnly() const
+{
+ return d_func()->playlist()->isReadOnly();
+}
+
+/*!
+ Returns the media content at \a index in the playlist.
+ \since 1.0
+*/
+
+QMediaContent QMediaPlaylist::media(int index) const
+{
+ return d_func()->playlist()->media(index);
+}
+
+/*!
+ Append the media \a content to the playlist.
+
+ Returns true if the operation is successful, otherwise return false.
+ \since 1.0
+ */
+bool QMediaPlaylist::addMedia(const QMediaContent &content)
+{
+ return d_func()->control->playlistProvider()->addMedia(content);
+}
+
+/*!
+ Append multiple media content \a items to the playlist.
+
+ Returns true if the operation is successful, otherwise return false.
+ \since 1.0
+ */
+bool QMediaPlaylist::addMedia(const QList<QMediaContent> &items)
+{
+ return d_func()->control->playlistProvider()->addMedia(items);
+}
+
+/*!
+ Insert the media \a content to the playlist at position \a pos.
+
+ Returns true if the operation is successful, otherwise false.
+ \since 1.0
+*/
+
+bool QMediaPlaylist::insertMedia(int pos, const QMediaContent &content)
+{
+ return d_func()->playlist()->insertMedia(pos, content);
+}
+
+/*!
+ Insert multiple media content \a items to the playlist at position \a pos.
+
+ Returns true if the operation is successful, otherwise false.
+ \since 1.0
+*/
+
+bool QMediaPlaylist::insertMedia(int pos, const QList<QMediaContent> &items)
+{
+ return d_func()->playlist()->insertMedia(pos, items);
+}
+
+/*!
+ Remove the item from the playlist at position \a pos.
+
+ Returns true if the operation is successful, otherwise return false.
+ \since 1.0
+ */
+bool QMediaPlaylist::removeMedia(int pos)
+{
+ Q_D(QMediaPlaylist);
+ return d->playlist()->removeMedia(pos);
+}
+
+/*!
+ Remove items in the playlist from \a start to \a end inclusive.
+
+ Returns true if the operation is successful, otherwise return false.
+ \since 1.0
+ */
+bool QMediaPlaylist::removeMedia(int start, int end)
+{
+ Q_D(QMediaPlaylist);
+ return d->playlist()->removeMedia(start, end);
+}
+
+/*!
+ Remove all the items from the playlist.
+
+ Returns true if the operation is successful, otherwise return false.
+ \since 1.0
+ */
+bool QMediaPlaylist::clear()
+{
+ Q_D(QMediaPlaylist);
+ return d->playlist()->clear();
+}
+
+bool QMediaPlaylistPrivate::readItems(QMediaPlaylistReader *reader)
+{
+ while (!reader->atEnd())
+ playlist()->addMedia(reader->readItem());
+
+ return true;
+}
+
+bool QMediaPlaylistPrivate::writeItems(QMediaPlaylistWriter *writer)
+{
+ for (int i=0; i<playlist()->mediaCount(); i++) {
+ if (!writer->writeItem(playlist()->media(i)))
+ return false;
+ }
+ writer->close();
+ return true;
+}
+
+/*!
+ Load playlist from \a location. If \a format is specified, it is used,
+ otherwise format is guessed from location name and data.
+
+ New items are appended to playlist.
+
+ QMediaPlaylist::loaded() signal is emitted if playlist was loaded successfully,
+ otherwise the playlist emits loadFailed().
+ \since 1.0
+*/
+void QMediaPlaylist::load(const QUrl &location, const char *format)
+{
+ Q_D(QMediaPlaylist);
+
+ d->error = NoError;
+ d->errorString.clear();
+
+ if (d->playlist()->load(location,format))
+ return;
+
+ if (isReadOnly()) {
+ d->error = AccessDeniedError;
+ d->errorString = tr("Could not add items to read only playlist.");
+ emit loadFailed();
+ return;
+ }
+
+ foreach (QString const& key, playlistIOLoader()->keys()) {
+ QMediaPlaylistIOInterface* plugin = qobject_cast<QMediaPlaylistIOInterface*>(playlistIOLoader()->instance(key));
+ if (plugin && plugin->canRead(location,format)) {
+ QMediaPlaylistReader *reader = plugin->createReader(location,QByteArray(format));
+ if (reader && d->readItems(reader)) {
+ delete reader;
+ emit loaded();
+ return;
+ }
+ delete reader;
+ }
+ }
+
+ d->error = FormatNotSupportedError;
+ d->errorString = tr("Playlist format is not supported");
+ emit loadFailed();
+
+ return;
+}
+
+/*!
+ Load playlist from QIODevice \a device. If \a format is specified, it is used,
+ otherwise format is guessed from device data.
+
+ New items are appended to playlist.
+
+ QMediaPlaylist::loaded() signal is emitted if playlist was loaded successfully,
+ otherwise the playlist emits loadFailed().
+ \since 1.0
+*/
+void QMediaPlaylist::load(QIODevice * device, const char *format)
+{
+ Q_D(QMediaPlaylist);
+
+ d->error = NoError;
+ d->errorString.clear();
+
+ if (d->playlist()->load(device,format))
+ return;
+
+ if (isReadOnly()) {
+ d->error = AccessDeniedError;
+ d->errorString = tr("Could not add items to read only playlist.");
+ emit loadFailed();
+ return;
+ }
+
+ foreach (QString const& key, playlistIOLoader()->keys()) {
+ QMediaPlaylistIOInterface* plugin = qobject_cast<QMediaPlaylistIOInterface*>(playlistIOLoader()->instance(key));
+ if (plugin && plugin->canRead(device,format)) {
+ QMediaPlaylistReader *reader = plugin->createReader(device,QByteArray(format));
+ if (reader && d->readItems(reader)) {
+ delete reader;
+ emit loaded();
+ return;
+ }
+ delete reader;
+ }
+ }
+
+ d->error = FormatNotSupportedError;
+ d->errorString = tr("Playlist format is not supported");
+ emit loadFailed();
+
+ return;
+}
+
+/*!
+ Save playlist to \a location. If \a format is specified, it is used,
+ otherwise format is guessed from location name.
+
+ Returns true if playlist was saved successfully, otherwise returns false.
+ \since 1.0
+ */
+bool QMediaPlaylist::save(const QUrl &location, const char *format)
+{
+ Q_D(QMediaPlaylist);
+
+ d->error = NoError;
+ d->errorString.clear();
+
+ if (d->playlist()->save(location,format))
+ return true;
+
+ QFile file(location.toLocalFile());
+
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ d->error = AccessDeniedError;
+ d->errorString = tr("The file could not be accessed.");
+ return false;
+ }
+
+ return save(&file, format);
+}
+
+/*!
+ Save playlist to QIODevice \a device using format \a format.
+
+ Returns true if playlist was saved successfully, otherwise returns false.
+ \since 1.0
+*/
+bool QMediaPlaylist::save(QIODevice * device, const char *format)
+{
+ Q_D(QMediaPlaylist);
+
+ d->error = NoError;
+ d->errorString.clear();
+
+ if (d->playlist()->save(device,format))
+ return true;
+
+ foreach (QString const& key, playlistIOLoader()->keys()) {
+ QMediaPlaylistIOInterface* plugin = qobject_cast<QMediaPlaylistIOInterface*>(playlistIOLoader()->instance(key));
+ if (plugin && plugin->canWrite(device,format)) {
+ QMediaPlaylistWriter *writer = plugin->createWriter(device,QByteArray(format));
+ if (writer && d->writeItems(writer)) {
+ delete writer;
+ return true;
+ }
+ delete writer;
+ }
+ }
+
+ d->error = FormatNotSupportedError;
+ d->errorString = tr("Playlist format is not supported.");
+
+ return false;
+}
+
+/*!
+ Returns the last error condition.
+ \since 1.0
+*/
+QMediaPlaylist::Error QMediaPlaylist::error() const
+{
+ return d_func()->error;
+}
+
+/*!
+ Returns the string describing the last error condition.
+ \since 1.0
+*/
+QString QMediaPlaylist::errorString() const
+{
+ return d_func()->errorString;
+}
+
+/*!
+ Shuffle items in the playlist.
+ \since 1.0
+*/
+void QMediaPlaylist::shuffle()
+{
+ d_func()->playlist()->shuffle();
+}
+
+
+/*!
+ Advance to the next media content in playlist.
+ \since 1.0
+*/
+void QMediaPlaylist::next()
+{
+ d_func()->control->next();
+}
+
+/*!
+ Return to the previous media content in playlist.
+ \since 1.0
+*/
+void QMediaPlaylist::previous()
+{
+ d_func()->control->previous();
+}
+
+/*!
+ Activate media content from playlist at position \a playlistPosition.
+ \since 1.0
+*/
+
+void QMediaPlaylist::setCurrentIndex(int playlistPosition)
+{
+ d_func()->control->setCurrentIndex(playlistPosition);
+}
+
+/*!
+ \fn void QMediaPlaylist::mediaInserted(int start, int end)
+
+ This signal is emitted after media has been inserted into the playlist.
+ The new items are those between \a start and \a end inclusive.
+ \since 1.0
+ */
+
+/*!
+ \fn void QMediaPlaylist::mediaRemoved(int start, int end)
+
+ This signal is emitted after media has been removed from the playlist.
+ The removed items are those between \a start and \a end inclusive.
+ \since 1.0
+ */
+
+/*!
+ \fn void QMediaPlaylist::mediaChanged(int start, int end)
+
+ This signal is emitted after media has been changed in the playlist
+ between \a start and \a end positions inclusive.
+ \since 1.0
+ */
+
+/*!
+ \fn void QMediaPlaylist::currentIndexChanged(int position)
+
+ Signal emitted when playlist position changed to \a position.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlaylist::playbackModeChanged(QMediaPlaylist::PlaybackMode mode)
+
+ Signal emitted when playback mode changed to \a mode.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlaylist::mediaAboutToBeInserted(int start, int end)
+
+ Signal emitted when items are to be inserted at \a start and ending at \a end.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlaylist::mediaAboutToBeRemoved(int start, int end)
+
+ Signal emitted when item are to be deleted at \a start and ending at \a end.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlaylist::currentMediaChanged(const QMediaContent &content)
+
+ Signal emitted when current media changes to \a content.
+ \since 1.0
+*/
+
+/*!
+ \property QMediaPlaylist::currentIndex
+ \brief Current position.
+ \since 1.0
+*/
+
+/*!
+ \property QMediaPlaylist::currentMedia
+ \brief Current media content.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylist::loaded()
+
+ Signal emitted when playlist finished loading.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylist::loadFailed()
+
+ Signal emitted if failed to load playlist.
+ \since 1.0
+*/
+
+/*!
+ \enum QMediaPlaylist::Error
+
+ This enum describes the QMediaPlaylist error codes.
+
+ \value NoError No errors.
+ \value FormatError Format error.
+ \value FormatNotSupportedError Format not supported.
+ \value NetworkError Network error.
+ \value AccessDeniedError Access denied error.
+*/
+
+#include "moc_qmediaplaylist.cpp"
+#include "moc_qmediaplaylist_p.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaplaylist.h b/src/multimediakit/qmediaplaylist.h
new file mode 100644
index 000000000..4e82c5fae
--- /dev/null
+++ b/src/multimediakit/qmediaplaylist.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** 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 QMEDIAPLAYLIST_H
+#define QMEDIAPLAYLIST_H
+
+#include <QtCore/qobject.h>
+
+#include <qmediacontent.h>
+#include <qmediaobject.h>
+#include <qmediabindableinterface.h>
+#include <qmediaenumdebug.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QMediaPlaylistProvider;
+
+class QMediaPlaylistPrivate;
+class Q_MULTIMEDIA_EXPORT QMediaPlaylist : public QObject, public QMediaBindableInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaBindableInterface)
+ Q_PROPERTY(QMediaPlaylist::PlaybackMode playbackMode READ playbackMode WRITE setPlaybackMode NOTIFY playbackModeChanged)
+ Q_PROPERTY(QMediaContent currentMedia READ currentMedia NOTIFY currentMediaChanged)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_ENUMS(PlaybackMode Error)
+
+public:
+ enum PlaybackMode { CurrentItemOnce, CurrentItemInLoop, Sequential, Loop, Random };
+ enum Error { NoError, FormatError, FormatNotSupportedError, NetworkError, AccessDeniedError };
+
+ QMediaPlaylist(QObject *parent = 0);
+ virtual ~QMediaPlaylist();
+
+ QMediaObject *mediaObject() const;
+
+ PlaybackMode playbackMode() const;
+ void setPlaybackMode(PlaybackMode mode);
+
+ int currentIndex() const;
+ QMediaContent currentMedia() const;
+
+ int nextIndex(int steps = 1) const;
+ int previousIndex(int steps = 1) const;
+
+ QMediaContent media(int index) const;
+
+ int mediaCount() const;
+ bool isEmpty() const;
+ bool isReadOnly() const;
+
+ bool addMedia(const QMediaContent &content);
+ bool addMedia(const QList<QMediaContent> &items);
+ bool insertMedia(int index, const QMediaContent &content);
+ bool insertMedia(int index, const QList<QMediaContent> &items);
+ bool removeMedia(int pos);
+ bool removeMedia(int start, int end);
+ bool clear();
+
+ void load(const QUrl &location, const char *format = 0);
+ void load(QIODevice * device, const char *format = 0);
+
+ bool save(const QUrl &location, const char *format = 0);
+ bool save(QIODevice * device, const char *format);
+
+ Error error() const;
+ QString errorString() const;
+
+public Q_SLOTS:
+ void shuffle();
+
+ void next();
+ void previous();
+
+ void setCurrentIndex(int index);
+
+Q_SIGNALS:
+ void currentIndexChanged(int index);
+ void playbackModeChanged(QMediaPlaylist::PlaybackMode mode);
+ void currentMediaChanged(const QMediaContent&);
+
+ void mediaAboutToBeInserted(int start, int end);
+ void mediaInserted(int start, int end);
+ void mediaAboutToBeRemoved(int start, int end);
+ void mediaRemoved(int start, int end);
+ void mediaChanged(int start, int end);
+
+ void loaded();
+ void loadFailed();
+
+protected:
+ bool setMediaObject(QMediaObject *object);
+ QMediaPlaylistPrivate *d_ptr;
+
+private:
+ Q_DECLARE_PRIVATE(QMediaPlaylist)
+ Q_PRIVATE_SLOT(d_func(), void _q_loadFailed(QMediaPlaylist::Error, const QString &))
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QMediaPlaylist::PlaybackMode)
+Q_DECLARE_METATYPE(QMediaPlaylist::Error)
+
+Q_MEDIA_ENUM_DEBUG(QMediaPlaylist, PlaybackMode)
+Q_MEDIA_ENUM_DEBUG(QMediaPlaylist, Error)
+
+#endif // QMEDIAPLAYLIST_H
diff --git a/src/multimediakit/qmediaplaylist_p.h b/src/multimediakit/qmediaplaylist_p.h
new file mode 100644
index 000000000..d029a68d4
--- /dev/null
+++ b/src/multimediakit/qmediaplaylist_p.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** 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 QMEDIAPLAYLIST_P_H
+#define QMEDIAPLAYLIST_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 "qmediaplaylist.h"
+#include "qmediaplaylistcontrol.h"
+#include "qmediaplayer.h"
+#include "qmediaplayercontrol.h"
+#include "qlocalmediaplaylistprovider.h"
+#include "qmediaobject_p.h"
+
+#include <QtCore/qdebug.h>
+
+#ifdef Q_MOC_RUN
+# pragma Q_MOC_EXPAND_MACROS
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QMediaPlaylistControl;
+class QMediaPlaylistProvider;
+class QMediaPlaylistReader;
+class QMediaPlaylistWriter;
+class QMediaPlayerControl;
+
+class QMediaPlaylistPrivate
+{
+ Q_DECLARE_PUBLIC(QMediaPlaylist)
+public:
+ QMediaPlaylistPrivate()
+ :mediaObject(0),
+ control(0),
+ localPlaylistControl(0),
+ error(QMediaPlaylist::NoError)
+ {
+ }
+
+ virtual ~QMediaPlaylistPrivate() {}
+
+ void _q_loadFailed(QMediaPlaylist::Error error, const QString &errorString)
+ {
+ this->error = error;
+ this->errorString = errorString;
+
+ emit q_ptr->loadFailed();
+ }
+
+ void _q_mediaObjectDeleted()
+ {
+ Q_Q(QMediaPlaylist);
+ mediaObject = 0;
+ if (control != localPlaylistControl)
+ control = 0;
+ q->setMediaObject(0);
+ }
+
+ QMediaObject *mediaObject;
+
+ QMediaPlaylistControl *control;
+ QMediaPlaylistProvider *playlist() const { return control->playlistProvider(); }
+
+ QMediaPlaylistControl *localPlaylistControl;
+
+ bool readItems(QMediaPlaylistReader *reader);
+ bool writeItems(QMediaPlaylistWriter *writer);
+
+ QMediaPlaylist::Error error;
+ QString errorString;
+
+ QMediaPlaylist *q_ptr;
+};
+
+
+class QLocalMediaPlaylistControl : public QMediaPlaylistControl
+{
+ Q_OBJECT
+public:
+ QLocalMediaPlaylistControl(QObject *parent)
+ :QMediaPlaylistControl(parent)
+ {
+ QMediaPlaylistProvider *playlist = new QLocalMediaPlaylistProvider(this);
+ m_navigator = new QMediaPlaylistNavigator(playlist,this);
+ m_navigator->setPlaybackMode(QMediaPlaylist::Sequential);
+
+ connect(m_navigator, SIGNAL(currentIndexChanged(int)), SIGNAL(currentIndexChanged(int)));
+ connect(m_navigator, SIGNAL(activated(QMediaContent)), SIGNAL(currentMediaChanged(QMediaContent)));
+ connect(m_navigator, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)), SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)));
+ }
+
+ virtual ~QLocalMediaPlaylistControl() {};
+
+ QMediaPlaylistProvider* playlistProvider() const { return m_navigator->playlist(); }
+ bool setPlaylistProvider(QMediaPlaylistProvider *mediaPlaylist)
+ {
+ m_navigator->setPlaylist(mediaPlaylist);
+ emit playlistProviderChanged();
+ return true;
+ }
+
+ int currentIndex() const { return m_navigator->currentIndex(); }
+ void setCurrentIndex(int position) { m_navigator->jump(position); }
+ int nextIndex(int steps) const { return m_navigator->nextIndex(steps); }
+ int previousIndex(int steps) const { return m_navigator->previousIndex(steps); }
+
+ void next() { m_navigator->next(); }
+ void previous() { m_navigator->previous(); }
+
+ QMediaPlaylist::PlaybackMode playbackMode() const { return m_navigator->playbackMode(); }
+ void setPlaybackMode(QMediaPlaylist::PlaybackMode mode) { m_navigator->setPlaybackMode(mode); }
+
+private:
+ QMediaPlaylistNavigator *m_navigator;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QMEDIAPLAYLIST_P_H
diff --git a/src/multimediakit/qmediaplaylistcontrol.cpp b/src/multimediakit/qmediaplaylistcontrol.cpp
new file mode 100644
index 000000000..47b4b5794
--- /dev/null
+++ b/src/multimediakit/qmediaplaylistcontrol.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** 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 "qmediaplaylistcontrol.h"
+#include "qmediacontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMediaPlaylistControl
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+
+ \brief The QMediaPlaylistControl class provides access to the playlist
+ functionality of a QMediaService.
+
+ If a QMediaService contains an internal playlist it will implement
+ QMediaPlaylistControl. This control provides access to the contents of the
+ \l {playlistProvider()}{playlist}, as well as the \l
+ {currentIndex()}{position} of the current media, and a means of navigating
+ to the \l {next()}{next} and \l {previous()}{previous} media.
+
+ The functionality provided by the control is exposed to application code
+ through the QMediaPlaylist class.
+
+ The interface name of QMediaPlaylistControl is \c com.nokia.Qt.QMediaPlaylistControl/1.0 as
+ defined in QMediaPlaylistControl_iid.
+
+ \sa QMediaService::requestControl(), QMediaPlayer
+*/
+
+/*!
+ \macro QMediaPlaylistControl_iid
+
+ \c com.nokia.Qt.QMediaPlaylistControl/1.0
+
+ Defines the interface name of the QMediaPlaylistControl class.
+
+ \relates QMediaPlaylistControl
+*/
+
+/*!
+ Create a new playlist control object with the given \a parent.
+*/
+QMediaPlaylistControl::QMediaPlaylistControl(QObject *parent):
+ QMediaControl(*new QMediaControlPrivate, parent)
+{
+}
+
+/*!
+ Destroys the playlist control.
+*/
+QMediaPlaylistControl::~QMediaPlaylistControl()
+{
+}
+
+
+/*!
+ \fn QMediaPlaylistControl::playlistProvider() const
+
+ Returns the playlist used by this media player.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistControl::setPlaylistProvider(QMediaPlaylistProvider *playlist)
+
+ Set the playlist of this media player to \a playlist.
+
+ In many cases it is possible just to use the playlist
+ constructed by player, but sometimes replacing the whole
+ playlist allows to avoid copyting of all the items bettween playlists.
+
+ Returns true if player can use this passed playlist; otherwise returns false.
+
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistControl::currentIndex() const
+
+ Returns position of the current media source in the playlist.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistControl::setCurrentIndex(int position)
+
+ Jump to the item at the given \a position.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistControl::nextIndex(int step) const
+
+ Returns the index of item, which were current after calling next()
+ \a step times.
+
+ Returned value depends on the size of playlist, current position
+ and playback mode.
+
+ \since 1.0
+ \sa QMediaPlaylist::playbackMode
+*/
+
+/*!
+ \fn QMediaPlaylistControl::previousIndex(int step) const
+
+ Returns the index of item, which were current after calling previous()
+ \a step times.
+
+ \since 1.0
+ \sa QMediaPlaylist::playbackMode
+*/
+
+/*!
+ \fn QMediaPlaylistControl::next()
+
+ Moves to the next item in playlist.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistControl::previous()
+
+ Returns to the previous item in playlist.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistControl::playbackMode() const
+
+ Returns the playlist navigation mode.
+
+ \since 1.0
+ \sa QMediaPlaylist::PlaybackMode
+*/
+
+/*!
+ \fn QMediaPlaylistControl::setPlaybackMode(QMediaPlaylist::PlaybackMode mode)
+
+ Sets the playback \a mode.
+
+ \since 1.0
+ \sa QMediaPlaylist::PlaybackMode
+*/
+
+/*!
+ \fn QMediaPlaylistControl::playlistProviderChanged()
+
+ Signal emitted when the playlist provider has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistControl::currentIndexChanged(int position)
+
+ Signal emitted when the playlist \a position is changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistControl::playbackModeChanged(QMediaPlaylist::PlaybackMode mode)
+
+ Signal emitted when the playback \a mode is changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistControl::currentMediaChanged(const QMediaContent& content)
+
+ Signal emitted when current media changes to \a content.
+ \since 1.0
+*/
+
+#include "moc_qmediaplaylistcontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaplaylistcontrol.h b/src/multimediakit/qmediaplaylistcontrol.h
new file mode 100644
index 000000000..ff113135a
--- /dev/null
+++ b/src/multimediakit/qmediaplaylistcontrol.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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 QMEDIAPLAYLISTCONTROL_H
+#define QMEDIAPLAYLISTCONTROL_H
+
+#include "qmediacontrol.h"
+#include "qmediaplaylistnavigator.h"
+
+
+QT_BEGIN_NAMESPACE
+
+class QMediaPlaylistProvider;
+
+class Q_MULTIMEDIA_EXPORT QMediaPlaylistControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ virtual ~QMediaPlaylistControl();
+
+ virtual QMediaPlaylistProvider* playlistProvider() const = 0;
+ virtual bool setPlaylistProvider(QMediaPlaylistProvider *playlist) = 0;
+
+ virtual int currentIndex() const = 0;
+ virtual void setCurrentIndex(int position) = 0;
+ virtual int nextIndex(int steps) const = 0;
+ virtual int previousIndex(int steps) const = 0;
+
+ virtual void next() = 0;
+ virtual void previous() = 0;
+
+ virtual QMediaPlaylist::PlaybackMode playbackMode() const = 0;
+ virtual void setPlaybackMode(QMediaPlaylist::PlaybackMode mode) = 0;
+
+Q_SIGNALS:
+ void playlistProviderChanged();
+ void currentIndexChanged(int position);
+ void currentMediaChanged(const QMediaContent&);
+ void playbackModeChanged(QMediaPlaylist::PlaybackMode mode);
+
+protected:
+ QMediaPlaylistControl(QObject* parent = 0);
+};
+
+#define QMediaPlaylistControl_iid "com.nokia.Qt.QMediaPlaylistControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QMediaPlaylistControl, QMediaPlaylistControl_iid)
+
+QT_END_NAMESPACE
+
+#endif // QMEDIAPLAYLISTCONTROL_H
diff --git a/src/multimediakit/qmediaplaylistioplugin.cpp b/src/multimediakit/qmediaplaylistioplugin.cpp
new file mode 100644
index 000000000..f0b5196f4
--- /dev/null
+++ b/src/multimediakit/qmediaplaylistioplugin.cpp
@@ -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$
+**
+****************************************************************************/
+
+#include "qmediaplaylistioplugin.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMediaPlaylistReader
+
+ \brief The QMediaPlaylistReader class provides an interface for reading a playlist file.
+ \inmodule QtMultimediaKit
+ \since 1.0
+
+ \sa QMediaPlaylistIOPlugin
+*/
+
+/*!
+ Destroys a media playlist reader.
+*/
+QMediaPlaylistReader::~QMediaPlaylistReader()
+{
+}
+
+/*!
+ \fn QMediaPlaylistReader::atEnd() const
+
+ Identifies if a playlist reader has reached the end of its input.
+
+ Returns true if the reader has reached the end; and false otherwise.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistReader::readItem()
+
+ Reads an item of media from a playlist file.
+
+ Returns the read media, or a null QMediaContent if no more media is available.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistReader::close()
+
+ Closes a playlist reader's input device.
+ \since 1.0
+*/
+
+/*!
+ \class QMediaPlaylistWriter
+
+ \brief The QMediaPlaylistWriter class provides an interface for writing a playlist file.
+
+ \since 1.0
+ \sa QMediaPlaylistIOPlugin
+*/
+
+/*!
+ Destroys a media playlist writer.
+*/
+QMediaPlaylistWriter::~QMediaPlaylistWriter()
+{
+}
+
+/*!
+ \fn QMediaPlaylistWriter::writeItem(const QMediaContent &media)
+
+ Writes an item of \a media to a playlist file.
+
+ Returns true if the media was written successfully; and false otherwise.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistWriter::close()
+
+ Finalizes the writing of a playlist and closes the output device.
+ \since 1.0
+*/
+
+/*!
+ \class QMediaPlaylistIOPlugin
+ \brief The QMediaPlaylistIOPlugin class provides an interface for media playlist I/O plug-ins.
+ \since 1.0
+*/
+
+/*!
+ Constructs a media playlist I/O plug-in with the given \a parent.
+*/
+QMediaPlaylistIOPlugin::QMediaPlaylistIOPlugin(QObject *parent)
+ :QObject(parent)
+{
+}
+
+/*!
+ Destroys a media playlist I/O plug-in.
+*/
+QMediaPlaylistIOPlugin::~QMediaPlaylistIOPlugin()
+{
+}
+
+/*!
+ \fn QMediaPlaylistIOPlugin::canRead(QIODevice *device, const QByteArray &format) const
+
+ Identifies if plug-in can read \a format data from an I/O \a device.
+
+ Returns true if the data can be read; and false otherwise.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistIOPlugin::canRead(const QUrl& location, const QByteArray &format) const
+
+ Identifies if a plug-in can read \a format data from a URL \a location.
+
+ Returns true if the data can be read; and false otherwise.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistIOPlugin::canWrite(QIODevice *device, const QByteArray &format) const
+
+ Identifies if a plug-in can write \a format data to an I/O \a device.
+
+ Returns true if the data can be written; and false otherwise.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistIOPlugin::keys() const
+
+ Returns a list of format keys supported by a plug-in.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistIOPlugin::createReader(QIODevice *device, const QByteArray &format)
+
+ Returns a new QMediaPlaylistReader which reads \a format data from an I/O \a device.
+
+ If the device is invalid or the format is unsupported this will return a null pointer.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistIOPlugin::createReader(const QUrl& location, const QByteArray &format)
+
+ Returns a new QMediaPlaylistReader which reads \a format data from a URL \a location.
+
+ If the location or the format is unsupported this will return a null pointer.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistIOPlugin::createWriter(QIODevice *device, const QByteArray &format)
+
+ Returns a new QMediaPlaylistWriter which writes \a format data to an I/O \a device.
+
+ If the device is invalid or the format is unsupported this will return a null pointer.
+ \since 1.0
+*/
+
+#include "moc_qmediaplaylistioplugin.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaplaylistioplugin.h b/src/multimediakit/qmediaplaylistioplugin.h
new file mode 100644
index 000000000..aa5f4fd95
--- /dev/null
+++ b/src/multimediakit/qmediaplaylistioplugin.h
@@ -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 QMEDIAPLAYLISTIOPLUGIN_H
+#define QMEDIAPLAYLISTIOPLUGIN_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+#include <qmobilityglobal.h>
+
+#include "qmediacontent.h"
+
+QT_BEGIN_NAMESPACE
+class QString;
+class QUrl;
+class QByteArray;
+class QIODevice;
+class QStringList;
+
+class Q_MULTIMEDIA_EXPORT QMediaPlaylistReader
+{
+public:
+ virtual ~QMediaPlaylistReader();
+
+ virtual bool atEnd() const = 0;
+ virtual QMediaContent readItem() = 0;
+ virtual void close() = 0;
+};
+
+class Q_MULTIMEDIA_EXPORT QMediaPlaylistWriter
+{
+public:
+ virtual ~QMediaPlaylistWriter();
+
+ virtual bool writeItem(const QMediaContent &content) = 0;
+ virtual void close() = 0;
+};
+
+struct Q_MULTIMEDIA_EXPORT QMediaPlaylistIOInterface : public QFactoryInterface
+{
+ virtual bool canRead(QIODevice *device, const QByteArray &format = QByteArray() ) const = 0;
+ virtual bool canRead(const QUrl& location, const QByteArray &format = QByteArray()) const = 0;
+
+ virtual bool canWrite(QIODevice *device, const QByteArray &format) const = 0;
+
+ virtual QMediaPlaylistReader *createReader(QIODevice *device, const QByteArray &format = QByteArray()) = 0;
+ virtual QMediaPlaylistReader *createReader(const QUrl& location, const QByteArray &format = QByteArray()) = 0;
+
+ virtual QMediaPlaylistWriter *createWriter(QIODevice *device, const QByteArray &format) = 0;
+};
+
+#define QMediaPlaylistIOInterface_iid "com.nokia.Qt.QMediaPlaylistIOInterface"
+Q_DECLARE_INTERFACE(QMediaPlaylistIOInterface, QMediaPlaylistIOInterface_iid);
+
+class Q_MULTIMEDIA_EXPORT QMediaPlaylistIOPlugin : public QObject, public QMediaPlaylistIOInterface
+{
+Q_OBJECT
+Q_INTERFACES(QMediaPlaylistIOInterface:QFactoryInterface)
+public:
+ explicit QMediaPlaylistIOPlugin(QObject *parent = 0);
+ virtual ~QMediaPlaylistIOPlugin();
+
+ virtual bool canRead(QIODevice *device, const QByteArray &format = QByteArray() ) const = 0;
+ virtual bool canRead(const QUrl& location, const QByteArray &format = QByteArray()) const = 0;
+
+ virtual bool canWrite(QIODevice *device, const QByteArray &format) const = 0;
+
+ virtual QStringList keys() const = 0;
+
+ virtual QMediaPlaylistReader *createReader(QIODevice *device, const QByteArray &format = QByteArray()) = 0;
+ virtual QMediaPlaylistReader *createReader(const QUrl& location, const QByteArray &format = QByteArray()) = 0;
+
+ virtual QMediaPlaylistWriter *createWriter(QIODevice *device, const QByteArray &format) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMEDIAPLAYLISTIOPLUGIN_H
diff --git a/src/multimediakit/qmediaplaylistnavigator.cpp b/src/multimediakit/qmediaplaylistnavigator.cpp
new file mode 100644
index 000000000..c3e358716
--- /dev/null
+++ b/src/multimediakit/qmediaplaylistnavigator.cpp
@@ -0,0 +1,568 @@
+/****************************************************************************
+**
+** 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 "qmediaplaylistnavigator.h"
+#include "qmediaplaylistprovider.h"
+#include "qmediaplaylist.h"
+#include "qmediaobject_p.h"
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMediaPlaylistNullProvider : public QMediaPlaylistProvider
+{
+public:
+ QMediaPlaylistNullProvider() :QMediaPlaylistProvider() {}
+ virtual ~QMediaPlaylistNullProvider() {}
+ virtual int mediaCount() const {return 0;}
+ virtual QMediaContent media(int) const { return QMediaContent(); }
+};
+
+Q_GLOBAL_STATIC(QMediaPlaylistNullProvider, _q_nullMediaPlaylist)
+
+class QMediaPlaylistNavigatorPrivate
+{
+ Q_DECLARE_NON_CONST_PUBLIC(QMediaPlaylistNavigator)
+public:
+ QMediaPlaylistNavigatorPrivate()
+ :playlist(0),
+ currentPos(-1),
+ lastValidPos(-1),
+ playbackMode(QMediaPlaylist::Sequential),
+ randomPositionsOffset(-1)
+ {
+ }
+
+ QMediaPlaylistProvider *playlist;
+ int currentPos;
+ int lastValidPos; //to be used with CurrentItemOnce playback mode
+ QMediaPlaylist::PlaybackMode playbackMode;
+ QMediaContent currentItem;
+
+ mutable QList<int> randomModePositions;
+ mutable int randomPositionsOffset;
+
+ int nextItemPos(int steps = 1) const;
+ int previousItemPos(int steps = 1) const;
+
+ void _q_mediaInserted(int start, int end);
+ void _q_mediaRemoved(int start, int end);
+ void _q_mediaChanged(int start, int end);
+
+ QMediaPlaylistNavigator *q_ptr;
+};
+
+
+int QMediaPlaylistNavigatorPrivate::nextItemPos(int steps) const
+{
+ if (playlist->mediaCount() == 0)
+ return -1;
+
+ if (steps == 0)
+ return currentPos;
+
+ switch (playbackMode) {
+ case QMediaPlaylist::CurrentItemOnce:
+ return /*currentPos == -1 ? lastValidPos :*/ -1;
+ case QMediaPlaylist::CurrentItemInLoop:
+ return currentPos;
+ case QMediaPlaylist::Sequential:
+ {
+ int nextPos = currentPos+steps;
+ return nextPos < playlist->mediaCount() ? nextPos : -1;
+ }
+ case QMediaPlaylist::Loop:
+ return (currentPos+steps) % playlist->mediaCount();
+ case QMediaPlaylist::Random:
+ {
+ //TODO: limit the history size
+
+ if (randomPositionsOffset == -1) {
+ randomModePositions.clear();
+ randomModePositions.append(currentPos);
+ randomPositionsOffset = 0;
+ }
+
+ while (randomModePositions.size() < randomPositionsOffset+steps+1)
+ randomModePositions.append(-1);
+ int res = randomModePositions[randomPositionsOffset+steps];
+ if (res<0 || res >= playlist->mediaCount()) {
+ res = qrand() % playlist->mediaCount();
+ randomModePositions[randomPositionsOffset+steps] = res;
+ }
+
+ return res;
+ }
+ }
+
+ return -1;
+}
+
+int QMediaPlaylistNavigatorPrivate::previousItemPos(int steps) const
+{
+ if (playlist->mediaCount() == 0)
+ return -1;
+
+ if (steps == 0)
+ return currentPos;
+
+ switch (playbackMode) {
+ case QMediaPlaylist::CurrentItemOnce:
+ return /*currentPos == -1 ? lastValidPos :*/ -1;
+ case QMediaPlaylist::CurrentItemInLoop:
+ return currentPos;
+ case QMediaPlaylist::Sequential:
+ {
+ int prevPos = currentPos == -1 ? playlist->mediaCount() - steps : currentPos - steps;
+ return prevPos>=0 ? prevPos : -1;
+ }
+ case QMediaPlaylist::Loop:
+ {
+ int prevPos = currentPos - steps;
+ while (prevPos<0)
+ prevPos += playlist->mediaCount();
+ return prevPos;
+ }
+ case QMediaPlaylist::Random:
+ {
+ //TODO: limit the history size
+
+ if (randomPositionsOffset == -1) {
+ randomModePositions.clear();
+ randomModePositions.append(currentPos);
+ randomPositionsOffset = 0;
+ }
+
+ while (randomPositionsOffset-steps < 0) {
+ randomModePositions.prepend(-1);
+ randomPositionsOffset++;
+ }
+
+ int res = randomModePositions[randomPositionsOffset-steps];
+ if (res<0 || res >= playlist->mediaCount()) {
+ res = qrand() % playlist->mediaCount();
+ randomModePositions[randomPositionsOffset-steps] = res;
+ }
+
+ return res;
+ }
+ }
+
+ return -1;
+}
+
+/*!
+ \class QMediaPlaylistNavigator
+
+ \brief The QMediaPlaylistNavigator class provides navigation for a media playlist.
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ \sa QMediaPlaylist, QMediaPlaylistProvider
+*/
+
+
+/*!
+ Constructs a media playlist navigator for a \a playlist.
+
+ The \a parent is passed to QObject.
+ \since 1.0
+ */
+QMediaPlaylistNavigator::QMediaPlaylistNavigator(QMediaPlaylistProvider *playlist, QObject *parent)
+ : QObject(parent)
+ , d_ptr(new QMediaPlaylistNavigatorPrivate)
+{
+ d_ptr->q_ptr = this;
+
+ setPlaylist(playlist ? playlist : _q_nullMediaPlaylist());
+}
+
+/*!
+ Destroys a media playlist navigator.
+ */
+
+QMediaPlaylistNavigator::~QMediaPlaylistNavigator()
+{
+ delete d_ptr;
+}
+
+
+/*! \property QMediaPlaylistNavigator::playbackMode
+ Contains the playback mode.
+ \since 1.0
+ */
+QMediaPlaylist::PlaybackMode QMediaPlaylistNavigator::playbackMode() const
+{
+ return d_func()->playbackMode;
+}
+
+/*!
+ Sets the playback \a mode.
+ \since 1.0
+ */
+void QMediaPlaylistNavigator::setPlaybackMode(QMediaPlaylist::PlaybackMode mode)
+{
+ Q_D(QMediaPlaylistNavigator);
+ if (d->playbackMode == mode)
+ return;
+
+ if (mode == QMediaPlaylist::Random) {
+ d->randomPositionsOffset = 0;
+ d->randomModePositions.append(d->currentPos);
+ } else if (d->playbackMode == QMediaPlaylist::Random) {
+ d->randomPositionsOffset = -1;
+ d->randomModePositions.clear();
+ }
+
+ d->playbackMode = mode;
+
+ emit playbackModeChanged(mode);
+ emit surroundingItemsChanged();
+}
+
+/*!
+ Returns the playlist being navigated.
+ \since 1.0
+*/
+
+QMediaPlaylistProvider *QMediaPlaylistNavigator::playlist() const
+{
+ return d_func()->playlist;
+}
+
+/*!
+ Sets the \a playlist to navigate.
+ \since 1.0
+*/
+void QMediaPlaylistNavigator::setPlaylist(QMediaPlaylistProvider *playlist)
+{
+ Q_D(QMediaPlaylistNavigator);
+
+ if (d->playlist == playlist)
+ return;
+
+ if (d->playlist) {
+ d->playlist->disconnect(this);
+ }
+
+ if (playlist) {
+ d->playlist = playlist;
+ } else {
+ //assign to shared readonly null playlist
+ d->playlist = _q_nullMediaPlaylist();
+ }
+
+ connect(d->playlist, SIGNAL(mediaInserted(int,int)), SLOT(_q_mediaInserted(int,int)));
+ connect(d->playlist, SIGNAL(mediaRemoved(int,int)), SLOT(_q_mediaRemoved(int,int)));
+ connect(d->playlist, SIGNAL(mediaChanged(int,int)), SLOT(_q_mediaChanged(int,int)));
+
+ d->randomPositionsOffset = -1;
+ d->randomModePositions.clear();
+
+ if (d->currentPos != -1) {
+ d->currentPos = -1;
+ emit currentIndexChanged(-1);
+ }
+
+ if (!d->currentItem.isNull()) {
+ d->currentItem = QMediaContent();
+ emit activated(d->currentItem); //stop playback
+ }
+}
+
+/*! \property QMediaPlaylistNavigator::currentItem
+
+ Contains the media at the current position in the playlist.
+
+ \since 1.0
+ \sa currentIndex()
+*/
+
+QMediaContent QMediaPlaylistNavigator::currentItem() const
+{
+ return itemAt(d_func()->currentPos);
+}
+
+/*! \fn QMediaContent QMediaPlaylistNavigator::nextItem(int steps) const
+
+ Returns the media that is \a steps positions ahead of the current
+ position in the playlist.
+
+ \since 1.0
+ \sa nextIndex()
+*/
+QMediaContent QMediaPlaylistNavigator::nextItem(int steps) const
+{
+ return itemAt(nextIndex(steps));
+}
+
+/*!
+ Returns the media that is \a steps positions behind the current
+ position in the playlist.
+
+ \since 1.0
+ \sa previousIndex()
+ */
+QMediaContent QMediaPlaylistNavigator::previousItem(int steps) const
+{
+ return itemAt(previousIndex(steps));
+}
+
+/*!
+ Returns the media at a \a position in the playlist.
+ \since 1.0
+ */
+QMediaContent QMediaPlaylistNavigator::itemAt(int position) const
+{
+ return d_func()->playlist->media(position);
+}
+
+/*! \property QMediaPlaylistNavigator::currentIndex
+
+ Contains the position of the current media.
+
+ If no media is current, the property contains -1.
+
+ \since 1.0
+ \sa nextIndex(), previousIndex()
+*/
+
+int QMediaPlaylistNavigator::currentIndex() const
+{
+ return d_func()->currentPos;
+}
+
+/*!
+ Returns a position \a steps ahead of the current position
+ accounting for the playbackMode().
+
+ If the position is beyond the end of the playlist, this value
+ returned is -1.
+
+ \since 1.0
+ \sa currentIndex(), previousIndex(), playbackMode()
+*/
+
+int QMediaPlaylistNavigator::nextIndex(int steps) const
+{
+ return d_func()->nextItemPos(steps);
+}
+
+/*!
+
+ Returns a position \a steps behind the current position accounting
+ for the playbackMode().
+
+ If the position is prior to the beginning of the playlist this will
+ return -1.
+
+ \since 1.0
+ \sa currentIndex(), nextIndex(), playbackMode()
+*/
+int QMediaPlaylistNavigator::previousIndex(int steps) const
+{
+ return d_func()->previousItemPos(steps);
+}
+
+/*!
+ Advances to the next item in the playlist.
+
+ \since 1.0
+ \sa previous(), jump(), playbackMode()
+ */
+void QMediaPlaylistNavigator::next()
+{
+ Q_D(QMediaPlaylistNavigator);
+
+ int nextPos = d->nextItemPos();
+
+ if ( playbackMode() == QMediaPlaylist::Random )
+ d->randomPositionsOffset++;
+
+ jump(nextPos);
+}
+
+/*!
+ Returns to the previous item in the playlist,
+
+ \since 1.0
+ \sa next(), jump(), playbackMode()
+ */
+void QMediaPlaylistNavigator::previous()
+{
+ Q_D(QMediaPlaylistNavigator);
+
+ int prevPos = d->previousItemPos();
+ if ( playbackMode() == QMediaPlaylist::Random )
+ d->randomPositionsOffset--;
+
+ jump(prevPos);
+}
+
+/*!
+ Jumps to a new \a position in the playlist.
+ \since 1.0
+ */
+void QMediaPlaylistNavigator::jump(int position)
+{
+ Q_D(QMediaPlaylistNavigator);
+
+ if (position<-1 || position>=d->playlist->mediaCount()) {
+ qWarning() << "QMediaPlaylistNavigator: Jump outside playlist range";
+ position = -1;
+ }
+
+ if (position != -1)
+ d->lastValidPos = position;
+
+ if (playbackMode() == QMediaPlaylist::Random) {
+ if (d->randomModePositions[d->randomPositionsOffset] != position) {
+ d->randomModePositions.clear();
+ d->randomModePositions.append(position);
+ d->randomPositionsOffset = 0;
+ }
+ }
+
+ if (position != -1)
+ d->currentItem = d->playlist->media(position);
+ else
+ d->currentItem = QMediaContent();
+
+ if (position != d->currentPos) {
+ d->currentPos = position;
+ emit currentIndexChanged(d->currentPos);
+ emit surroundingItemsChanged();
+ }
+
+ emit activated(d->currentItem);
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+void QMediaPlaylistNavigatorPrivate::_q_mediaInserted(int start, int end)
+{
+ Q_Q(QMediaPlaylistNavigator);
+
+ if (currentPos >= start) {
+ currentPos = end-start+1;
+ q->jump(currentPos);
+ }
+
+ //TODO: check if they really changed
+ emit q->surroundingItemsChanged();
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+void QMediaPlaylistNavigatorPrivate::_q_mediaRemoved(int start, int end)
+{
+ Q_Q(QMediaPlaylistNavigator);
+
+ if (currentPos > end) {
+ currentPos = currentPos - end-start+1;
+ q->jump(currentPos);
+ } else if (currentPos >= start) {
+ //current item was removed
+ currentPos = qMin(start, playlist->mediaCount()-1);
+ q->jump(currentPos);
+ }
+
+ //TODO: check if they really changed
+ emit q->surroundingItemsChanged();
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+void QMediaPlaylistNavigatorPrivate::_q_mediaChanged(int start, int end)
+{
+ Q_Q(QMediaPlaylistNavigator);
+
+ if (currentPos >= start && currentPos<=end) {
+ QMediaContent src = playlist->media(currentPos);
+ if (src != currentItem) {
+ currentItem = src;
+ emit q->activated(src);
+ }
+ }
+
+ //TODO: check if they really changed
+ emit q->surroundingItemsChanged();
+}
+
+/*!
+ \fn QMediaPlaylistNavigator::activated(const QMediaContent &media)
+
+ Signals that the current \a media has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistNavigator::currentIndexChanged(int position)
+
+ Signals the \a position of the current media has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistNavigator::playbackModeChanged(QMediaPlaylist::PlaybackMode mode)
+
+ Signals that the playback \a mode has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistNavigator::surroundingItemsChanged()
+
+ Signals that media immediately surrounding the current position has changed.
+ \since 1.0
+*/
+
+#include "moc_qmediaplaylistnavigator.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaplaylistnavigator.h b/src/multimediakit/qmediaplaylistnavigator.h
new file mode 100644
index 000000000..e19686a7a
--- /dev/null
+++ b/src/multimediakit/qmediaplaylistnavigator.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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 QMEDIAPLAYLISTNAVIGATOR_H
+#define QMEDIAPLAYLISTNAVIGATOR_H
+
+#include "qmediaplaylistprovider.h"
+#include "qmediaplaylist.h"
+#include <QtCore/qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMediaPlaylistNavigatorPrivate;
+class Q_MULTIMEDIA_EXPORT QMediaPlaylistNavigator : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QMediaPlaylist::PlaybackMode playbackMode READ playbackMode WRITE setPlaybackMode NOTIFY playbackModeChanged)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE jump NOTIFY currentIndexChanged)
+ Q_PROPERTY(QMediaContent currentItem READ currentItem)
+
+public:
+ QMediaPlaylistNavigator(QMediaPlaylistProvider *playlist, QObject *parent = 0);
+ virtual ~QMediaPlaylistNavigator();
+
+ QMediaPlaylistProvider *playlist() const;
+ void setPlaylist(QMediaPlaylistProvider *playlist);
+
+ QMediaPlaylist::PlaybackMode playbackMode() const;
+
+ QMediaContent currentItem() const;
+ QMediaContent nextItem(int steps = 1) const;
+ QMediaContent previousItem(int steps = 1) const;
+
+ QMediaContent itemAt(int position) const;
+
+ int currentIndex() const;
+ int nextIndex(int steps = 1) const;
+ int previousIndex(int steps = 1) const;
+
+public Q_SLOTS:
+ void next();
+ void previous();
+
+ void jump(int);
+
+ void setPlaybackMode(QMediaPlaylist::PlaybackMode mode);
+
+Q_SIGNALS:
+ void activated(const QMediaContent &content);
+ void currentIndexChanged(int);
+ void playbackModeChanged(QMediaPlaylist::PlaybackMode mode);
+
+ void surroundingItemsChanged();
+
+protected:
+ QMediaPlaylistNavigatorPrivate *d_ptr;
+
+private:
+ Q_DISABLE_COPY(QMediaPlaylistNavigator)
+ Q_DECLARE_PRIVATE(QMediaPlaylistNavigator)
+
+ Q_PRIVATE_SLOT(d_func(), void _q_mediaInserted(int start, int end))
+ Q_PRIVATE_SLOT(d_func(), void _q_mediaRemoved(int start, int end))
+ Q_PRIVATE_SLOT(d_func(), void _q_mediaChanged(int start, int end))
+};
+
+QT_END_NAMESPACE
+
+#endif // QMEDIAPLAYLISTNAVIGATOR_H
diff --git a/src/multimediakit/qmediaplaylistprovider.cpp b/src/multimediakit/qmediaplaylistprovider.cpp
new file mode 100644
index 000000000..5c892b79e
--- /dev/null
+++ b/src/multimediakit/qmediaplaylistprovider.cpp
@@ -0,0 +1,329 @@
+/****************************************************************************
+**
+** 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 "qmediaplaylistprovider.h"
+#include "qmediaplaylistprovider_p.h"
+
+#include <QtCore/qurl.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMediaPlaylistProvider
+
+ \brief The QMediaPlaylistProvider class provides an abstract list of media.
+ \inmodule QtMultimediaKit
+ \since 1.0
+
+ \sa QMediaPlaylist
+*/
+
+/*!
+ Constructs a playlist provider with the given \a parent.
+*/
+QMediaPlaylistProvider::QMediaPlaylistProvider(QObject *parent)
+ :QObject(parent), d_ptr(new QMediaPlaylistProviderPrivate)
+{
+}
+
+/*!
+ \internal
+*/
+QMediaPlaylistProvider::QMediaPlaylistProvider(QMediaPlaylistProviderPrivate &dd, QObject *parent)
+ :QObject(parent), d_ptr(&dd)
+{
+}
+
+/*!
+ Destroys a playlist provider.
+*/
+QMediaPlaylistProvider::~QMediaPlaylistProvider()
+{
+ delete d_ptr;
+}
+
+/*!
+ \fn QMediaPlaylistProvider::mediaCount() const;
+
+ Returns the size of playlist.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistProvider::media(int index) const;
+
+ Returns the media at \a index in the playlist.
+
+ If the index is invalid this will return a null media content.
+ \since 1.0
+*/
+
+
+/*!
+ Loads a playlist from from a URL \a location. If no playlist \a format is specified the loader
+ will inspect the URL or probe the headers to guess the format.
+
+ New items are appended to playlist.
+
+ Returns true if the provider supports the format and loading from the locations URL protocol,
+ otherwise this will return false.
+ \since 1.0
+*/
+bool QMediaPlaylistProvider::load(const QUrl &location, const char *format)
+{
+ Q_UNUSED(location);
+ Q_UNUSED(format);
+ return false;
+}
+
+/*!
+ Loads a playlist from from an I/O \a device. If no playlist \a format is specified the loader
+ will probe the headers to guess the format.
+
+ New items are appended to playlist.
+
+ Returns true if the provider supports the format and loading from an I/O device, otherwise this
+ will return false.
+ \since 1.0
+*/
+bool QMediaPlaylistProvider::load(QIODevice * device, const char *format)
+{
+ Q_UNUSED(device);
+ Q_UNUSED(format);
+ return false;
+}
+
+/*!
+ Saves the contents of a playlist to a URL \a location. If no playlist \a format is specified
+ the writer will inspect the URL to guess the format.
+
+ Returns true if the playlist was saved successfully; and false otherwise.
+ \since 1.0
+ */
+bool QMediaPlaylistProvider::save(const QUrl &location, const char *format)
+{
+ Q_UNUSED(location);
+ Q_UNUSED(format);
+ return false;
+}
+
+/*!
+ Saves the contents of a playlist to an I/O \a device in the specified \a format.
+
+ Returns true if the playlist was saved successfully; and false otherwise.
+ \since 1.0
+*/
+bool QMediaPlaylistProvider::save(QIODevice * device, const char *format)
+{
+ Q_UNUSED(device);
+ Q_UNUSED(format);
+ return false;
+}
+
+/*!
+ Returns true if a playlist is read-only; otherwise returns false.
+ \since 1.0
+*/
+bool QMediaPlaylistProvider::isReadOnly() const
+{
+ return true;
+}
+
+/*!
+ Append \a media to a playlist.
+
+ Returns true if the media was appended; and false otherwise.
+ \since 1.0
+*/
+bool QMediaPlaylistProvider::addMedia(const QMediaContent &media)
+{
+ Q_UNUSED(media);
+ return false;
+}
+
+/*!
+ Append multiple media \a items to a playlist.
+
+ Returns true if the media items were appended; and false otherwise.
+ \since 1.0
+*/
+bool QMediaPlaylistProvider::addMedia(const QList<QMediaContent> &items)
+{
+ foreach(const QMediaContent &item, items) {
+ if (!addMedia(item))
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ Inserts \a media into a playlist at \a position.
+
+ Returns true if the media was inserted; and false otherwise.
+ \since 1.0
+*/
+bool QMediaPlaylistProvider::insertMedia(int position, const QMediaContent &media)
+{
+ Q_UNUSED(position);
+ Q_UNUSED(media);
+ return false;
+}
+
+/*!
+ Inserts multiple media \a items into a playlist at \a position.
+
+ Returns true if the media \a items were inserted; and false otherwise.
+ \since 1.0
+*/
+bool QMediaPlaylistProvider::insertMedia(int position, const QList<QMediaContent> &items)
+{
+ for (int i=0; i<items.count(); i++) {
+ if (!insertMedia(position+i,items.at(i)))
+ return false;
+ }
+
+ return true;
+}
+
+
+/*!
+ Removes the media at \a position from a playlist.
+
+ Returns true if the media was removed; and false otherwise.
+ \since 1.0
+*/
+bool QMediaPlaylistProvider::removeMedia(int position)
+{
+ Q_UNUSED(position);
+ return false;
+}
+
+/*!
+ Removes the media between the given \a start and \a end positions from a playlist.
+
+ Returns true if the media was removed; and false otherwise.
+ \since 1.0
+ */
+bool QMediaPlaylistProvider::removeMedia(int start, int end)
+{
+ for (int pos=start; pos<=end; pos++) {
+ if (!removeMedia(pos))
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ Removes all media from a playlist.
+
+ Returns true if the media was removed; and false otherwise.
+ \since 1.0
+*/
+bool QMediaPlaylistProvider::clear()
+{
+ return removeMedia(0, mediaCount()-1);
+}
+
+/*!
+ Shuffles the contents of a playlist.
+ \since 1.0
+*/
+void QMediaPlaylistProvider::shuffle()
+{
+}
+
+/*!
+ \fn void QMediaPlaylistProvider::mediaAboutToBeInserted(int start, int end);
+
+ Signals that new media is about to be inserted into a playlist between the \a start and \a end
+ positions.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlaylistProvider::mediaInserted(int start, int end);
+
+ Signals that new media has been inserted into a playlist between the \a start and \a end
+ positions.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlaylistProvider::mediaAboutToBeRemoved(int start, int end);
+
+ Signals that media is about to be removed from a playlist between the \a start and \a end
+ positions.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlaylistProvider::mediaRemoved(int start, int end);
+
+ Signals that media has been removed from a playlist between the \a start and \a end positions.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlaylistProvider::mediaChanged(int start, int end);
+
+ Signals that media in playlist between the \a start and \a end positions inclusive has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlaylistProvider::loaded()
+
+ Signals that a load() finished successfully.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaPlaylistProvider::loadFailed(QMediaPlaylist::Error error, const QString& errorMessage)
+
+ Signals that a load failed() due to an \a error. The \a errorMessage provides more information.
+ \since 1.0
+*/
+
+#include "moc_qmediaplaylistprovider.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaplaylistprovider.h b/src/multimediakit/qmediaplaylistprovider.h
new file mode 100644
index 000000000..2fde87bc8
--- /dev/null
+++ b/src/multimediakit/qmediaplaylistprovider.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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 QMEDIAPLAYLISTPROVIDER_H
+#define QMEDIAPLAYLISTPROVIDER_H
+
+#include <QObject>
+
+#include "qmediacontent.h"
+#include "qmediaplaylist.h"
+
+QT_BEGIN_NAMESPACE
+class QString;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class QMediaPlaylistProviderPrivate;
+class Q_MULTIMEDIA_EXPORT QMediaPlaylistProvider : public QObject
+{
+Q_OBJECT
+public:
+ QMediaPlaylistProvider(QObject *parent=0);
+ virtual ~QMediaPlaylistProvider();
+
+ virtual bool load(const QUrl &location, const char *format = 0);
+ virtual bool load(QIODevice * device, const char *format = 0);
+ virtual bool save(const QUrl &location, const char *format = 0);
+ virtual bool save(QIODevice * device, const char *format);
+
+ virtual int mediaCount() const = 0;
+ virtual QMediaContent media(int index) const = 0;
+
+ virtual bool isReadOnly() const;
+
+ virtual bool addMedia(const QMediaContent &content);
+ virtual bool addMedia(const QList<QMediaContent> &contentList);
+ virtual bool insertMedia(int index, const QMediaContent &content);
+ virtual bool insertMedia(int index, const QList<QMediaContent> &content);
+ virtual bool removeMedia(int pos);
+ virtual bool removeMedia(int start, int end);
+ virtual bool clear();
+
+public Q_SLOTS:
+ virtual void shuffle();
+
+Q_SIGNALS:
+ void mediaAboutToBeInserted(int start, int end);
+ void mediaInserted(int start, int end);
+
+ void mediaAboutToBeRemoved(int start, int end);
+ void mediaRemoved(int start, int end);
+
+ void mediaChanged(int start, int end);
+
+ void loaded();
+ void loadFailed(QMediaPlaylist::Error, const QString& errorMessage);
+
+protected:
+ QMediaPlaylistProviderPrivate *d_ptr;
+ QMediaPlaylistProvider(QMediaPlaylistProviderPrivate &dd, QObject *parent);
+
+private:
+ Q_DECLARE_PRIVATE(QMediaPlaylistProvider)
+};
+
+QT_END_NAMESPACE
+
+#endif // QMEDIAPLAYLISTPROVIDER_H
diff --git a/src/multimediakit/qmediaplaylistprovider_p.h b/src/multimediakit/qmediaplaylistprovider_p.h
new file mode 100644
index 000000000..ded31a7b2
--- /dev/null
+++ b/src/multimediakit/qmediaplaylistprovider_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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 QMEDIAPLAYLISTPROVIDER_P_H
+#define QMEDIAPLAYLISTPROVIDER_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 "qmediaplaylist.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMediaPlaylistProviderPrivate
+{
+public:
+ QMediaPlaylistProviderPrivate()
+ {}
+ virtual ~QMediaPlaylistProviderPrivate()
+ {}
+};
+
+QT_END_NAMESPACE
+
+
+#endif // QMEDIAPLAYLISTSOURCE_P_H
diff --git a/src/multimediakit/qmediaplaylistsourcecontrol.cpp b/src/multimediakit/qmediaplaylistsourcecontrol.cpp
new file mode 100644
index 000000000..e8feaf07b
--- /dev/null
+++ b/src/multimediakit/qmediaplaylistsourcecontrol.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 <qmediaplaylistsourcecontrol.h>
+#include <qmediacontrol_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMediaPlaylistSourceControl
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+
+ \brief The QMediaPlaylistSourceControl class provides access to the playlist playback
+ functionality of a QMediaService.
+
+ This control allows QMediaPlaylist to be passed directly to the service
+ instead of playing media sources one by one. This control should be
+ implemented if backend benefits from knowing the next media source to be
+ played, for example for preloading, cross fading or gap-less playback.
+
+ If QMediaPlaylistSourceControl is provided, the backend must listen for
+ current playlist item changes to load corresponding media source and
+ advance the playlist with QMediaPlaylist::next() when playback of the
+ current media is finished.
+
+ The interface name of QMediaPlaylistSourceControl is \c com.nokia.Qt.QMediaPlaylistSourceControl/1.0 as
+ defined in QMediaPlaylistSourceControl_iid.
+
+ \sa QMediaService::requestControl(), QMediaPlayer
+*/
+
+/*!
+ \macro QMediaPlaylistSourceControl_iid
+
+ \c com.nokia.Qt.QMediaPlaylistSourceControl/1.0
+
+ Defines the interface name of the QMediaPlaylistSourceControl class.
+
+ \relates QMediaPlaylistSourceControl
+*/
+
+/*!
+ Create a new playlist source control object with the given \a parent.
+*/
+QMediaPlaylistSourceControl::QMediaPlaylistSourceControl(QObject *parent):
+ QMediaControl(*new QMediaControlPrivate, parent)
+{
+}
+
+/*!
+ Destroys the playlist control.
+*/
+QMediaPlaylistSourceControl::~QMediaPlaylistSourceControl()
+{
+}
+
+
+/*!
+ \fn QMediaPlaylistSourceControl::playlist() const
+
+ Returns the current playlist.
+ Should return a null pointer if no playlist is assigned.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaPlaylistSourceControl::setPlaylist(QMediaPlaylist *playlist)
+
+ Set the playlist of this media player to \a playlist.
+ If a null pointer is passed, the playlist source should be disabled.
+
+ The current media should be replaced with the current item of the media playlist.
+ \since 1.0
+*/
+
+
+/*!
+ \fn QMediaPlaylistSourceControl::playlistChanged(QMediaPlaylist* playlist)
+
+ Signal emitted when the playlist has changed to \a playlist.
+ \since 1.0
+*/
+
+#include "moc_qmediaplaylistsourcecontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaplaylistsourcecontrol.h b/src/multimediakit/qmediaplaylistsourcecontrol.h
new file mode 100644
index 000000000..d9b40392e
--- /dev/null
+++ b/src/multimediakit/qmediaplaylistsourcecontrol.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 QMEDIAPLAYLISTSOURCECONTROL_H
+#define QMEDIAPLAYLISTSOURCECONTROL_H
+
+#include <qmediacontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMediaPlaylist;
+
+class Q_MULTIMEDIA_EXPORT QMediaPlaylistSourceControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ virtual ~QMediaPlaylistSourceControl();
+
+ virtual QMediaPlaylist *playlist() const = 0;
+ virtual void setPlaylist(QMediaPlaylist *) = 0;
+
+Q_SIGNALS:
+ void playlistChanged(QMediaPlaylist* playlist);
+
+protected:
+ QMediaPlaylistSourceControl(QObject* parent = 0);
+};
+
+#define QMediaPlaylistSourceControl_iid "com.nokia.Qt.QMediaPlaylistSourceControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QMediaPlaylistSourceControl, QMediaPlaylistSourceControl_iid)
+
+QT_END_NAMESPACE
+
+#endif // QMEDIAPLAYLISTCONTROL_H
diff --git a/src/multimediakit/qmediapluginloader.cpp b/src/multimediakit/qmediapluginloader.cpp
new file mode 100644
index 000000000..5fa52ab10
--- /dev/null
+++ b/src/multimediakit/qmediapluginloader.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** 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 "qmediapluginloader_p.h"
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qpluginloader.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qdebug.h>
+
+#include "qmediaserviceproviderplugin.h"
+
+#if defined(Q_OS_SYMBIAN)
+# include <f32file.h>
+#endif
+
+#if defined(Q_OS_MAC)
+# include <CoreFoundation/CoreFoundation.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+typedef QMap<QString,QObjectList> ObjectListMap;
+Q_GLOBAL_STATIC(ObjectListMap, staticMediaPlugins);
+
+
+#if defined(Q_OS_SYMBIAN)
+// XXX: Copied over from Mobility, hopefully to be removed at some point
+class DirChecker
+{
+public:
+ DirChecker();
+ ~DirChecker();
+ bool checkDir(const QDir& dir);
+
+private:
+ RFs rfs;
+};
+
+DirChecker::DirChecker()
+{
+ qt_symbian_throwIfError(rfs.Connect());
+}
+
+bool DirChecker::checkDir(const QDir& dir)
+{
+ bool pathFound = false;
+ // In Symbian, going cdUp() in a c:/private/<uid3>/ will result in *platsec* error at fileserver (requires AllFiles capability)
+ // Also, trying to cd() to a nonexistent directory causes *platsec* error. This does not cause functional harm, but should
+ // nevertheless be changed to use native Symbian methods to avoid unnecessary platsec warnings (as per qpluginloader.cpp).
+ // Use native Symbian code to check for directory existence, because checking
+ // for files from under non-existent protected dir like E:/private/<uid> using
+ // QDir::exists causes platform security violations on most apps.
+ QString nativePath = QDir::toNativeSeparators(dir.absolutePath());
+ TPtrC ptr = TPtrC16(static_cast<const TUint16*>(nativePath.utf16()), nativePath.length());
+ TUint attributes;
+ TInt err = rfs.Att(ptr, attributes);
+ if (err == KErrNone) {
+ // yes, the directory exists.
+ pathFound = true;
+ }
+ return pathFound;
+}
+
+DirChecker::~DirChecker()
+{
+ rfs.Close();
+}
+#endif
+
+
+QMediaPluginLoader::QMediaPluginLoader(const char *iid, const QString &location, Qt::CaseSensitivity):
+ m_iid(iid)
+{
+ m_location = QString::fromLatin1("/%1").arg(location);
+ load();
+}
+
+QStringList QMediaPluginLoader::keys() const
+{
+ return m_instances.keys();
+}
+
+QObject* QMediaPluginLoader::instance(QString const &key)
+{
+ return m_instances.value(key).value(0);
+}
+
+QList<QObject*> QMediaPluginLoader::instances(QString const &key)
+{
+ return m_instances.value(key);
+}
+
+//to be used for testing purposes only
+void QMediaPluginLoader::setStaticPlugins(const QString &location, const QObjectList& objects)
+{
+ staticMediaPlugins()->insert(QString::fromLatin1("/%1").arg(location), objects);
+}
+
+QStringList QMediaPluginLoader::availablePlugins() const
+{
+ QStringList paths;
+ QStringList plugins;
+
+#if defined(Q_OS_SYMBIAN)
+ DirChecker dirChecker;
+#endif
+
+#if defined(Q_OS_MAC)
+ QString imageSuffix(qgetenv("DYLD_IMAGE_SUFFIX"));
+
+ // Bundle plugin directory
+ CFBundleRef mainBundle = CFBundleGetMainBundle();
+ if (mainBundle != 0) {
+ CFURLRef baseUrl = CFBundleCopyBundleURL(mainBundle);
+ CFURLRef pluginUrlPart = CFBundleCopyBuiltInPlugInsURL(mainBundle);
+ CFStringRef pluginPathPart = CFURLCopyFileSystemPath(pluginUrlPart, kCFURLPOSIXPathStyle);
+ CFURLRef pluginUrl = CFURLCreateCopyAppendingPathComponent(0, baseUrl, pluginPathPart, true);
+ CFStringRef pluginPath = CFURLCopyFileSystemPath(pluginUrl, kCFURLPOSIXPathStyle);
+
+ CFIndex length = CFStringGetLength(pluginPath);
+ UniChar buffer[length];
+ CFStringGetCharacters(pluginPath, CFRangeMake(0, length), buffer);
+
+ paths << QString(reinterpret_cast<const QChar *>(buffer), length);
+
+ CFRelease(pluginPath);
+ CFRelease(pluginUrl);
+ CFRelease(pluginPathPart);
+ CFRelease(pluginUrlPart);
+ CFRelease(baseUrl);
+ }
+#endif
+
+ // Qt paths
+ paths << QCoreApplication::libraryPaths();
+
+ foreach (const QString &path, paths) {
+ QDir typeDir(path + m_location);
+#if defined(Q_OS_SYMBIAN)
+ if (dirChecker.checkDir(typeDir))
+#endif
+ {
+ foreach (const QString &file, typeDir.entryList(QDir::Files)) {
+#if defined(Q_OS_MAC)
+ if (!imageSuffix.isEmpty()) { // Only add appropriate images
+ if (file.lastIndexOf(imageSuffix, -6) == -1)
+ continue;
+ } else { // Ignore any images with common suffixes
+ if (file.endsWith(QLatin1String("_debug.dylib")) ||
+ file.endsWith(QLatin1String("_profile.dylib")))
+ continue;
+ }
+#elif defined(Q_OS_UNIX)
+ // Ignore separate debug files
+ if (file.endsWith(QLatin1String(".debug")))
+ continue;
+#elif defined(Q_OS_WIN)
+ // Ignore non-dlls
+ if (!file.endsWith(QLatin1String(".dll"), Qt::CaseInsensitive))
+ continue;
+#endif
+ plugins << typeDir.absoluteFilePath(file);
+ }
+ }
+ }
+
+ return plugins;
+}
+
+void QMediaPluginLoader::load()
+{
+ if (!m_instances.isEmpty())
+ return;
+
+#if !defined QT_NO_DEBUG
+ const bool showDebug = qgetenv("QT_DEBUG_PLUGINS").toInt() > 0;
+#endif
+
+ if (staticMediaPlugins() && staticMediaPlugins()->contains(m_location)) {
+ foreach(QObject *o, staticMediaPlugins()->value(m_location)) {
+ if (o != 0 && o->qt_metacast(m_iid) != 0) {
+ QFactoryInterface* p = qobject_cast<QFactoryInterface*>(o);
+ if (p != 0) {
+ foreach (QString const &key, p->keys())
+ m_instances[key].append(o);
+ }
+ }
+ }
+ } else {
+ QSet<QString> loadedPlugins;
+
+ foreach (const QString &plugin, availablePlugins()) {
+ QString fileName = QFileInfo(plugin).fileName();
+ //don't try to load plugin with the same name if it's already loaded
+ if (loadedPlugins.contains(fileName)) {
+#if !defined QT_NO_DEBUG
+ if (showDebug)
+ qDebug() << "Skip loading plugin" << plugin;
+#endif
+ continue;
+ }
+
+ QPluginLoader loader(plugin);
+
+ QObject *o = loader.instance();
+ if (o != 0 && o->qt_metacast(m_iid) != 0) {
+ QFactoryInterface* p = qobject_cast<QFactoryInterface*>(o);
+ if (p != 0) {
+ foreach (const QString &key, p->keys())
+ m_instances[key].append(o);
+
+ loadedPlugins.insert(fileName);
+#if !defined QT_NO_DEBUG
+ if (showDebug)
+ qDebug() << "Loaded plugin" << plugin << "services:" << p->keys();
+#endif
+ }
+
+ continue;
+ } else {
+#if !defined QT_NO_DEBUG
+ if (showDebug)
+ qWarning() << "QMediaPluginLoader: Failed to load plugin: " << plugin << loader.errorString();
+#endif
+ }
+
+ delete o;
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediapluginloader_p.h b/src/multimediakit/qmediapluginloader_p.h
new file mode 100644
index 000000000..eef395a33
--- /dev/null
+++ b/src/multimediakit/qmediapluginloader_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QMEDIAPLUGINLOADER_H
+#define QMEDIAPLUGINLOADER_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/qstring.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QMediaServiceProviderPlugin;
+
+class Q_AUTOTEST_EXPORT QMediaPluginLoader
+{
+public:
+ QMediaPluginLoader(const char *iid,
+ const QString &suffix = QString(),
+ Qt::CaseSensitivity = Qt::CaseSensitive);
+
+ QStringList keys() const;
+ QObject* instance(QString const &key);
+ QList<QObject*> instances(QString const &key);
+
+ static void setStaticPlugins(const QString &location, const QObjectList& objects);
+
+private:
+ void load();
+ QStringList availablePlugins() const;
+
+ QByteArray m_iid;
+ QString m_location;
+ QMap<QString, QList<QObject *> > m_instances;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMEDIAPLUGINLOADER_H
diff --git a/src/multimediakit/qmediarecorder.cpp b/src/multimediakit/qmediarecorder.cpp
new file mode 100644
index 000000000..1b5601249
--- /dev/null
+++ b/src/multimediakit/qmediarecorder.cpp
@@ -0,0 +1,899 @@
+/****************************************************************************
+**
+** 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 "qmediarecorder.h"
+
+#include <qmediarecordercontrol.h>
+#include <qmediaobject_p.h>
+#include <qmediaservice.h>
+#include <qmediaserviceprovider.h>
+#include <qmetadatawritercontrol.h>
+#include <qaudioencodercontrol.h>
+#include <qvideoencodercontrol.h>
+#include <qmediacontainercontrol.h>
+#include <qcamera.h>
+#include <qcameracontrol.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmetaobject.h>
+
+#include <qaudioformat.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMediaRecorder
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+
+ \brief The QMediaRecorder class is used for the recording of media content.
+
+ The QMediaRecorder class is a high level media recording class. It's not
+ intended to be used alone but for accessing the media recording functions
+ of other media objects, like QRadioTuner, or QAudioCaptureSource.
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Media recorder
+
+ \sa QAudioCaptureSource
+*/
+
+namespace
+{
+class MediaRecorderRegisterMetaTypes
+{
+public:
+ MediaRecorderRegisterMetaTypes()
+ {
+ qRegisterMetaType<QMediaRecorder::State>("QMediaRecorder::State");
+ qRegisterMetaType<QMediaRecorder::Error>("QMediaRecorder::Error");
+ }
+} _registerRecorderMetaTypes;
+}
+
+
+class QMediaRecorderPrivate
+{
+ Q_DECLARE_NON_CONST_PUBLIC(QMediaRecorder)
+
+public:
+ QMediaRecorderPrivate();
+
+ QMediaObject *mediaObject;
+
+ QMediaRecorderControl *control;
+ QMediaContainerControl *formatControl;
+ QAudioEncoderControl *audioControl;
+ QVideoEncoderControl *videoControl;
+ QMetaDataWriterControl *metaDataControl;
+
+ QTimer* notifyTimer;
+
+ QMediaRecorder::State state;
+ QMediaRecorder::Error error;
+ QString errorString;
+
+ void _q_stateChanged(QMediaRecorder::State state);
+ void _q_error(int error, const QString &errorString);
+ void _q_serviceDestroyed();
+ void _q_notify();
+ void _q_updateNotifyInterval(int ms);
+
+ QMediaRecorder *q_ptr;
+};
+
+QMediaRecorderPrivate::QMediaRecorderPrivate():
+ mediaObject(0),
+ control(0),
+ formatControl(0),
+ audioControl(0),
+ videoControl(0),
+ metaDataControl(0),
+ notifyTimer(0),
+ state(QMediaRecorder::StoppedState),
+ error(QMediaRecorder::NoError)
+{
+}
+
+#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
+
+void QMediaRecorderPrivate::_q_stateChanged(QMediaRecorder::State ps)
+{
+ Q_Q(QMediaRecorder);
+
+ if (ps == QMediaRecorder::RecordingState)
+ notifyTimer->start();
+ else
+ notifyTimer->stop();
+
+// qDebug() << "Recorder state changed:" << ENUM_NAME(QMediaRecorder,"State",ps);
+ if (state != ps) {
+ emit q->stateChanged(ps);
+ }
+
+ state = ps;
+}
+
+
+void QMediaRecorderPrivate::_q_error(int error, const QString &errorString)
+{
+ Q_Q(QMediaRecorder);
+
+ this->error = QMediaRecorder::Error(error);
+ this->errorString = errorString;
+
+ emit q->error(this->error);
+}
+
+void QMediaRecorderPrivate::_q_serviceDestroyed()
+{
+ q_func()->setMediaObject(0);
+}
+
+void QMediaRecorderPrivate::_q_notify()
+{
+ emit q_func()->durationChanged(q_func()->duration());
+}
+
+void QMediaRecorderPrivate::_q_updateNotifyInterval(int ms)
+{
+ notifyTimer->setInterval(ms);
+}
+
+
+/*!
+ Constructs a media recorder which records the media produced by \a mediaObject.
+
+ The \a parent is passed to QMediaObject.
+ \since 1.0
+*/
+
+QMediaRecorder::QMediaRecorder(QMediaObject *mediaObject, QObject *parent):
+ QObject(parent),
+ d_ptr(new QMediaRecorderPrivate)
+{
+ Q_D(QMediaRecorder);
+ d->q_ptr = this;
+ setMediaObject(mediaObject);
+
+ d->notifyTimer = new QTimer(this);
+ d->notifyTimer->setInterval(mediaObject->notifyInterval());
+ connect(d->notifyTimer, SIGNAL(timeout()), SLOT(_q_notify()));
+ connect(mediaObject, SIGNAL(notifyIntervalChanged(int)), SLOT(_q_updateNotifyInterval(int)));
+}
+
+/*!
+ Destroys a media recorder object.
+*/
+
+QMediaRecorder::~QMediaRecorder()
+{
+}
+
+/*!
+ Returns the QMediaObject instance that this QMediaRecorder is bound too,
+ or 0 otherwise.
+ \since 1.0
+*/
+QMediaObject *QMediaRecorder::mediaObject() const
+{
+ return d_func()->mediaObject;
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+bool QMediaRecorder::setMediaObject(QMediaObject *object)
+{
+ Q_D(QMediaRecorder);
+
+ if (object == d->mediaObject)
+ return true;
+
+ if (d->mediaObject) {
+ if (d->control) {
+ disconnect(d->control, SIGNAL(stateChanged(QMediaRecorder::State)),
+ this, SLOT(_q_stateChanged(QMediaRecorder::State)));
+
+ disconnect(d->control, SIGNAL(mutedChanged(bool)),
+ this, SIGNAL(mutedChanged(bool)));
+
+ disconnect(d->control, SIGNAL(durationChanged(qint64)),
+ this, SIGNAL(durationChanged(qint64)));
+
+ disconnect(d->control, SIGNAL(error(int,QString)),
+ this, SLOT(_q_error(int,QString)));
+ }
+
+ QMediaService *service = d->mediaObject->service();
+
+ if (service) {
+ disconnect(service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed()));
+
+ if (d->control)
+ service->releaseControl(d->control);
+ if (d->formatControl)
+ service->releaseControl(d->formatControl);
+ if (d->audioControl)
+ service->releaseControl(d->audioControl);
+ if (d->videoControl)
+ service->releaseControl(d->videoControl);
+ if (d->metaDataControl) {
+ disconnect(d->metaDataControl, SIGNAL(metaDataChanged()),
+ this, SIGNAL(metaDataChanged()));
+ disconnect(d->metaDataControl, SIGNAL(metaDataAvailableChanged(bool)),
+ this, SIGNAL(metaDataAvailableChanged(bool)));
+ disconnect(d->metaDataControl, SIGNAL(writableChanged(bool)),
+ this, SIGNAL(metaDataWritableChanged(bool)));
+
+ service->releaseControl(d->metaDataControl);
+ }
+ }
+ }
+
+ d->control = 0;
+ d->formatControl = 0;
+ d->audioControl = 0;
+ d->videoControl = 0;
+ d->metaDataControl = 0;
+
+ d->mediaObject = object;
+
+ if (d->mediaObject) {
+ QMediaService *service = d->mediaObject->service();
+
+ if (service) {
+ d->control = qobject_cast<QMediaRecorderControl*>(service->requestControl(QMediaRecorderControl_iid));
+
+ if (d->control) {
+ d->formatControl = qobject_cast<QMediaContainerControl *>(service->requestControl(QMediaContainerControl_iid));
+ d->audioControl = qobject_cast<QAudioEncoderControl *>(service->requestControl(QAudioEncoderControl_iid));
+ d->videoControl = qobject_cast<QVideoEncoderControl *>(service->requestControl(QVideoEncoderControl_iid));
+
+ QMediaControl *control = service->requestControl(QMetaDataWriterControl_iid);
+ if (control) {
+ d->metaDataControl = qobject_cast<QMetaDataWriterControl *>(control);
+ if (!d->metaDataControl) {
+ service->releaseControl(control);
+ } else {
+ connect(d->metaDataControl,
+ SIGNAL(metaDataChanged()),
+ SIGNAL(metaDataChanged()));
+ connect(d->metaDataControl,
+ SIGNAL(metaDataAvailableChanged(bool)),
+ SIGNAL(metaDataAvailableChanged(bool)));
+ connect(d->metaDataControl,
+ SIGNAL(writableChanged(bool)),
+ SIGNAL(metaDataWritableChanged(bool)));
+ }
+ }
+
+ connect(d->control, SIGNAL(stateChanged(QMediaRecorder::State)),
+ this, SLOT(_q_stateChanged(QMediaRecorder::State)));
+
+ connect(d->control, SIGNAL(mutedChanged(bool)),
+ this, SIGNAL(mutedChanged(bool)));
+
+ connect(d->control, SIGNAL(durationChanged(qint64)),
+ this, SIGNAL(durationChanged(qint64)));
+
+ connect(d->control, SIGNAL(error(int,QString)),
+ this, SLOT(_q_error(int,QString)));
+
+ connect(service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed()));
+
+
+ return true;
+ }
+ }
+
+ d->mediaObject = 0;
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \property QMediaRecorder::outputLocation
+ \brief the destination location of media content.
+
+ Setting the location can fail, for example when the service supports only
+ local file system locations but a network URL was passed. If the service
+ does not support media recording this setting the output location will
+ always fail.
+
+ The \a location can be relative or empty;
+ in this case the recorder uses the system specific place and file naming scheme.
+ After recording has stated, QMediaRecorder::outputLocation() returns the actual output location.
+ \since 1.0
+*/
+
+/*!
+ Returns true if media recorder service ready to use.
+ \since 1.0
+*/
+bool QMediaRecorder::isAvailable() const
+{
+ if (d_func()->control != NULL)
+ return true;
+ else
+ return false;
+}
+
+/*!
+ Returns the availability error code.
+ \since 1.0
+*/
+QtMultimediaKit::AvailabilityError QMediaRecorder::availabilityError() const
+{
+ if (d_func()->control != NULL)
+ return QtMultimediaKit::NoError;
+ else
+ return QtMultimediaKit::ServiceMissingError;
+}
+
+QUrl QMediaRecorder::outputLocation() const
+{
+ return d_func()->control ? d_func()->control->outputLocation() : QUrl();
+}
+
+bool QMediaRecorder::setOutputLocation(const QUrl &location)
+{
+ Q_D(QMediaRecorder);
+ return d->control ? d->control->setOutputLocation(location) : false;
+}
+
+/*!
+ Returns the current media recorder state.
+
+ \since 1.0
+ \sa QMediaRecorder::State
+*/
+
+QMediaRecorder::State QMediaRecorder::state() const
+{
+ return d_func()->control ? QMediaRecorder::State(d_func()->control->state()) : StoppedState;
+}
+
+/*!
+ Returns the current error state.
+
+ \since 1.0
+ \sa errorString()
+*/
+
+QMediaRecorder::Error QMediaRecorder::error() const
+{
+ return d_func()->error;
+}
+
+/*!
+ Returns a string describing the current error state.
+
+ \since 1.0
+ \sa error()
+*/
+
+QString QMediaRecorder::errorString() const
+{
+ return d_func()->errorString;
+}
+
+/*!
+ \property QMediaRecorder::duration
+
+ \brief the recorded media duration in milliseconds.
+ \since 1.0
+*/
+
+qint64 QMediaRecorder::duration() const
+{
+ return d_func()->control ? d_func()->control->duration() : 0;
+}
+
+/*!
+ \property QMediaRecorder::muted
+
+ \brief whether a recording audio stream is muted.
+ \since 1.0
+*/
+
+bool QMediaRecorder::isMuted() const
+{
+ return d_func()->control ? d_func()->control->isMuted() : 0;
+}
+
+void QMediaRecorder::setMuted(bool muted)
+{
+ Q_D(QMediaRecorder);
+
+ if (d->control)
+ d->control->setMuted(muted);
+}
+
+/*!
+ Returns a list of MIME types of supported container formats.
+ \since 1.0
+*/
+QStringList QMediaRecorder::supportedContainers() const
+{
+ return d_func()->formatControl ?
+ d_func()->formatControl->supportedContainers() : QStringList();
+}
+
+/*!
+ Returns a description of a container format \a mimeType.
+ \since 1.0
+*/
+QString QMediaRecorder::containerDescription(const QString &mimeType) const
+{
+ return d_func()->formatControl ?
+ d_func()->formatControl->containerDescription(mimeType) : QString();
+}
+
+/*!
+ Returns the MIME type of the selected container format.
+ \since 1.0
+*/
+
+QString QMediaRecorder::containerMimeType() const
+{
+ return d_func()->formatControl ?
+ d_func()->formatControl->containerMimeType() : QString();
+}
+
+/*!
+ Returns a list of supported audio codecs.
+ \since 1.0
+*/
+QStringList QMediaRecorder::supportedAudioCodecs() const
+{
+ return d_func()->audioControl ?
+ d_func()->audioControl->supportedAudioCodecs() : QStringList();
+}
+
+/*!
+ Returns a description of an audio \a codec.
+ \since 1.0
+*/
+QString QMediaRecorder::audioCodecDescription(const QString &codec) const
+{
+ return d_func()->audioControl ?
+ d_func()->audioControl->codecDescription(codec) : QString();
+}
+
+/*!
+ Returns a list of supported audio sample rates.
+
+ If non null audio \a settings parameter is passed, the returned list is
+ reduced to sample rates supported with partial settings applied.
+
+ This can be used to query the list of sample rates, supported by specific
+ audio codec.
+
+ If the encoder supports arbitrary sample rates within the supported rates
+ range, *\a continuous is set to true, otherwise *\a continuous is set to
+ false.
+ \since 1.0
+*/
+
+QList<int> QMediaRecorder::supportedAudioSampleRates(const QAudioEncoderSettings &settings, bool *continuous) const
+{
+ if (continuous)
+ *continuous = false;
+
+ return d_func()->audioControl ?
+ d_func()->audioControl->supportedSampleRates(settings, continuous) : QList<int>();
+}
+
+/*!
+ Returns a list of resolutions video can be encoded at.
+
+ If non null video \a settings parameter is passed, the returned list is
+ reduced to resolution supported with partial settings like video codec or
+ framerate applied.
+
+ If the encoder supports arbitrary resolutions within the supported range,
+ *\a continuous is set to true, otherwise *\a continuous is set to false.
+
+ \since 1.0
+ \sa QVideoEncoderSettings::resolution()
+*/
+QList<QSize> QMediaRecorder::supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous) const
+{
+ if (continuous)
+ *continuous = false;
+
+ return d_func()->videoControl ?
+ d_func()->videoControl->supportedResolutions(settings, continuous) : QList<QSize>();
+}
+
+/*!
+ Returns a list of frame rates video can be encoded at.
+
+ If non null video \a settings parameter is passed, the returned list is
+ reduced to frame rates supported with partial settings like video codec or
+ resolution applied.
+
+ If the encoder supports arbitrary frame rates within the supported range,
+ *\a continuous is set to true, otherwise *\a continuous is set to false.
+
+ \since 1.0
+ \sa QVideoEncoderSettings::frameRate()
+*/
+QList<qreal> QMediaRecorder::supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const
+{
+ if (continuous)
+ *continuous = false;
+
+ return d_func()->videoControl ?
+ d_func()->videoControl->supportedFrameRates(settings, continuous) : QList<qreal>();
+}
+
+/*!
+ Returns a list of supported video codecs.
+ \since 1.0
+*/
+QStringList QMediaRecorder::supportedVideoCodecs() const
+{
+ return d_func()->videoControl ?
+ d_func()->videoControl->supportedVideoCodecs() : QStringList();
+}
+
+/*!
+ Returns a description of a video \a codec.
+
+ \since 1.0
+ \sa setEncodingSettings()
+*/
+QString QMediaRecorder::videoCodecDescription(const QString &codec) const
+{
+ return d_func()->videoControl ?
+ d_func()->videoControl->videoCodecDescription(codec) : QString();
+}
+
+/*!
+ Returns the audio encoder settings being used.
+
+ \since 1.0
+ \sa setEncodingSettings()
+*/
+
+QAudioEncoderSettings QMediaRecorder::audioSettings() const
+{
+ return d_func()->audioControl ?
+ d_func()->audioControl->audioSettings() : QAudioEncoderSettings();
+}
+
+/*!
+ Returns the video encoder settings being used.
+
+ \since 1.0
+ \sa setEncodingSettings()
+*/
+
+QVideoEncoderSettings QMediaRecorder::videoSettings() const
+{
+ return d_func()->videoControl ?
+ d_func()->videoControl->videoSettings() : QVideoEncoderSettings();
+}
+
+/*!
+ Sets the \a audio and \a video encoder settings and \a container format MIME type.
+
+ If some parameters are not specified, or null settings are passed, the
+ encoder will choose default encoding parameters, depending on media
+ source properties.
+ While setEncodingSettings is optional, the backend can preload
+ encoding pipeline to improve recording startup time.
+
+ It's only possible to change settings when the encoder is in the
+ QMediaEncoder::StoppedState state.
+
+ \since 1.0
+ \sa audioSettings(), videoSettings(), containerMimeType()
+*/
+
+void QMediaRecorder::setEncodingSettings(const QAudioEncoderSettings &audio,
+ const QVideoEncoderSettings &video,
+ const QString &container)
+{
+ Q_D(QMediaRecorder);
+
+ QCamera *camera = qobject_cast<QCamera*>(d->mediaObject);
+ if (camera && camera->captureMode() == QCamera::CaptureVideo) {
+ QMetaObject::invokeMethod(camera,
+ "_q_preparePropertyChange",
+ Qt::DirectConnection,
+ Q_ARG(int, QCameraControl::VideoEncodingSettings));
+ }
+
+ if (d->audioControl)
+ d->audioControl->setAudioSettings(audio);
+
+ if (d->videoControl)
+ d->videoControl->setVideoSettings(video);
+
+ if (d->formatControl)
+ d->formatControl->setContainerMimeType(container);
+
+ if (d->control)
+ d->control->applySettings();
+}
+
+
+/*!
+ Start recording.
+
+ This is an asynchronous call, with signal
+ stateCahnged(QMediaRecorder::RecordingState) being emitted when recording
+ started, otherwise the error() signal is emitted.
+ \since 1.0
+*/
+
+void QMediaRecorder::record()
+{
+ Q_D(QMediaRecorder);
+
+ // reset error
+ d->error = NoError;
+ d->errorString = QString();
+
+ if (d->control)
+ d->control->record();
+}
+
+/*!
+ Pause recording.
+ \since 1.0
+*/
+
+void QMediaRecorder::pause()
+{
+ Q_D(QMediaRecorder);
+ if (d->control)
+ d->control->pause();
+}
+
+/*!
+ Stop recording.
+ \since 1.0
+*/
+
+void QMediaRecorder::stop()
+{
+ Q_D(QMediaRecorder);
+ if (d->control)
+ d->control->stop();
+}
+
+/*!
+ \enum QMediaRecorder::State
+
+ \value StoppedState The recorder is not active.
+ \value RecordingState The recorder is currently active and producing data.
+ \value PausedState The recorder is paused.
+*/
+
+/*!
+ \enum QMediaRecorder::Error
+
+ \value NoError No Errors.
+ \value ResourceError Device is not ready or not available.
+ \value FormatError Current format is not supported.
+*/
+
+/*!
+ \fn QMediaRecorder::stateChanged(State state)
+
+ Signals that a media recorder's \a state has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaRecorder::durationChanged(qint64 duration)
+
+ Signals that the \a duration of the recorded media has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaRecorder::error(QMediaRecorder::Error error)
+
+ Signals that an \a error has occurred.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaRecorder::mutedChanged(bool muted)
+
+ Signals that the \a muted state has changed. If true the recording is being muted.
+ \since 1.0
+*/
+
+/*!
+ \property QMediaRecorder::metaDataAvailable
+ \brief whether access to a media object's meta-data is available.
+
+ If this is true there is meta-data available, otherwise there is no meta-data available.
+ \since 1.0
+*/
+
+bool QMediaRecorder::isMetaDataAvailable() const
+{
+ Q_D(const QMediaRecorder);
+
+ return d->metaDataControl
+ ? d->metaDataControl->isMetaDataAvailable()
+ : false;
+}
+
+/*!
+ \fn QMediaRecorder::metaDataAvailableChanged(bool available)
+
+ Signals that the \a available state of a media object's meta-data has changed.
+ \since 1.0
+*/
+
+/*!
+ \property QMediaRecorder::metaDataWritable
+ \brief whether a media object's meta-data is writable.
+
+ If this is true the meta-data is writable, otherwise the meta-data is read-only.
+ \since 1.0
+*/
+
+bool QMediaRecorder::isMetaDataWritable() const
+{
+ Q_D(const QMediaRecorder);
+
+ return d->metaDataControl
+ ? d->metaDataControl->isWritable()
+ : false;
+}
+
+/*!
+ \fn QMediaRecorder::metaDataWritableChanged(bool writable)
+
+ Signals that the \a writable state of a media object's meta-data has changed.
+ \since 1.0
+*/
+
+/*!
+ Returns the value associated with a meta-data \a key.
+ \since 1.0
+*/
+QVariant QMediaRecorder::metaData(QtMultimediaKit::MetaData key) const
+{
+ Q_D(const QMediaRecorder);
+
+ return d->metaDataControl
+ ? d->metaDataControl->metaData(key)
+ : QVariant();
+}
+
+/*!
+ Sets a \a value for a meta-data \a key.
+
+ \note To ensure that meta data is set corretly, it should be set before starting the recording.
+ Once the recording is stopped, any meta data set will be attached to the next recording.
+ \since 1.0
+*/
+void QMediaRecorder::setMetaData(QtMultimediaKit::MetaData key, const QVariant &value)
+{
+ Q_D(QMediaRecorder);
+
+ if (d->metaDataControl)
+ d->metaDataControl->setMetaData(key, value);
+}
+
+/*!
+ Returns a list of keys there is meta-data available for.
+ \since 1.0
+*/
+QList<QtMultimediaKit::MetaData> QMediaRecorder::availableMetaData() const
+{
+ Q_D(const QMediaRecorder);
+
+ return d->metaDataControl
+ ? d->metaDataControl->availableMetaData()
+ : QList<QtMultimediaKit::MetaData>();
+}
+
+/*!
+ \fn QMediaRecorder::metaDataChanged()
+
+ Signals that a media object's meta-data has changed.
+ \since 1.0
+*/
+
+/*!
+ Returns the value associated with a meta-data \a key.
+
+ The naming and type of extended meta-data is not standardized, so the values and meaning
+ of keys may vary between backends.
+ \since 1.0
+*/
+QVariant QMediaRecorder::extendedMetaData(const QString &key) const
+{
+ Q_D(const QMediaRecorder);
+
+ return d->metaDataControl
+ ? d->metaDataControl->extendedMetaData(key)
+ : QVariant();
+}
+
+/*!
+ Sets a \a value for a meta-data \a key.
+
+ The naming and type of extended meta-data is not standardized, so the values and meaning
+ of keys may vary between backends.
+ \since 1.0
+*/
+void QMediaRecorder::setExtendedMetaData(const QString &key, const QVariant &value)
+{
+ Q_D(QMediaRecorder);
+
+ if (d->metaDataControl)
+ d->metaDataControl->setExtendedMetaData(key, value);
+}
+
+/*!
+ Returns a list of keys there is extended meta-data available for.
+ \since 1.0
+*/
+QStringList QMediaRecorder::availableExtendedMetaData() const
+{
+ Q_D(const QMediaRecorder);
+
+ return d->metaDataControl
+ ? d->metaDataControl->availableExtendedMetaData()
+ : QStringList();
+}
+
+#include "moc_qmediarecorder.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediarecorder.h b/src/multimediakit/qmediarecorder.h
new file mode 100644
index 000000000..4f5d6fd69
--- /dev/null
+++ b/src/multimediakit/qmediarecorder.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** 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 QMEDIARECORDER_H
+#define QMEDIARECORDER_H
+
+#include <qmediaobject.h>
+#include <qmediaserviceprovider.h>
+#include <qmediaencodersettings.h>
+#include <qmediabindableinterface.h>
+#include <qmediaenumdebug.h>
+
+#include <QtCore/qpair.h>
+
+QT_BEGIN_NAMESPACE
+class QUrl;
+class QSize;
+class QAudioFormat;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class QMediaRecorderService;
+class QAudioEncoderSettings;
+class QVideoEncoderSettings;
+
+class QMediaRecorderPrivate;
+class Q_MULTIMEDIA_EXPORT QMediaRecorder : public QObject, public QMediaBindableInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaBindableInterface)
+ Q_ENUMS(State)
+ Q_ENUMS(Error)
+ Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged)
+ Q_PROPERTY(QUrl outputLocation READ outputLocation WRITE setOutputLocation)
+ Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
+ Q_PROPERTY(bool metaDataAvailable READ isMetaDataAvailable NOTIFY metaDataAvailableChanged)
+ Q_PROPERTY(bool metaDataWritable READ isMetaDataWritable NOTIFY metaDataWritableChanged)
+public:
+
+ enum State
+ {
+ StoppedState,
+ RecordingState,
+ PausedState
+ };
+
+ enum Error
+ {
+ NoError,
+ ResourceError,
+ FormatError
+ };
+
+ QMediaRecorder(QMediaObject *mediaObject, QObject *parent = 0);
+ ~QMediaRecorder();
+
+ QMediaObject *mediaObject() const;
+
+ bool isAvailable() const;
+ QtMultimediaKit::AvailabilityError availabilityError() const;
+
+ QUrl outputLocation() const;
+ bool setOutputLocation(const QUrl &location);
+
+ State state() const;
+
+ Error error() const;
+ QString errorString() const;
+
+ qint64 duration() const;
+
+ bool isMuted() const;
+
+ QStringList supportedContainers() const;
+ QString containerDescription(const QString &containerMimeType) const;
+
+ QStringList supportedAudioCodecs() const;
+ QString audioCodecDescription(const QString &codecName) const;
+
+ QList<int> supportedAudioSampleRates(const QAudioEncoderSettings &settings = QAudioEncoderSettings(),
+ bool *continuous = 0) const;
+
+ QStringList supportedVideoCodecs() const;
+ QString videoCodecDescription(const QString &codecName) const;
+
+ QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings = QVideoEncoderSettings(),
+ bool *continuous = 0) const;
+
+ QList<qreal> supportedFrameRates(const QVideoEncoderSettings &settings = QVideoEncoderSettings(),
+ bool *continuous = 0) const;
+
+ QAudioEncoderSettings audioSettings() const;
+ QVideoEncoderSettings videoSettings() const;
+ QString containerMimeType() const;
+
+ void setEncodingSettings(const QAudioEncoderSettings &audioSettings,
+ const QVideoEncoderSettings &videoSettings = QVideoEncoderSettings(),
+ const QString &containerMimeType = QString());
+
+
+ bool isMetaDataAvailable() const;
+ bool isMetaDataWritable() const;
+
+ QVariant metaData(QtMultimediaKit::MetaData key) const;
+ void setMetaData(QtMultimediaKit::MetaData key, const QVariant &value);
+ QList<QtMultimediaKit::MetaData> availableMetaData() const;
+
+ QVariant extendedMetaData(const QString &key) const;
+ void setExtendedMetaData(const QString &key, const QVariant &value);
+ QStringList availableExtendedMetaData() const;
+
+public Q_SLOTS:
+ void record();
+ void pause();
+ void stop();
+ void setMuted(bool muted);
+
+Q_SIGNALS:
+ void stateChanged(QMediaRecorder::State state);
+ void durationChanged(qint64 duration);
+ void mutedChanged(bool muted);
+
+ void error(QMediaRecorder::Error error);
+
+ void metaDataAvailableChanged(bool available);
+ void metaDataWritableChanged(bool writable);
+ void metaDataChanged();
+
+protected:
+ bool setMediaObject(QMediaObject *object);
+
+private:
+ QMediaRecorderPrivate *d_ptr;
+ Q_DISABLE_COPY(QMediaRecorder)
+ Q_DECLARE_PRIVATE(QMediaRecorder)
+ Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(QMediaRecorder::State))
+ Q_PRIVATE_SLOT(d_func(), void _q_error(int, const QString &))
+ Q_PRIVATE_SLOT(d_func(), void _q_serviceDestroyed())
+ Q_PRIVATE_SLOT(d_func(), void _q_notify())
+ Q_PRIVATE_SLOT(d_func(), void _q_updateNotifyInterval(int))
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QMediaRecorder::State)
+Q_DECLARE_METATYPE(QMediaRecorder::Error)
+
+Q_MEDIA_ENUM_DEBUG(QMediaRecorder, State)
+Q_MEDIA_ENUM_DEBUG(QMediaRecorder, Error)
+
+#endif // QMEDIARECORDER_H
diff --git a/src/multimediakit/qmediarecordercontrol.cpp b/src/multimediakit/qmediarecordercontrol.cpp
new file mode 100644
index 000000000..2b88ee9ef
--- /dev/null
+++ b/src/multimediakit/qmediarecordercontrol.cpp
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** 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 "qmediarecordercontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ \class QMediaRecorderControl
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+
+ \brief The QMediaRecorderControl class provides access to the recording
+ functionality of a QMediaService.
+
+ If a QMediaService can record media it will implement QMediaRecorderControl.
+ This control provides a means to set the \l {outputLocation()}{output location},
+ and \l {record()}{start}, \l {pause()}{pause} and \l {stop()}{stop}
+ recording. It also provides feedback on the \l {duration()}{duration}
+ of the recording.
+
+ The functionality provided by this control is exposed to application
+ code through the QMediaRecorder class.
+
+ The interface name of QMediaRecorderControl is \c com.nokia.Qt.QMediaRecorderControl/1.0 as
+ defined in QMediaRecorderControl_iid.
+
+ \sa QMediaService::requestControl(), QMediaRecorder
+
+*/
+
+/*!
+ \macro QMediaRecorderControl_iid
+
+ \c com.nokia.Qt.QMediaRecorderControl/1.0
+
+ Defines the interface name of the QMediaRecorderControl class.
+
+ \relates QMediaRecorderControl
+*/
+
+/*!
+ Constructs a media recorder control with the given \a parent.
+*/
+
+QMediaRecorderControl::QMediaRecorderControl(QObject* parent)
+ : QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys a media recorder control.
+*/
+
+QMediaRecorderControl::~QMediaRecorderControl()
+{
+}
+
+/*!
+ \fn QUrl QMediaRecorderControl::outputLocation() const
+
+ Returns the current output location being used.
+ \since 1.0
+*/
+
+/*!
+ \fn bool QMediaRecorderControl::setOutputLocation(const QUrl &location)
+
+ Sets the output \a location and returns if this operation is successful.
+ If file at the output location already exists, it should be overwritten.
+
+ The \a location can be relative or empty;
+ in this case the service should use the system specific place and file naming scheme.
+ After recording has stated, QMediaRecorderControl::outputLocation() should return the actual output location.
+ \since 1.0
+*/
+
+/*!
+ \fn int QMediaRecorderControl::state() const
+
+ Return the current recording state.
+ \since 1.0
+*/
+
+/*!
+ \fn qint64 QMediaRecorderControl::duration() const
+
+ Return the current duration in milliseconds.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaRecorderControl::record()
+
+ Start recording.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaRecorderControl::pause()
+
+ Pause recording.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaRecorderControl::stop()
+
+ Stop recording.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaRecorderControl::applySettings()
+
+ Commits the encoder settings and performs pre-initialization to reduce delays when recording
+ is started.
+ \since 1.0
+*/
+
+/*!
+ \fn bool QMediaRecorderControl::isMuted() const
+
+ Returns true if the recorder is muted, and false if it is not.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaRecorderControl::setMuted(bool muted)
+
+ Sets the \a muted state of a media recorder.
+ \since 1.0
+*/
+
+
+/*!
+ \fn void QMediaRecorderControl::stateChanged(QMediaRecorder::State state)
+
+ Signals that the \a state of a media recorder has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaRecorderControl::durationChanged(qint64 duration)
+
+ Signals that the \a duration of the recorded media has changed.
+
+ This only emitted when there is a discontinuous change in the duration such as being reset to 0.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaRecorderControl::mutedChanged(bool muted)
+
+ Signals that the \a muted state of a media recorder has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaRecorderControl::error(int error, const QString &errorString)
+
+ Signals that an \a error has occurred. The \a errorString describes the error.
+ \since 1.0
+*/
+
+#include "moc_qmediarecordercontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediarecordercontrol.h b/src/multimediakit/qmediarecordercontrol.h
new file mode 100644
index 000000000..bc5bf71be
--- /dev/null
+++ b/src/multimediakit/qmediarecordercontrol.h
@@ -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 QMEDIARECORDERCONTROL_H
+#define QMEDIARECORDERCONTROL_H
+
+#include "qmediacontrol.h"
+#include "qmediarecorder.h"
+
+QT_BEGIN_NAMESPACE
+class QUrl;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QMediaRecorderControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ virtual ~QMediaRecorderControl();
+
+ virtual QUrl outputLocation() const = 0;
+ virtual bool setOutputLocation(const QUrl &location) = 0;
+
+ virtual QMediaRecorder::State state() const = 0;
+
+ virtual qint64 duration() const = 0;
+
+ virtual bool isMuted() const = 0;
+
+ virtual void applySettings() = 0;
+
+Q_SIGNALS:
+ void stateChanged(QMediaRecorder::State state);
+ void durationChanged(qint64 position);
+ void mutedChanged(bool muted);
+ void error(int error, const QString &errorString);
+
+public Q_SLOTS:
+ virtual void record() = 0;
+ virtual void pause() = 0;
+ virtual void stop() = 0;
+ virtual void setMuted(bool muted) = 0;
+
+protected:
+ QMediaRecorderControl(QObject* parent = 0);
+};
+
+#define QMediaRecorderControl_iid "com.nokia.Qt.QMediaRecorderControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QMediaRecorderControl, QMediaRecorderControl_iid)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qmediaresource.cpp b/src/multimediakit/qmediaresource.cpp
new file mode 100644
index 000000000..a0dddb103
--- /dev/null
+++ b/src/multimediakit/qmediaresource.cpp
@@ -0,0 +1,440 @@
+/****************************************************************************
+**
+** 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 "qmediaresource.h"
+
+#include <QtCore/qsize.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMediaResource
+
+ \brief The QMediaResource class provides a description of a media resource.
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ A media resource is composed of a \l {url()}{URL} containing the
+ location of the resource and a set of properties that describe the
+ format of the resource. The properties provide a means to assess a
+ resource without first attempting to load it, and in situations where
+ media be represented by multiple alternative representations provide a
+ means to select the appropriate resource.
+
+ Media made available by a remote services can often be available in
+ multiple encodings or quality levels, this allows a client to select
+ an appropriate resource based on considerations such as codecs supported,
+ network bandwidth, and display constraints. QMediaResource includes
+ information such as the \l {mimeType()}{MIME type}, \l {audioCodec()}{audio}
+ and \l {videoCodec()}{video} codecs, \l {audioBitRate()}{audio} and
+ \l {videoBitRate()}{video} bit rates, and \l {resolution()}{resolution}
+ so these constraints and others can be evaluated.
+
+ The only mandatory property of a QMediaResource is the url().
+
+ \sa QMediaContent
+*/
+
+/*!
+ \typedef QMediaResourceList
+
+ Synonym for \c QList<QMediaResource>
+*/
+
+/*!
+ Constructs a null media resource.
+*/
+QMediaResource::QMediaResource()
+{
+}
+
+/*!
+ Constructs a media resource with the given \a mimeType from a \a url.
+ \since 1.0
+*/
+QMediaResource::QMediaResource(const QUrl &url, const QString &mimeType)
+{
+ values.insert(Url, url);
+ values.insert(MimeType, mimeType);
+}
+
+/*!
+ Constructs a media resource with the given \a mimeType from a network \a request.
+ \since 1.0
+*/
+QMediaResource::QMediaResource(const QNetworkRequest &request, const QString &mimeType)
+{
+ values.insert(Request, QVariant::fromValue(request));
+ values.insert(Url, request.url());
+ values.insert(MimeType, mimeType);
+}
+
+/*!
+ Constructs a copy of a media resource \a other.
+ \since 1.0
+*/
+QMediaResource::QMediaResource(const QMediaResource &other)
+ : values(other.values)
+{
+}
+
+/*!
+ Assigns the value of \a other to a media resource.
+ \since 1.0
+*/
+QMediaResource &QMediaResource::operator =(const QMediaResource &other)
+{
+ values = other.values;
+
+ return *this;
+}
+
+/*!
+ Destroys a media resource.
+*/
+QMediaResource::~QMediaResource()
+{
+}
+
+
+/*!
+ Compares a media resource to \a other.
+
+ Returns true if the resources are identical, and false otherwise.
+ \since 1.0
+*/
+bool QMediaResource::operator ==(const QMediaResource &other) const
+{
+ // Compare requests directly as QNetworkRequests are "custom types".
+ foreach (int key, values.keys()) {
+ switch (key) {
+ case Request:
+ if (request() != other.request())
+ return false;
+ break;
+ default:
+ if (values.value(key) != other.values.value(key))
+ return false;
+ }
+ }
+ return true;
+}
+
+/*!
+ Compares a media resource to \a other.
+
+ Returns true if they are different, and false otherwise.
+ \since 1.0
+*/
+bool QMediaResource::operator !=(const QMediaResource &other) const
+{
+ return !(*this == other);
+}
+
+/*!
+ Identifies if a media resource is null.
+
+ Returns true if the resource is null, and false otherwise.
+ \since 1.0
+*/
+bool QMediaResource::isNull() const
+{
+ return values.isEmpty();
+}
+
+/*!
+ Returns the URL of a media resource.
+ \since 1.0
+*/
+QUrl QMediaResource::url() const
+{
+ return qvariant_cast<QUrl>(values.value(Url));
+}
+
+/*!
+ Returns the network request associated with this media resource.
+ \since 1.0
+*/
+QNetworkRequest QMediaResource::request() const
+{
+ if(values.contains(Request))
+ return qvariant_cast<QNetworkRequest>(values.value(Request));
+
+ return QNetworkRequest(url());
+}
+
+/*!
+ Returns the MIME type of a media resource.
+
+ This may be null if the MIME type is unknown.
+ \since 1.0
+*/
+QString QMediaResource::mimeType() const
+{
+ return qvariant_cast<QString>(values.value(MimeType));
+}
+
+/*!
+ Returns the language of a media resource as an ISO 639-2 code.
+
+ This may be null if the language is unknown.
+ \since 1.0
+*/
+QString QMediaResource::language() const
+{
+ return qvariant_cast<QString>(values.value(Language));
+}
+
+/*!
+ Sets the \a language of a media resource.
+ \since 1.0
+*/
+void QMediaResource::setLanguage(const QString &language)
+{
+ if (!language.isNull())
+ values.insert(Language, language);
+ else
+ values.remove(Language);
+}
+
+/*!
+ Returns the audio codec of a media resource.
+
+ This may be null if the media resource does not contain an audio stream, or the codec is
+ unknown.
+ \since 1.0
+*/
+QString QMediaResource::audioCodec() const
+{
+ return qvariant_cast<QString>(values.value(AudioCodec));
+}
+
+/*!
+ Sets the audio \a codec of a media resource.
+ \since 1.0
+*/
+void QMediaResource::setAudioCodec(const QString &codec)
+{
+ if (!codec.isNull())
+ values.insert(AudioCodec, codec);
+ else
+ values.remove(AudioCodec);
+}
+
+/*!
+ Returns the video codec of a media resource.
+
+ This may be null if the media resource does not contain a video stream, or the codec is
+ unknonwn.
+ \since 1.0
+*/
+QString QMediaResource::videoCodec() const
+{
+ return qvariant_cast<QString>(values.value(VideoCodec));
+}
+
+/*!
+ Sets the video \a codec of media resource.
+ \since 1.0
+*/
+void QMediaResource::setVideoCodec(const QString &codec)
+{
+ if (!codec.isNull())
+ values.insert(VideoCodec, codec);
+ else
+ values.remove(VideoCodec);
+}
+
+/*!
+ Returns the size in bytes of a media resource.
+
+ This may be zero if the size is unknown.
+ \since 1.0
+*/
+qint64 QMediaResource::dataSize() const
+{
+ return qvariant_cast<qint64>(values.value(DataSize));
+}
+
+/*!
+ Sets the \a size in bytes of a media resource.
+ \since 1.0
+*/
+void QMediaResource::setDataSize(const qint64 size)
+{
+ if (size != 0)
+ values.insert(DataSize, size);
+ else
+ values.remove(DataSize);
+}
+
+/*!
+ Returns the bit rate in bits per second of a media resource's audio stream.
+
+ This may be zero if the bit rate is unknown, or the resource contains no audio stream.
+ \since 1.0
+*/
+int QMediaResource::audioBitRate() const
+{
+ return values.value(AudioBitRate).toInt();
+}
+
+/*!
+ Sets the bit \a rate in bits per second of a media resource's video stream.
+ \since 1.0
+*/
+void QMediaResource::setAudioBitRate(int rate)
+{
+ if (rate != 0)
+ values.insert(AudioBitRate, rate);
+ else
+ values.remove(AudioBitRate);
+}
+
+/*!
+ Returns the audio sample rate of a media resource.
+
+ This may be zero if the sample size is unknown, or the resource contains no audio stream.
+ \since 1.0
+*/
+int QMediaResource::sampleRate() const
+{
+ return qvariant_cast<int>(values.value(SampleRate));
+}
+
+/*!
+ Sets the audio \a sampleRate of a media resource.
+ \since 1.0
+*/
+void QMediaResource::setSampleRate(int sampleRate)
+{
+ if (sampleRate != 0)
+ values.insert(SampleRate, sampleRate);
+ else
+ values.remove(SampleRate);
+}
+
+/*!
+ Returns the number of audio channels in a media resource.
+
+ This may be zero if the sample size is unknown, or the resource contains no audio stream.
+ \since 1.0
+*/
+int QMediaResource::channelCount() const
+{
+ return qvariant_cast<int>(values.value(ChannelCount));
+}
+
+/*!
+ Sets the number of audio \a channels in a media resource.
+ \since 1.0
+*/
+void QMediaResource::setChannelCount(int channels)
+{
+ if (channels != 0)
+ values.insert(ChannelCount, channels);
+ else
+ values.remove(ChannelCount);
+}
+
+/*!
+ Returns the bit rate in bits per second of a media resource's video stream.
+
+ This may be zero if the bit rate is unknown, or the resource contains no video stream.
+ \since 1.0
+*/
+int QMediaResource::videoBitRate() const
+{
+ return values.value(VideoBitRate).toInt();
+}
+
+/*!
+ Sets the bit \a rate in bits per second of a media resource's video stream.
+ \since 1.0
+*/
+void QMediaResource::setVideoBitRate(int rate)
+{
+ if (rate != 0)
+ values.insert(VideoBitRate, rate);
+ else
+ values.remove(VideoBitRate);
+}
+
+/*!
+ Returns the resolution in pixels of a media resource.
+
+ This may be null is the resolution is unknown, or the resource contains no pixel data (i.e. the
+ resource is an audio stream.
+ \since 1.0
+*/
+QSize QMediaResource::resolution() const
+{
+ return qvariant_cast<QSize>(values.value(Resolution));
+}
+
+/*!
+ Sets the \a resolution in pixels of a media resource.
+ \since 1.0
+*/
+void QMediaResource::setResolution(const QSize &resolution)
+{
+ if (resolution.width() != -1 || resolution.height() != -1)
+ values.insert(Resolution, resolution);
+ else
+ values.remove(Resolution);
+}
+
+/*!
+ Sets the \a width and \a height in pixels of a media resource.
+ \since 1.0
+*/
+void QMediaResource::setResolution(int width, int height)
+{
+ if (width != -1 || height != -1)
+ values.insert(Resolution, QSize(width, height));
+ else
+ values.remove(Resolution);
+}
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaresource.h b/src/multimediakit/qmediaresource.h
new file mode 100644
index 000000000..0dd930cc2
--- /dev/null
+++ b/src/multimediakit/qmediaresource.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** 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 QMEDIARESOURCE_H
+#define QMEDIARESOURCE_H
+
+#include <QtCore/qmap.h>
+#include <QtCore/qmetatype.h>
+#include <QtNetwork/qnetworkrequest.h>
+
+#include <qmobilityglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QMediaResource
+{
+public:
+ QMediaResource();
+ QMediaResource(const QUrl &url, const QString &mimeType = QString());
+ QMediaResource(const QNetworkRequest &request, const QString &mimeType = QString());
+ QMediaResource(const QMediaResource &other);
+ QMediaResource &operator =(const QMediaResource &other);
+ ~QMediaResource();
+
+ bool isNull() const;
+
+ bool operator ==(const QMediaResource &other) const;
+ bool operator !=(const QMediaResource &other) const;
+
+ QUrl url() const;
+ QNetworkRequest request() const;
+ QString mimeType() const;
+
+ QString language() const;
+ void setLanguage(const QString &language);
+
+ QString audioCodec() const;
+ void setAudioCodec(const QString &codec);
+
+ QString videoCodec() const;
+ void setVideoCodec(const QString &codec);
+
+ qint64 dataSize() const;
+ void setDataSize(const qint64 size);
+
+ int audioBitRate() const;
+ void setAudioBitRate(int rate);
+
+ int sampleRate() const;
+ void setSampleRate(int frequency);
+
+ int channelCount() const;
+ void setChannelCount(int channels);
+
+ int videoBitRate() const;
+ void setVideoBitRate(int rate);
+
+ QSize resolution() const;
+ void setResolution(const QSize &resolution);
+ void setResolution(int width, int height);
+
+
+private:
+ enum Property
+ {
+ Url,
+ Request,
+ MimeType,
+ Language,
+ AudioCodec,
+ VideoCodec,
+ DataSize,
+ AudioBitRate,
+ VideoBitRate,
+ SampleRate,
+ ChannelCount,
+ Resolution
+ };
+ QMap<int, QVariant> values;
+};
+
+typedef QList<QMediaResource> QMediaResourceList;
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QMediaResource)
+Q_DECLARE_METATYPE(QMediaResourceList)
+
+
+#endif
diff --git a/src/multimediakit/qmediaservice.cpp b/src/multimediakit/qmediaservice.cpp
new file mode 100644
index 000000000..6ea6fa20c
--- /dev/null
+++ b/src/multimediakit/qmediaservice.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** 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 "qmediaservice.h"
+#include "qmediaservice_p.h"
+
+#include <QtCore/qtimer.h>
+
+
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ \class QMediaService
+ \brief The QMediaService class provides a common base class for media
+ service implementations.
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+
+ Media services provide implementations of the functionality promised
+ by media objects, and allow multiple providers to implement a QMediaObject.
+
+ To provide the functionality of a QMediaObject media services implement
+ QMediaControl interfaces. Services typically implement one core media
+ control which provides the core feature of a media object, and some
+ number of additional controls which provide either optional features of
+ the media object, or features of a secondary media object or peripheral
+ object.
+
+ A pointer to media service's QMediaControl implementation can be obtained
+ by passing the control's interface name to the requestControl() function.
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Request control
+
+ Media objects can use services loaded dynamically from plug-ins or
+ implemented statically within an applications. Plug-in based services
+ should also implement the QMediaServiceProviderPlugin interface. Static
+ services should implement the QMediaServiceProvider interface.
+
+ \sa QMediaObject, QMediaControl, QMediaServiceProvider, QMediaServiceProviderPlugin
+*/
+
+/*!
+ Construct a media service with the given \a parent. This class is meant as a
+ base class for Multimedia services so this constructor is protected.
+*/
+
+QMediaService::QMediaService(QObject *parent)
+ : QObject(parent)
+ , d_ptr(new QMediaServicePrivate)
+{
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ \internal
+*/
+QMediaService::QMediaService(QMediaServicePrivate &dd, QObject *parent)
+ : QObject(parent)
+ , d_ptr(&dd)
+{
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ Destroys a media service.
+*/
+
+QMediaService::~QMediaService()
+{
+ delete d_ptr;
+}
+
+/*!
+ \fn QMediaControl* QMediaService::requestControl(const char *interface)
+
+ Returns a pointer to the media control implementing \a interface.
+
+ If the service does not implement the control, or if it is unavailable a
+ null pointer is returned instead.
+
+ Controls must be returned to the service when no longer needed using the
+ releaseControl() function.
+ \since 1.0
+*/
+
+/*!
+ \fn T QMediaService::requestControl()
+
+ Returns a pointer to the media control of type T implemented by a media service.
+
+ If the service does not implement the control, or if it is unavailable a
+ null pointer is returned instead.
+
+ Controls must be returned to the service when no longer needed using the
+ releaseControl() function.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMediaService::releaseControl(QMediaControl *control);
+
+ Releases a \a control back to the service.
+ \since 1.0
+*/
+
+#include "moc_qmediaservice.cpp"
+
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaservice.h b/src/multimediakit/qmediaservice.h
new file mode 100644
index 000000000..57ae3bba3
--- /dev/null
+++ b/src/multimediakit/qmediaservice.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** 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 QABSTRACTMEDIASERVICE_H
+#define QABSTRACTMEDIASERVICE_H
+
+#include <qmobilityglobal.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qstringlist.h>
+
+#include "qmediacontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMediaServicePrivate;
+class Q_MULTIMEDIA_EXPORT QMediaService : public QObject
+{
+ Q_OBJECT
+
+public:
+ ~QMediaService();
+
+ virtual QMediaControl* requestControl(const char *name) = 0;
+
+#ifndef QT_NO_MEMBER_TEMPLATES
+ template <typename T> inline T requestControl() {
+ if (QMediaControl *control = requestControl(qmediacontrol_iid<T>())) {
+ if (T typedControl = qobject_cast<T>(control))
+ return typedControl;
+ releaseControl(control);
+ }
+ return 0;
+ }
+#endif
+
+ virtual void releaseControl(QMediaControl *control) = 0;
+
+protected:
+ QMediaService(QObject* parent);
+ QMediaService(QMediaServicePrivate &dd, QObject *parent);
+
+ QMediaServicePrivate *d_ptr;
+
+private:
+ Q_DECLARE_PRIVATE(QMediaService)
+};
+
+QT_END_NAMESPACE
+
+#endif // QABSTRACTMEDIASERVICE_H
+
diff --git a/src/multimediakit/qmediaservice_p.h b/src/multimediakit/qmediaservice_p.h
new file mode 100644
index 000000000..37eac75ca
--- /dev/null
+++ b/src/multimediakit/qmediaservice_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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 QABSTRACTMEDIASERVICE_P_H
+#define QABSTRACTMEDIASERVICE_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.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QAudioDeviceControl;
+
+class QMediaServicePrivate
+{
+public:
+ QMediaServicePrivate(): q_ptr(0) {}
+ virtual ~QMediaServicePrivate() {}
+
+ QMediaService *q_ptr;
+};
+
+QT_END_NAMESPACE
+
+
+#endif
diff --git a/src/multimediakit/qmediaserviceprovider.cpp b/src/multimediakit/qmediaserviceprovider.cpp
new file mode 100644
index 000000000..74db5a2e0
--- /dev/null
+++ b/src/multimediakit/qmediaserviceprovider.cpp
@@ -0,0 +1,780 @@
+/****************************************************************************
+**
+** 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 <QtCore/qmap.h>
+
+#include "qmediaservice.h"
+#include "qmediaserviceprovider.h"
+#include "qmediaserviceproviderplugin.h"
+#include "qmediapluginloader_p.h"
+#include "qmediaplayer.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMediaServiceProviderHintPrivate : public QSharedData
+{
+public:
+ QMediaServiceProviderHintPrivate(QMediaServiceProviderHint::Type type)
+ :type(type), features(0)
+ {
+ }
+
+ QMediaServiceProviderHintPrivate(const QMediaServiceProviderHintPrivate &other)
+ :QSharedData(other),
+ type(other.type),
+ device(other.device),
+ mimeType(other.mimeType),
+ codecs(other.codecs),
+ features(other.features)
+ {
+ }
+
+ ~QMediaServiceProviderHintPrivate()
+ {
+ }
+
+ QMediaServiceProviderHint::Type type;
+ QByteArray device;
+ QString mimeType;
+ QStringList codecs;
+ QMediaServiceProviderHint::Features features;
+};
+
+/*!
+ \class QMediaServiceProviderHint
+
+ \brief The QMediaServiceProviderHint class describes what is required of a QMediaService.
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ The QMediaServiceProvider class uses hints to select an appropriate media service.
+*/
+
+/*!
+ \enum QMediaServiceProviderHint::Feature
+
+ Enumerates features a media service may provide.
+
+ \value LowLatencyPlayback
+ The service is expected to play simple audio formats,
+ but playback should start without significant delay.
+ Such playback service can be used for beeps, ringtones, etc.
+
+ \value RecordingSupport
+ The service provides audio or video recording functions.
+
+ \value StreamPlayback
+ The service is capable of playing QIODevice based streams.
+
+ \value VideoSurface
+ The service is capable of renderering to a QAbstractVideoSurface
+ output.
+*/
+
+/*!
+ \enum QMediaServiceProviderHint::Type
+
+ Enumerates the possible types of media service provider hint.
+
+ \value Null En empty hint, use the default service.
+ \value ContentType Select media service most suitable for certain content type.
+ \value Device Select media service which supports certain device.
+ \value SupportedFeatures Select media service supporting the set of optional features.
+*/
+
+
+/*!
+ Constructs an empty media service provider hint.
+*/
+QMediaServiceProviderHint::QMediaServiceProviderHint()
+ :d(new QMediaServiceProviderHintPrivate(Null))
+{
+}
+
+/*!
+ Constructs a ContentType media service provider hint.
+
+ This type of hint describes a service that is able to play content of a specific MIME \a type
+ encoded with one or more of the listed \a codecs.
+ \since 1.0
+*/
+QMediaServiceProviderHint::QMediaServiceProviderHint(const QString &type, const QStringList& codecs)
+ :d(new QMediaServiceProviderHintPrivate(ContentType))
+{
+ d->mimeType = type;
+ d->codecs = codecs;
+}
+
+/*!
+ Constructs a Device media service provider hint.
+
+ This type of hint describes a media service that utilizes a specific \a device.
+ \since 1.0
+*/
+QMediaServiceProviderHint::QMediaServiceProviderHint(const QByteArray &device)
+ :d(new QMediaServiceProviderHintPrivate(Device))
+{
+ d->device = device;
+}
+
+/*!
+ Constructs a SupportedFeatures media service provider hint.
+
+ This type of hint describes a service which supports a specific set of \a features.
+ \since 1.0
+*/
+QMediaServiceProviderHint::QMediaServiceProviderHint(QMediaServiceProviderHint::Features features)
+ :d(new QMediaServiceProviderHintPrivate(SupportedFeatures))
+{
+ d->features = features;
+}
+
+/*!
+ Constructs a copy of the media service provider hint \a other.
+ \since 1.0
+*/
+QMediaServiceProviderHint::QMediaServiceProviderHint(const QMediaServiceProviderHint &other)
+ :d(other.d)
+{
+}
+
+/*!
+ Destroys a media service provider hint.
+*/
+QMediaServiceProviderHint::~QMediaServiceProviderHint()
+{
+}
+
+/*!
+ Assigns the value \a other to a media service provider hint.
+ \since 1.0
+*/
+QMediaServiceProviderHint& QMediaServiceProviderHint::operator=(const QMediaServiceProviderHint &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Identifies if \a other is of equal value to a media service provider hint.
+
+ Returns true if the hints are equal, and false if they are not.
+ \since 1.0
+*/
+bool QMediaServiceProviderHint::operator == (const QMediaServiceProviderHint &other) const
+{
+ return (d == other.d) ||
+ (d->type == other.d->type &&
+ d->device == other.d->device &&
+ d->mimeType == other.d->mimeType &&
+ d->codecs == other.d->codecs &&
+ d->features == other.d->features);
+}
+
+/*!
+ Identifies if \a other is not of equal value to a media service provider hint.
+
+ Returns true if the hints are not equal, and false if they are.
+ \since 1.0
+*/
+bool QMediaServiceProviderHint::operator != (const QMediaServiceProviderHint &other) const
+{
+ return !(*this == other);
+}
+
+/*!
+ Returns true if a media service provider is null.
+ \since 1.0
+*/
+bool QMediaServiceProviderHint::isNull() const
+{
+ return d->type == Null;
+}
+
+/*!
+ Returns the type of a media service provider hint.
+ \since 1.0
+*/
+QMediaServiceProviderHint::Type QMediaServiceProviderHint::type() const
+{
+ return d->type;
+}
+
+/*!
+ Returns the mime type of the media a service is expected to be able play.
+ \since 1.0
+*/
+QString QMediaServiceProviderHint::mimeType() const
+{
+ return d->mimeType;
+}
+
+/*!
+ Returns a list of codes a media service is expected to be able to decode.
+ \since 1.0
+*/
+QStringList QMediaServiceProviderHint::codecs() const
+{
+ return d->codecs;
+}
+
+/*!
+ Returns the name of a device a media service is expected to utilize.
+ \since 1.0
+*/
+QByteArray QMediaServiceProviderHint::device() const
+{
+ return d->device;
+}
+
+/*!
+ Returns a set of features a media service is expected to provide.
+ \since 1.0
+*/
+QMediaServiceProviderHint::Features QMediaServiceProviderHint::features() const
+{
+ return d->features;
+}
+
+
+Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, loader,
+ (QMediaServiceProviderFactoryInterface_iid, QLatin1String("mediaservice"), Qt::CaseInsensitive))
+
+
+class QPluginServiceProvider : public QMediaServiceProvider
+{
+ QMap<QMediaService*, QMediaServiceProviderPlugin*> pluginMap;
+
+public:
+ QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &hint)
+ {
+ QString key(type);
+
+ QList<QMediaServiceProviderPlugin *>plugins;
+ foreach (QObject *obj, loader()->instances(key)) {
+ QMediaServiceProviderPlugin *plugin =
+ qobject_cast<QMediaServiceProviderPlugin*>(obj);
+ if (plugin)
+ plugins << plugin;
+ }
+
+ if (!plugins.isEmpty()) {
+ QMediaServiceProviderPlugin *plugin = 0;
+
+ switch (hint.type()) {
+ case QMediaServiceProviderHint::Null:
+ plugin = plugins[0];
+ //special case for media player, if low latency was not asked,
+ //prefer services not offering it, since they are likely to support
+ //more formats
+ if (type == QByteArray(Q_MEDIASERVICE_MEDIAPLAYER)) {
+ foreach (QMediaServiceProviderPlugin *currentPlugin, plugins) {
+ QMediaServiceFeaturesInterface *iface =
+ qobject_cast<QMediaServiceFeaturesInterface*>(currentPlugin);
+
+ if (!iface || !(iface->supportedFeatures(type) &
+ QMediaServiceProviderHint::LowLatencyPlayback)) {
+ plugin = currentPlugin;
+ break;
+ }
+
+ }
+ }
+ break;
+ case QMediaServiceProviderHint::SupportedFeatures:
+ plugin = plugins[0];
+ foreach (QMediaServiceProviderPlugin *currentPlugin, plugins) {
+ QMediaServiceFeaturesInterface *iface =
+ qobject_cast<QMediaServiceFeaturesInterface*>(currentPlugin);
+
+ if (iface) {
+ if ((iface->supportedFeatures(type) & hint.features()) == hint.features()) {
+ plugin = currentPlugin;
+ break;
+ }
+ }
+ }
+ break;
+ case QMediaServiceProviderHint::Device: {
+ foreach (QMediaServiceProviderPlugin *currentPlugin, plugins) {
+ QMediaServiceSupportedDevicesInterface *iface =
+ qobject_cast<QMediaServiceSupportedDevicesInterface*>(currentPlugin);
+
+ if (!iface) {
+ // the plugin may support the device,
+ // but this choice still can be overridden
+ plugin = currentPlugin;
+ } else {
+ if (iface->devices(type).contains(hint.device())) {
+ plugin = currentPlugin;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case QMediaServiceProviderHint::ContentType: {
+ QtMultimediaKit::SupportEstimate estimate = QtMultimediaKit::NotSupported;
+ foreach (QMediaServiceProviderPlugin *currentPlugin, plugins) {
+ QtMultimediaKit::SupportEstimate currentEstimate = QtMultimediaKit::MaybeSupported;
+ QMediaServiceSupportedFormatsInterface *iface =
+ qobject_cast<QMediaServiceSupportedFormatsInterface*>(currentPlugin);
+
+ if (iface)
+ currentEstimate = iface->hasSupport(hint.mimeType(), hint.codecs());
+
+ if (currentEstimate > estimate) {
+ estimate = currentEstimate;
+ plugin = currentPlugin;
+
+ if (currentEstimate == QtMultimediaKit::PreferredService)
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ if (plugin != 0) {
+ QMediaService *service = plugin->create(key);
+ if (service != 0)
+ pluginMap.insert(service, plugin);
+
+ return service;
+ }
+ }
+
+ qWarning() << "defaultServiceProvider::requestService(): no service found for -" << key;
+ return 0;
+ }
+
+ void releaseService(QMediaService *service)
+ {
+ if (service != 0) {
+ QMediaServiceProviderPlugin *plugin = pluginMap.take(service);
+
+ if (plugin != 0)
+ plugin->release(service);
+ }
+ }
+
+ QtMultimediaKit::SupportEstimate hasSupport(const QByteArray &serviceType,
+ const QString &mimeType,
+ const QStringList& codecs,
+ int flags) const
+ {
+ QList<QObject*> instances = loader()->instances(serviceType);
+
+ if (instances.isEmpty())
+ return QtMultimediaKit::NotSupported;
+
+ bool allServicesProvideInterface = true;
+ QtMultimediaKit::SupportEstimate supportEstimate = QtMultimediaKit::NotSupported;
+
+ foreach(QObject *obj, instances) {
+ QMediaServiceSupportedFormatsInterface *iface =
+ qobject_cast<QMediaServiceSupportedFormatsInterface*>(obj);
+
+
+ if (flags) {
+ QMediaServiceFeaturesInterface *iface =
+ qobject_cast<QMediaServiceFeaturesInterface*>(obj);
+
+ if (iface) {
+ QMediaServiceProviderHint::Features features = iface->supportedFeatures(serviceType);
+
+ //if low latency playback was asked, skip services known
+ //not to provide low latency playback
+ if ((flags & QMediaPlayer::LowLatency) &&
+ !(features & QMediaServiceProviderHint::LowLatencyPlayback))
+ continue;
+
+ //the same for QIODevice based streams support
+ if ((flags & QMediaPlayer::StreamPlayback) &&
+ !(features & QMediaServiceProviderHint::StreamPlayback))
+ continue;
+ }
+ }
+
+ if (iface)
+ supportEstimate = qMax(supportEstimate, iface->hasSupport(mimeType, codecs));
+ else
+ allServicesProvideInterface = false;
+ }
+
+ //don't return PreferredService
+ supportEstimate = qMin(supportEstimate, QtMultimediaKit::ProbablySupported);
+
+ //Return NotSupported only if no services are available of serviceType
+ //or all the services returned NotSupported, otherwise return at least MaybeSupported
+ if (!allServicesProvideInterface)
+ supportEstimate = qMax(QtMultimediaKit::MaybeSupported, supportEstimate);
+
+ return supportEstimate;
+ }
+
+ QStringList supportedMimeTypes(const QByteArray &serviceType, int flags) const
+ {
+ QList<QObject*> instances = loader()->instances(serviceType);
+
+ QStringList supportedTypes;
+
+ foreach(QObject *obj, instances) {
+ QMediaServiceSupportedFormatsInterface *iface =
+ qobject_cast<QMediaServiceSupportedFormatsInterface*>(obj);
+
+
+ if (flags) {
+ QMediaServiceFeaturesInterface *iface =
+ qobject_cast<QMediaServiceFeaturesInterface*>(obj);
+
+ if (iface) {
+ QMediaServiceProviderHint::Features features = iface->supportedFeatures(serviceType);
+
+ // If low latency playback was asked for, skip MIME types from services known
+ // not to provide low latency playback
+ if ((flags & QMediaPlayer::LowLatency) &&
+ !(features & QMediaServiceProviderHint::LowLatencyPlayback))
+ continue;
+
+ //the same for QIODevice based streams support
+ if ((flags & QMediaPlayer::StreamPlayback) &&
+ !(features & QMediaServiceProviderHint::StreamPlayback))
+ continue;
+
+ //the same for QAbstractVideoSurface support
+ if ((flags & QMediaPlayer::VideoSurface) &&
+ !(features & QMediaServiceProviderHint::VideoSurface))
+ continue;
+ }
+ }
+
+ if (iface) {
+ supportedTypes << iface->supportedMimeTypes();
+ }
+ }
+
+ // Multiple services may support the same MIME type
+ supportedTypes.removeDuplicates();
+
+ return supportedTypes;
+ }
+
+ QList<QByteArray> devices(const QByteArray &serviceType) const
+ {
+ QList<QByteArray> res;
+
+ foreach(QObject *obj, loader()->instances(serviceType)) {
+ QMediaServiceSupportedDevicesInterface *iface =
+ qobject_cast<QMediaServiceSupportedDevicesInterface*>(obj);
+
+ if (iface) {
+ res.append(iface->devices(serviceType));
+ }
+ }
+
+ return res;
+ }
+
+ QString deviceDescription(const QByteArray &serviceType, const QByteArray &device)
+ {
+ foreach(QObject *obj, loader()->instances(serviceType)) {
+ QMediaServiceSupportedDevicesInterface *iface =
+ qobject_cast<QMediaServiceSupportedDevicesInterface*>(obj);
+
+ if (iface) {
+ if (iface->devices(serviceType).contains(device))
+ return iface->deviceDescription(serviceType, device);
+ }
+ }
+
+ return QString();
+ }
+};
+
+Q_GLOBAL_STATIC(QPluginServiceProvider, pluginProvider);
+
+/*!
+ \class QMediaServiceProvider
+
+ \brief The QMediaServiceProvider class provides an abstract allocator for media services.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaServiceProvider::requestService(const QByteArray &type, const QMediaServiceProviderHint &hint)
+
+ Requests an instance of a \a type service which best matches the given \a
+ hint.
+
+ Returns a pointer to the requested service, or a null pointer if there is
+ no suitable service.
+
+ The returned service must be released with releaseService when it is
+ finished with.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaServiceProvider::releaseService(QMediaService *service)
+
+ Releases a media \a service requested with requestService().
+ \since 1.0
+*/
+
+/*!
+ \fn QtMultimediaKit::SupportEstimate QMediaServiceProvider::hasSupport(const QByteArray &serviceType, const QString &mimeType, const QStringList& codecs, int flags) const
+
+ Returns how confident a media service provider is that is can provide a \a
+ serviceType service that is able to play media of a specific \a mimeType
+ that is encoded using the listed \a codecs while adhering to constraints
+ identified in \a flags.
+ \since 1.0
+*/
+QtMultimediaKit::SupportEstimate QMediaServiceProvider::hasSupport(const QByteArray &serviceType,
+ const QString &mimeType,
+ const QStringList& codecs,
+ int flags) const
+{
+ Q_UNUSED(serviceType);
+ Q_UNUSED(mimeType);
+ Q_UNUSED(codecs);
+ Q_UNUSED(flags);
+
+ return QtMultimediaKit::MaybeSupported;
+}
+
+/*!
+ \fn QStringList QMediaServiceProvider::supportedMimeTypes(const QByteArray &serviceType, int flags) const
+
+ Returns a list of MIME types supported by the service provider for the
+ specified \a serviceType.
+
+ The resultant list is restricted to MIME types which can be supported given
+ the constraints in \a flags.
+ \since 1.0
+*/
+QStringList QMediaServiceProvider::supportedMimeTypes(const QByteArray &serviceType, int flags) const
+{
+ Q_UNUSED(serviceType);
+ Q_UNUSED(flags);
+
+ return QStringList();
+}
+
+/*!
+ Returns the list of devices related to \a service type.
+ \since 1.0
+*/
+QList<QByteArray> QMediaServiceProvider::devices(const QByteArray &service) const
+{
+ Q_UNUSED(service);
+ return QList<QByteArray>();
+}
+
+/*!
+ Returns the description of \a device related to \a serviceType, suitable for use by
+ an application for display.
+ \since 1.0
+*/
+QString QMediaServiceProvider::deviceDescription(const QByteArray &serviceType, const QByteArray &device)
+{
+ Q_UNUSED(serviceType);
+ Q_UNUSED(device);
+ return QString();
+}
+
+
+#ifdef QT_BUILD_INTERNAL
+
+static QMediaServiceProvider *qt_defaultMediaServiceProvider = 0;
+
+/*!
+ Sets a media service \a provider as the default.
+
+ \internal
+ \since 1.0
+*/
+void QMediaServiceProvider::setDefaultServiceProvider(QMediaServiceProvider *provider)
+{
+ qt_defaultMediaServiceProvider = provider;
+}
+
+#endif
+
+/*!
+ Returns a default provider of media services.
+*/
+QMediaServiceProvider *QMediaServiceProvider::defaultServiceProvider()
+{
+#ifdef QT_BUILD_INTERNAL
+ return qt_defaultMediaServiceProvider != 0
+ ? qt_defaultMediaServiceProvider
+ : static_cast<QMediaServiceProvider *>(pluginProvider());
+#else
+ return pluginProvider();
+#endif
+}
+
+/*!
+ \class QMediaServiceProviderPlugin
+
+ \brief The QMediaServiceProviderPlugin class interface provides an interface for QMediaService
+ plug-ins.
+ \since 1.0
+
+ A media service provider plug-in may implement one or more of
+ QMediaServiceSupportedFormatsInterface,
+ QMediaServiceSupportedDevicesInterface, and QMediaServiceFeaturesInterface
+ to identify the features it supports.
+*/
+
+/*!
+ \fn QMediaServiceProviderPlugin::keys() const
+
+ Returns a list of keys for media services a plug-in can create.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaServiceProviderPlugin::create(const QString &key)
+
+ Constructs a new instance of the QMediaService identified by \a key.
+
+ The QMediaService returned must be destroyed with release().
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaServiceProviderPlugin::release(QMediaService *service)
+
+ Destroys a media \a service constructed with create().
+ \since 1.0
+*/
+
+
+/*!
+ \class QMediaServiceSupportedFormatsInterface
+ \brief The QMediaServiceSupportedFormatsInterface class interface
+ identifies if a media service plug-in supports a media format.
+ \since 1.0
+
+ A QMediaServiceProviderPlugin may implement this interface.
+*/
+
+/*!
+ \fn QMediaServiceSupportedFormatsInterface::~QMediaServiceSupportedFormatsInterface()
+
+ Destroys a media service supported formats interface.
+*/
+
+/*!
+ \fn QMediaServiceSupportedFormatsInterface::hasSupport(const QString &mimeType, const QStringList& codecs) const
+
+ Returns the level of support a media service plug-in has for a \a mimeType
+ and set of \a codecs.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaServiceSupportedFormatsInterface::supportedMimeTypes() const
+
+ Returns a list of MIME types supported by the media service plug-in.
+ \since 1.0
+*/
+
+/*!
+ \class QMediaServiceSupportedDevicesInterface
+ \brief The QMediaServiceSupportedDevicesInterface class interface
+ identifies the devices supported by a media service plug-in.
+ \since 1.0
+
+ A QMediaServiceProviderPlugin may implement this interface.
+*/
+
+/*!
+ \fn QMediaServiceSupportedDevicesInterface::~QMediaServiceSupportedDevicesInterface()
+
+ Destroys a media service supported devices interface.
+*/
+
+/*!
+ \fn QMediaServiceSupportedDevicesInterface::devices(const QByteArray &service) const
+
+ Returns a list of devices supported by a plug-in \a service.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaServiceSupportedDevicesInterface::deviceDescription(const QByteArray &service, const QByteArray &device)
+
+ Returns a description of a \a device supported by a plug-in \a service.
+ \since 1.0
+*/
+
+/*!
+ \class QMediaServiceFeaturesInterface
+ \brief The QMediaServiceFeaturesInterface class interface identifies
+ features supported by a media service plug-in.
+ \since 1.0
+
+ A QMediaServiceProviderPlugin may implement this interface.
+*/
+
+/*!
+ \fn QMediaServiceFeaturesInterface::~QMediaServiceFeaturesInterface()
+
+ Destroys a media service features interface.
+*/
+/*!
+ \fn QMediaServiceFeaturesInterface::supportedFeatures(const QByteArray &service) const
+
+ Returns a set of features supported by a plug-in \a service.
+ \since 1.0
+*/
+
+#include "moc_qmediaserviceprovider.cpp"
+#include "moc_qmediaserviceproviderplugin.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediaserviceprovider.h b/src/multimediakit/qmediaserviceprovider.h
new file mode 100644
index 000000000..997f371f5
--- /dev/null
+++ b/src/multimediakit/qmediaserviceprovider.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** 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 QMEDIASERVICEPROVIDER_H
+#define QMEDIASERVICEPROVIDER_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qshareddata.h>
+#include <qmobilityglobal.h>
+#include "qtmedianamespace.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMediaService;
+
+class QMediaServiceProviderHintPrivate;
+class Q_MULTIMEDIA_EXPORT QMediaServiceProviderHint
+{
+public:
+ enum Type { Null, ContentType, Device, SupportedFeatures };
+
+ enum Feature {
+ LowLatencyPlayback = 0x01,
+ RecordingSupport = 0x02,
+ StreamPlayback = 0x04,
+ VideoSurface = 0x08
+ };
+ Q_DECLARE_FLAGS(Features, Feature)
+
+ QMediaServiceProviderHint();
+ QMediaServiceProviderHint(const QString &mimeType, const QStringList& codecs);
+ QMediaServiceProviderHint(const QByteArray &device);
+ QMediaServiceProviderHint(Features features);
+ QMediaServiceProviderHint(const QMediaServiceProviderHint &other);
+ ~QMediaServiceProviderHint();
+
+ QMediaServiceProviderHint& operator=(const QMediaServiceProviderHint &other);
+
+ bool operator == (const QMediaServiceProviderHint &other) const;
+ bool operator != (const QMediaServiceProviderHint &other) const;
+
+ bool isNull() const;
+
+ Type type() const;
+
+ QString mimeType() const;
+ QStringList codecs() const;
+
+ QByteArray device() const;
+
+ Features features() const;
+
+ //to be extended, if necessary
+
+private:
+ QSharedDataPointer<QMediaServiceProviderHintPrivate> d;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMediaServiceProviderHint::Features)
+
+class Q_MULTIMEDIA_EXPORT QMediaServiceProvider : public QObject
+{
+ Q_OBJECT
+
+public:
+ virtual QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &hint = QMediaServiceProviderHint()) = 0;
+ virtual void releaseService(QMediaService *service) = 0;
+
+ virtual QtMultimediaKit::SupportEstimate hasSupport(const QByteArray &serviceType,
+ const QString &mimeType,
+ const QStringList& codecs,
+ int flags = 0) const;
+ virtual QStringList supportedMimeTypes(const QByteArray &serviceType, int flags = 0) const;
+
+ virtual QList<QByteArray> devices(const QByteArray &serviceType) const;
+ virtual QString deviceDescription(const QByteArray &serviceType, const QByteArray &device);
+
+ static QMediaServiceProvider* defaultServiceProvider();
+
+#ifdef QT_BUILD_INTERNAL
+ static void setDefaultServiceProvider(QMediaServiceProvider *provider);
+#endif
+};
+
+/*!
+ Service with support for media playback
+ Required Controls: QMediaPlayerControl
+ Optional Controls: QMediaPlaylistControl, QAudioDeviceControl
+ Video Output Controls (used by QWideoWidget and QGraphicsVideoItem):
+ Required: QVideoOutputControl
+ Optional: QVideoWindowControl, QVideoRendererControl, QVideoWidgetControl
+*/
+#define Q_MEDIASERVICE_MEDIAPLAYER "com.nokia.qt.mediaplayer"
+
+/*!
+ Service with support for recording from audio sources
+ Required Controls: QAudioDeviceControl
+ Recording Controls (QMediaRecorder):
+ Required: QMediaRecorderControl
+ Recommended: QAudioEncoderControl
+ Optional: QMediaContainerControl
+*/
+#define Q_MEDIASERVICE_AUDIOSOURCE "com.nokia.qt.audiosource"
+
+/*!
+ Service with support for camera use.
+ Required Controls: QCameraControl
+ Optional Controls: QCameraExposureControl, QCameraFocusControl, QCameraImageProcessingControl
+ Still Capture Controls: QCameraImageCaptureControl
+ Video Capture Controls (QMediaRecorder):
+ Required: QMediaRecorderControl
+ Recommended: QAudioEncoderControl, QVideoEncoderControl, QMediaContainerControl
+ Viewfinder Video Output Controls (used by QCameraViewfinder and QGraphicsVideoItem):
+ Required: QVideoOutputControl
+ Optional: QVideoWindowControl, QVideoRendererControl, QVideoWidgetControl
+*/
+#define Q_MEDIASERVICE_CAMERA "com.nokia.qt.camera"
+
+/*!
+ Service with support for radio tuning.
+ Required Controls: QRadioTunerControl
+ Recording Controls (Optional, used by QMediaRecorder):
+ Required: QMediaRecorderControl
+ Recommended: QAudioEncoderControl
+ Optional: QMediaContainerControl
+*/
+#define Q_MEDIASERVICE_RADIO "com.nokia.qt.radio"
+
+
+QT_END_NAMESPACE
+
+#endif // QMEDIASERVICEPROVIDER_H
diff --git a/src/multimediakit/qmediaserviceproviderplugin.h b/src/multimediakit/qmediaserviceproviderplugin.h
new file mode 100644
index 000000000..767dd4949
--- /dev/null
+++ b/src/multimediakit/qmediaserviceproviderplugin.h
@@ -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$
+**
+****************************************************************************/
+
+#ifndef QMEDIASERVICEPROVIDERPLUGIN_H
+#define QMEDIASERVICEPROVIDERPLUGIN_H
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+#include <qmobilityglobal.h>
+#include "qmediaserviceprovider.h"
+
+#ifdef Q_MOC_RUN
+# pragma Q_MOC_EXPAND_MACROS
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QMediaService;
+
+struct Q_MULTIMEDIA_EXPORT QMediaServiceProviderFactoryInterface : public QFactoryInterface
+{
+ virtual QStringList keys() const = 0;
+ virtual QMediaService* create(QString const& key) = 0;
+ virtual void release(QMediaService *service) = 0;
+};
+
+#define QMediaServiceProviderFactoryInterface_iid \
+ "com.nokia.Qt.QMediaServiceProviderFactoryInterface/1.0"
+Q_DECLARE_INTERFACE(QMediaServiceProviderFactoryInterface, QMediaServiceProviderFactoryInterface_iid)
+
+
+struct Q_MULTIMEDIA_EXPORT QMediaServiceSupportedFormatsInterface
+{
+ virtual ~QMediaServiceSupportedFormatsInterface() {}
+ virtual QtMultimediaKit::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const = 0;
+ virtual QStringList supportedMimeTypes() const = 0;
+};
+
+#define QMediaServiceSupportedFormatsInterface_iid \
+ "com.nokia.Qt.QMediaServiceSupportedFormatsInterface/1.0"
+Q_DECLARE_INTERFACE(QMediaServiceSupportedFormatsInterface, QMediaServiceSupportedFormatsInterface_iid)
+
+
+struct Q_MULTIMEDIA_EXPORT QMediaServiceSupportedDevicesInterface
+{
+ virtual ~QMediaServiceSupportedDevicesInterface() {}
+ virtual QList<QByteArray> devices(const QByteArray &service) const = 0;
+ virtual QString deviceDescription(const QByteArray &service, const QByteArray &device) = 0;
+};
+
+#define QMediaServiceSupportedDevicesInterface_iid \
+ "com.nokia.Qt.QMediaServiceSupportedDevicesInterface/1.0"
+Q_DECLARE_INTERFACE(QMediaServiceSupportedDevicesInterface, QMediaServiceSupportedDevicesInterface_iid)
+
+
+
+struct Q_MULTIMEDIA_EXPORT QMediaServiceFeaturesInterface
+{
+ virtual ~QMediaServiceFeaturesInterface() {}
+ virtual QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const = 0;
+};
+
+#define QMediaServiceFeaturesInterface_iid \
+ "com.nokia.Qt.QMediaServiceFeaturesInterface/1.0"
+Q_DECLARE_INTERFACE(QMediaServiceFeaturesInterface, QMediaServiceFeaturesInterface_iid)
+
+
+class Q_MULTIMEDIA_EXPORT QMediaServiceProviderPlugin : public QObject, public QMediaServiceProviderFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceProviderFactoryInterface:QFactoryInterface)
+
+public:
+ virtual QStringList keys() const = 0;
+ virtual QMediaService* create(const QString& key) = 0;
+ virtual void release(QMediaService *service) = 0;
+};
+
+QT_END_NAMESPACE
+
+
+#endif // QMEDIASERVICEPROVIDERPLUGIN_H
diff --git a/src/multimediakit/qmediastreamscontrol.cpp b/src/multimediakit/qmediastreamscontrol.cpp
new file mode 100644
index 000000000..3b4e668b3
--- /dev/null
+++ b/src/multimediakit/qmediastreamscontrol.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** 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 "qmediastreamscontrol.h"
+#include "qmediacontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMediaStreamsControl
+ \preliminary
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \brief The QMediaStreamsControl class provides a media stream selection control.
+
+ \ingroup multimedia
+ \since 1.0
+
+ The QMediaStreamsControl class provides descriptions of the available media streams
+ and allows individual streams to be activated and deactivated.
+
+ The interface name of QMediaStreamsControl is \c com.nokia.Qt.MediaStreamsControl as
+ defined in QMediaStreamsControl_iid.
+
+ \sa QMediaService::requestControl()
+*/
+
+/*!
+ \macro QMediaStreamsControl_iid
+
+ \c com.nokia.Qt.MediaStreamsControl
+
+ Defines the interface name of the QMediaStreamsControl class.
+
+ \relates QMediaStreamsControl
+ \since 1.0
+*/
+
+/*!
+ Constructs a new media streams control with the given \a parent.
+*/
+QMediaStreamsControl::QMediaStreamsControl(QObject *parent)
+ :QMediaControl(*new QMediaControlPrivate, parent)
+{
+}
+
+/*!
+ Destroys a media streams control.
+*/
+QMediaStreamsControl::~QMediaStreamsControl()
+{
+}
+
+/*!
+ \enum QMediaStreamsControl::StreamType
+
+ Media stream type.
+
+ \value AudioStream Audio stream.
+ \value VideoStream Video stream.
+ \value SubPictureStream Subpicture or teletext stream.
+ \value UnknownStream The stream type is unknown.
+ \value DataStream
+*/
+
+/*!
+ \fn QMediaStreamsControl::streamCount()
+
+ Returns the number of media streams.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaStreamsControl::streamType(int stream)
+
+ Return the type of a media \a stream.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaStreamsControl::metaData(int stream, QtMultimediaKit::MetaData key)
+
+ Returns the meta-data value of \a key for a given \a stream.
+
+ Useful metadata keya are QtMultimediaKit::Title, QtMultimediaKit::Description and QtMultimediaKit::Language.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaStreamsControl::isActive(int stream)
+
+ Returns true if the media \a stream is active.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaStreamsControl::setActive(int stream, bool state)
+
+ Sets the active \a state of a media \a stream.
+
+ Setting the active state of a media stream to true will activate it. If any other stream
+ of the same type was previously active it will be deactivated. Setting the active state fo a
+ media stream to false will deactivate it.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaStreamsControl::streamsChanged()
+
+ The signal is emitted when the available streams list is changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QMediaStreamsControl::activeStreamsChanged()
+
+ The signal is emitted when the active streams list is changed.
+ \since 1.0
+*/
+
+#include "moc_qmediastreamscontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediastreamscontrol.h b/src/multimediakit/qmediastreamscontrol.h
new file mode 100644
index 000000000..a5ee71e3e
--- /dev/null
+++ b/src/multimediakit/qmediastreamscontrol.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** 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 QMEDIASTREAMSCONTROL_H
+#define QMEDIASTREAMSCONTROL_H
+
+#include "qmediacontrol.h"
+#include "qtmedianamespace.h"
+#include "qmobilityglobal.h"
+#include <qmediaenumdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QMediaStreamsControl : public QMediaControl
+{
+ Q_OBJECT
+ Q_ENUMS(SteamType)
+public:
+ enum StreamType { UnknownStream, VideoStream, AudioStream, SubPictureStream, DataStream };
+
+ virtual ~QMediaStreamsControl();
+
+ virtual int streamCount() = 0;
+ virtual StreamType streamType(int streamNumber) = 0;
+
+ virtual QVariant metaData(int streamNumber, QtMultimediaKit::MetaData key) = 0;
+
+ virtual bool isActive(int streamNumber) = 0;
+ virtual void setActive(int streamNumber, bool state) = 0;
+
+Q_SIGNALS:
+ void streamsChanged();
+ void activeStreamsChanged();
+
+protected:
+ QMediaStreamsControl(QObject *parent = 0);
+};
+
+#define QMediaStreamsControl_iid "com.nokia.Qt.QMediaStreamsControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QMediaStreamsControl, QMediaStreamsControl_iid)
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QMediaStreamsControl::StreamType)
+
+Q_MEDIA_ENUM_DEBUG(QMediaStreamsControl, StreamType)
+
+#endif // QMEDIASTREAMSCONTROL_H
+
diff --git a/src/multimediakit/qmediatimerange.cpp b/src/multimediakit/qmediatimerange.cpp
new file mode 100644
index 000000000..9183f0ae1
--- /dev/null
+++ b/src/multimediakit/qmediatimerange.cpp
@@ -0,0 +1,759 @@
+/****************************************************************************
+**
+** 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 "qmediatimerange.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMediaTimeInterval
+ \brief The QMediaTimeInterval class represents a time interval with integer precision.
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ An interval is specified by an inclusive start() and end() time. These
+ must be set in the constructor, as this is an immutable class. The
+ specific units of time represented by the class have not been defined - it
+ is suitable for any times which can be represented by a signed 64 bit
+ integer.
+
+ The isNormal() method determines if a time interval is normal (a normal
+ time interval has start() <= end()). An abnormal interval can be converted
+ in to a normal interval by calling the normalized() method.
+
+ The contains() method determines if a specified time lies within the time
+ interval.
+
+ The translated() method returns a time interval which has been translated
+ forwards or backwards through time by a specified offset.
+
+ \sa QMediaTimeRange
+*/
+
+/*!
+ \fn QMediaTimeInterval::QMediaTimeInterval()
+
+ Constructs an empty interval.
+*/
+QMediaTimeInterval::QMediaTimeInterval()
+ : s(0)
+ , e(0)
+{
+
+}
+
+/*!
+ \fn QMediaTimeInterval::QMediaTimeInterval(qint64 start, qint64 end)
+
+ Constructs an interval with the specified \a start and \a end times.
+ \since 1.0
+*/
+QMediaTimeInterval::QMediaTimeInterval(qint64 start, qint64 end)
+ : s(start)
+ , e(end)
+{
+
+}
+
+/*!
+ \fn QMediaTimeInterval::QMediaTimeInterval(const QMediaTimeInterval &other)
+
+ Constructs an interval by taking a copy of \a other.
+ \since 1.0
+*/
+QMediaTimeInterval::QMediaTimeInterval(const QMediaTimeInterval &other)
+ : s(other.s)
+ , e(other.e)
+{
+
+}
+
+/*!
+ \fn QMediaTimeInterval::start() const
+
+ Returns the start time of the interval.
+
+ \since 1.0
+ \sa end()
+*/
+qint64 QMediaTimeInterval::start() const
+{
+ return s;
+}
+
+/*!
+ \fn QMediaTimeInterval::end() const
+
+ Returns the end time of the interval.
+
+ \since 1.0
+ \sa start()
+*/
+qint64 QMediaTimeInterval::end() const
+{
+ return e;
+}
+
+/*!
+ \fn QMediaTimeInterval::contains(qint64 time) const
+
+ Returns true if the time interval contains the specified \a time.
+ That is, start() <= time <= end().
+ \since 1.0
+*/
+bool QMediaTimeInterval::contains(qint64 time) const
+{
+ return isNormal() ? (s <= time && time <= e)
+ : (e <= time && time <= s);
+}
+
+/*!
+ \fn QMediaTimeInterval::isNormal() const
+
+ Returns true if this time interval is normal.
+ A normal time interval has start() <= end().
+
+ \since 1.0
+ \sa normalized()
+*/
+bool QMediaTimeInterval::isNormal() const
+{
+ return s <= e;
+}
+
+/*!
+ \fn QMediaTimeInterval::normalized() const
+
+ Returns a normalized version of this interval.
+
+ If the start() time of the interval is greater than the end() time,
+ then the returned interval has the start and end times swapped.
+ \since 1.0
+*/
+QMediaTimeInterval QMediaTimeInterval::normalized() const
+{
+ if(s > e)
+ return QMediaTimeInterval(e, s);
+
+ return *this;
+}
+
+/*!
+ \fn QMediaTimeInterval::translated(qint64 offset) const
+
+ Returns a copy of this time interval, translated by a value of \a offset.
+ An interval can be moved forward through time with a positive offset, or backward
+ through time with a negative offset.
+ \since 1.0
+*/
+QMediaTimeInterval QMediaTimeInterval::translated(qint64 offset) const
+{
+ return QMediaTimeInterval(s + offset, e + offset);
+}
+
+/*!
+ \fn operator==(const QMediaTimeInterval &a, const QMediaTimeInterval &b)
+ \relates QMediaTimeRange
+
+ Returns true if \a a is exactly equal to \a b.
+ \since 1.0
+*/
+bool operator==(const QMediaTimeInterval &a, const QMediaTimeInterval &b)
+{
+ return a.start() == b.start() && a.end() == b.end();
+}
+
+/*!
+ \fn operator!=(const QMediaTimeInterval &a, const QMediaTimeInterval &b)
+ \relates QMediaTimeRange
+
+ Returns true if \a a is not exactly equal to \a b.
+ \since 1.0
+*/
+bool operator!=(const QMediaTimeInterval &a, const QMediaTimeInterval &b)
+{
+ return a.start() != b.start() || a.end() != b.end();
+}
+
+class QMediaTimeRangePrivate : public QSharedData
+{
+public:
+
+ QMediaTimeRangePrivate();
+ QMediaTimeRangePrivate(const QMediaTimeRangePrivate &other);
+ QMediaTimeRangePrivate(const QMediaTimeInterval &interval);
+
+ QList<QMediaTimeInterval> intervals;
+
+ void addInterval(const QMediaTimeInterval &interval);
+ void removeInterval(const QMediaTimeInterval &interval);
+};
+
+QMediaTimeRangePrivate::QMediaTimeRangePrivate()
+ : QSharedData()
+{
+
+}
+
+QMediaTimeRangePrivate::QMediaTimeRangePrivate(const QMediaTimeRangePrivate &other)
+ : QSharedData()
+ , intervals(other.intervals)
+{
+
+}
+
+QMediaTimeRangePrivate::QMediaTimeRangePrivate(const QMediaTimeInterval &interval)
+ : QSharedData()
+{
+ if(interval.isNormal())
+ intervals << interval;
+}
+
+void QMediaTimeRangePrivate::addInterval(const QMediaTimeInterval &interval)
+{
+ // Handle normalized intervals only
+ if(!interval.isNormal())
+ return;
+
+ // Find a place to insert the interval
+ int i;
+ for (i = 0; i < intervals.count(); i++) {
+ // Insert before this element
+ if(interval.s < intervals[i].s) {
+ intervals.insert(i, interval);
+ break;
+ }
+ }
+
+ // Interval needs to be added to the end of the list
+ if (i == intervals.count())
+ intervals.append(interval);
+
+ // Do we need to correct the element before us?
+ if(i > 0 && intervals[i - 1].e >= interval.s - 1)
+ i--;
+
+ // Merge trailing ranges
+ while (i < intervals.count() - 1
+ && intervals[i].e >= intervals[i + 1].s - 1) {
+ intervals[i].e = qMax(intervals[i].e, intervals[i + 1].e);
+ intervals.removeAt(i + 1);
+ }
+}
+
+void QMediaTimeRangePrivate::removeInterval(const QMediaTimeInterval &interval)
+{
+ // Handle normalized intervals only
+ if(!interval.isNormal())
+ return;
+
+ for (int i = 0; i < intervals.count(); i++) {
+ QMediaTimeInterval r = intervals[i];
+
+ if (r.e < interval.s) {
+ // Before the removal interval
+ continue;
+ } else if (interval.e < r.s) {
+ // After the removal interval - stop here
+ break;
+ } else if (r.s < interval.s && interval.e < r.e) {
+ // Split case - a single range has a chunk removed
+ intervals[i].e = interval.s -1;
+ addInterval(QMediaTimeInterval(interval.e + 1, r.e));
+ break;
+ } else if (r.s < interval.s) {
+ // Trimming Tail Case
+ intervals[i].e = interval.s - 1;
+ } else if (interval.e < r.e) {
+ // Trimming Head Case - we can stop after this
+ intervals[i].s = interval.e + 1;
+ break;
+ } else {
+ // Complete coverage case
+ intervals.removeAt(i);
+ --i;
+ }
+ }
+}
+
+/*!
+ \class QMediaTimeRange
+ \brief The QMediaTimeRange class represents a set of zero or more disjoint
+ time intervals.
+ \ingroup multimedia
+ \since 1.0
+
+ \reentrant
+
+ The earliestTime(), latestTime(), intervals() and isEmpty()
+ methods are used to get information about the current time range.
+
+ The addInterval(), removeInterval() and clear() methods are used to modify
+ the current time range.
+
+ When adding or removing intervals from the time range, existing intervals
+ within the range may be expanded, trimmed, deleted, merged or split to ensure
+ that all intervals within the time range remain distinct and disjoint. As a
+ consequence, all intervals added or removed from a time range must be
+ \l{QMediaTimeInterval::isNormal()}{normal}.
+
+ \sa QMediaTimeInterval
+*/
+
+/*!
+ \fn QMediaTimeRange::QMediaTimeRange()
+
+ Constructs an empty time range.
+*/
+QMediaTimeRange::QMediaTimeRange()
+ : d(new QMediaTimeRangePrivate)
+{
+
+}
+
+/*!
+ \fn QMediaTimeRange::QMediaTimeRange(qint64 start, qint64 end)
+
+ Constructs a time range that contains an initial interval from
+ \a start to \a end inclusive.
+
+ If the interval is not \l{QMediaTimeInterval::isNormal()}{normal},
+ the resulting time range will be empty.
+
+ \since 1.0
+ \sa addInterval()
+*/
+QMediaTimeRange::QMediaTimeRange(qint64 start, qint64 end)
+ : d(new QMediaTimeRangePrivate(QMediaTimeInterval(start, end)))
+{
+
+}
+
+/*!
+ \fn QMediaTimeRange::QMediaTimeRange(const QMediaTimeInterval &interval)
+
+ Constructs a time range that contains an intitial interval, \a interval.
+
+ If \a interval is not \l{QMediaTimeInterval::isNormal()}{normal},
+ the resulting time range will be empty.
+
+ \since 1.0
+ \sa addInterval()
+*/
+QMediaTimeRange::QMediaTimeRange(const QMediaTimeInterval &interval)
+ : d(new QMediaTimeRangePrivate(interval))
+{
+
+}
+
+/*!
+ \fn QMediaTimeRange::QMediaTimeRange(const QMediaTimeRange &range)
+
+ Constructs a time range by copying another time \a range.
+ \since 1.0
+*/
+QMediaTimeRange::QMediaTimeRange(const QMediaTimeRange &range)
+ : d(range.d)
+{
+
+}
+
+/*!
+ \fn QMediaTimeRange::~QMediaTimeRange()
+
+ Destructor.
+*/
+QMediaTimeRange::~QMediaTimeRange()
+{
+
+}
+
+/*!
+ \fn QMediaTimeRange::operator=(const QMediaTimeRange &other)
+
+ Takes a copy of the \a other time range and returns itself.
+ \since 1.0
+*/
+QMediaTimeRange &QMediaTimeRange::operator=(const QMediaTimeRange &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \fn QMediaTimeRange::operator=(const QMediaTimeInterval &interval)
+
+ Sets the time range to a single continuous interval, \a interval.
+ \since 1.0
+*/
+QMediaTimeRange &QMediaTimeRange::operator=(const QMediaTimeInterval &interval)
+{
+ d = new QMediaTimeRangePrivate(interval);
+ return *this;
+}
+
+/*!
+ \fn QMediaTimeRange::earliestTime() const
+
+ Returns the earliest time within the time range.
+
+ For empty time ranges, this value is equal to zero.
+
+ \since 1.0
+ \sa latestTime()
+*/
+qint64 QMediaTimeRange::earliestTime() const
+{
+ if (!d->intervals.isEmpty())
+ return d->intervals[0].s;
+
+ return 0;
+}
+
+/*!
+ \fn QMediaTimeRange::latestTime() const
+
+ Returns the latest time within the time range.
+
+ For empty time ranges, this value is equal to zero.
+
+ \since 1.0
+ \sa earliestTime()
+*/
+qint64 QMediaTimeRange::latestTime() const
+{
+ if (!d->intervals.isEmpty())
+ return d->intervals[d->intervals.count() - 1].e;
+
+ return 0;
+}
+
+/*!
+ \fn QMediaTimeRange::addInterval(qint64 start, qint64 end)
+ \overload
+
+ Adds the interval specified by \a start and \a end
+ to the time range.
+
+ \since 1.0
+ \sa addInterval()
+*/
+void QMediaTimeRange::addInterval(qint64 start, qint64 end)
+{
+ d->addInterval(QMediaTimeInterval(start, end));
+}
+
+/*!
+ \fn QMediaTimeRange::addInterval(const QMediaTimeInterval &interval)
+
+ Adds the specified \a interval to the time range.
+
+ Adding intervals which are not \l{QMediaTimeInterval::isNormal()}{normal}
+ is invalid, and will be ignored.
+
+ If the specified interval is adjacent to, or overlaps existing
+ intervals within the time range, these intervals will be merged.
+
+ This operation takes \l{linear time}
+
+ \since 1.0
+ \sa removeInterval()
+*/
+void QMediaTimeRange::addInterval(const QMediaTimeInterval &interval)
+{
+ d->addInterval(interval);
+}
+
+/*!
+ \fn QMediaTimeRange::addTimeRange(const QMediaTimeRange &range)
+
+ Adds each of the intervals in \a range to this time range.
+
+ Equivalent to calling addInterval() for each interval in \a range.
+ \since 1.0
+*/
+void QMediaTimeRange::addTimeRange(const QMediaTimeRange &range)
+{
+ foreach(const QMediaTimeInterval &i, range.intervals()) {
+ d->addInterval(i);
+ }
+}
+
+/*!
+ \fn QMediaTimeRange::removeInterval(qint64 start, qint64 end)
+ \overload
+
+ Removes the interval specified by \a start and \a end
+ from the time range.
+
+ \since 1.0
+ \sa removeInterval()
+*/
+void QMediaTimeRange::removeInterval(qint64 start, qint64 end)
+{
+ d->removeInterval(QMediaTimeInterval(start, end));
+}
+
+/*!
+ \fn QMediaTimeRange::removeInterval(const QMediaTimeInterval &interval)
+
+ Removes the specified \a interval from the time range.
+
+ Removing intervals which are not \l{QMediaTimeInterval::isNormal()}{normal}
+ is invalid, and will be ignored.
+
+ Intervals within the time range will be trimmed, split or deleted
+ such that no intervals within the time range include any part of the
+ target interval.
+
+ This operation takes \l{linear time}
+
+ \since 1.0
+ \sa addInterval()
+*/
+void QMediaTimeRange::removeInterval(const QMediaTimeInterval &interval)
+{
+ d->removeInterval(interval);
+}
+
+/*!
+ \fn QMediaTimeRange::removeTimeRange(const QMediaTimeRange &range)
+
+ Removes each of the intervals in \a range from this time range.
+
+ Equivalent to calling removeInterval() for each interval in \a range.
+ \since 1.0
+*/
+void QMediaTimeRange::removeTimeRange(const QMediaTimeRange &range)
+{
+ foreach(const QMediaTimeInterval &i, range.intervals()) {
+ d->removeInterval(i);
+ }
+}
+
+/*!
+ \fn QMediaTimeRange::operator+=(const QMediaTimeRange &other)
+
+ Adds each interval in \a other to the time range and returns the result.
+ \since 1.0
+*/
+QMediaTimeRange& QMediaTimeRange::operator+=(const QMediaTimeRange &other)
+{
+ addTimeRange(other);
+ return *this;
+}
+
+/*!
+ \fn QMediaTimeRange::operator+=(const QMediaTimeInterval &interval)
+
+ Adds the specified \a interval to the time range and returns the result.
+ \since 1.0
+*/
+QMediaTimeRange& QMediaTimeRange::operator+=(const QMediaTimeInterval &interval)
+{
+ addInterval(interval);
+ return *this;
+}
+
+/*!
+ \fn QMediaTimeRange::operator-=(const QMediaTimeRange &other)
+
+ Removes each interval in \a other from the time range and returns the result.
+ \since 1.0
+*/
+QMediaTimeRange& QMediaTimeRange::operator-=(const QMediaTimeRange &other)
+{
+ removeTimeRange(other);
+ return *this;
+}
+
+/*!
+ \fn QMediaTimeRange::operator-=(const QMediaTimeInterval &interval)
+
+ Removes the specified \a interval from the time range and returns the result.
+ \since 1.0
+*/
+QMediaTimeRange& QMediaTimeRange::operator-=(const QMediaTimeInterval &interval)
+{
+ removeInterval(interval);
+ return *this;
+}
+
+/*!
+ \fn QMediaTimeRange::clear()
+
+ Removes all intervals from the time range.
+
+ \since 1.0
+ \sa removeInterval()
+*/
+void QMediaTimeRange::clear()
+{
+ d->intervals.clear();
+}
+
+/*!
+ \fn QMediaTimeRange::intervals() const
+
+ Returns the list of intervals covered by this time range.
+ \since 1.0
+*/
+QList<QMediaTimeInterval> QMediaTimeRange::intervals() const
+{
+ return d->intervals;
+}
+
+/*!
+ \fn QMediaTimeRange::isEmpty() const
+
+ Returns true if there are no intervals within the time range.
+
+ \since 1.0
+ \sa intervals()
+*/
+bool QMediaTimeRange::isEmpty() const
+{
+ return d->intervals.isEmpty();
+}
+
+/*!
+ \fn QMediaTimeRange::isContinuous() const
+
+ Returns true if the time range consists of a continuous interval.
+ That is, there is one or fewer disjoint intervals within the time range.
+ \since 1.0
+*/
+bool QMediaTimeRange::isContinuous() const
+{
+ return (d->intervals.count() <= 1);
+}
+
+/*!
+ \fn QMediaTimeRange::contains(qint64 time) const
+
+ Returns true if the specified \a time lies within the time range.
+ \since 1.0
+*/
+bool QMediaTimeRange::contains(qint64 time) const
+{
+ for (int i = 0; i < d->intervals.count(); i++) {
+ if (d->intervals[i].contains(time))
+ return true;
+
+ if (time < d->intervals[i].s)
+ break;
+ }
+
+ return false;
+}
+
+/*!
+ \fn operator==(const QMediaTimeRange &a, const QMediaTimeRange &b)
+ \relates QMediaTimeRange
+
+ Returns true if all intervals in \a a are present in \a b.
+ \since 1.0
+*/
+bool operator==(const QMediaTimeRange &a, const QMediaTimeRange &b)
+{
+ if (a.intervals().count() != b.intervals().count())
+ return false;
+
+ for (int i = 0; i < a.intervals().count(); i++)
+ {
+ if(a.intervals()[i] != b.intervals()[i])
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \fn operator!=(const QMediaTimeRange &a, const QMediaTimeRange &b)
+ \relates QMediaTimeRange
+
+ Returns true if one or more intervals in \a a are not present in \a b.
+ \since 1.0
+*/
+bool operator!=(const QMediaTimeRange &a, const QMediaTimeRange &b)
+{
+ return !(a == b);
+}
+
+/*!
+ \fn operator+(const QMediaTimeRange &r1, const QMediaTimeRange &r2)
+
+ Returns a time range containing the union between \a r1 and \a r2.
+ \since 1.0
+ */
+QMediaTimeRange operator+(const QMediaTimeRange &r1, const QMediaTimeRange &r2)
+{
+ return (QMediaTimeRange(r1) += r2);
+}
+
+/*!
+ \fn operator-(const QMediaTimeRange &r1, const QMediaTimeRange &r2)
+
+ Returns a time range containing \a r2 subtracted from \a r1.
+ \since 1.0
+ */
+QMediaTimeRange operator-(const QMediaTimeRange &r1, const QMediaTimeRange &r2)
+{
+ return (QMediaTimeRange(r1) -= r2);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QMediaTimeRange &range)
+{
+ dbg.nospace() << "QMediaTimeRange( ";
+ foreach (const QMediaTimeInterval &interval, range.intervals()) {
+ dbg.nospace() << "(" << interval.start() << ", " << interval.end() << ") ";
+ }
+ dbg.space() << ")";
+ return dbg;
+}
+#endif
+
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmediatimerange.h b/src/multimediakit/qmediatimerange.h
new file mode 100644
index 000000000..cb236c688
--- /dev/null
+++ b/src/multimediakit/qmediatimerange.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** 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 QMEDIATIMERANGE_H
+#define QMEDIATIMERANGE_H
+
+#include <qmobilityglobal.h>
+#include "qtmedianamespace.h"
+#include <QtCore/qshareddata.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMediaTimeRangePrivate;
+
+class Q_MULTIMEDIA_EXPORT QMediaTimeInterval
+{
+public:
+ QMediaTimeInterval();
+ QMediaTimeInterval(qint64 start, qint64 end);
+ QMediaTimeInterval(const QMediaTimeInterval&);
+
+ qint64 start() const;
+ qint64 end() const;
+
+ bool contains(qint64 time) const;
+
+ bool isNormal() const;
+ QMediaTimeInterval normalized() const;
+ QMediaTimeInterval translated(qint64 offset) const;
+
+private:
+ friend class QMediaTimeRangePrivate;
+ friend class QMediaTimeRange;
+
+ qint64 s;
+ qint64 e;
+};
+
+Q_MULTIMEDIA_EXPORT bool operator==(const QMediaTimeInterval&, const QMediaTimeInterval&);
+Q_MULTIMEDIA_EXPORT bool operator!=(const QMediaTimeInterval&, const QMediaTimeInterval&);
+
+class Q_MULTIMEDIA_EXPORT QMediaTimeRange
+{
+public:
+
+ QMediaTimeRange();
+ QMediaTimeRange(qint64 start, qint64 end);
+ QMediaTimeRange(const QMediaTimeInterval&);
+ QMediaTimeRange(const QMediaTimeRange &range);
+ ~QMediaTimeRange();
+
+ QMediaTimeRange &operator=(const QMediaTimeRange&);
+ QMediaTimeRange &operator=(const QMediaTimeInterval&);
+
+ qint64 earliestTime() const;
+ qint64 latestTime() const;
+
+ QList<QMediaTimeInterval> intervals() const;
+ bool isEmpty() const;
+ bool isContinuous() const;
+
+ bool contains(qint64 time) const;
+
+ void addInterval(qint64 start, qint64 end);
+ void addInterval(const QMediaTimeInterval &interval);
+ void addTimeRange(const QMediaTimeRange&);
+
+ void removeInterval(qint64 start, qint64 end);
+ void removeInterval(const QMediaTimeInterval &interval);
+ void removeTimeRange(const QMediaTimeRange&);
+
+ QMediaTimeRange& operator+=(const QMediaTimeRange&);
+ QMediaTimeRange& operator+=(const QMediaTimeInterval&);
+ QMediaTimeRange& operator-=(const QMediaTimeRange&);
+ QMediaTimeRange& operator-=(const QMediaTimeInterval&);
+
+ void clear();
+
+private:
+ QSharedDataPointer<QMediaTimeRangePrivate> d;
+};
+
+Q_MULTIMEDIA_EXPORT bool operator==(const QMediaTimeRange&, const QMediaTimeRange&);
+Q_MULTIMEDIA_EXPORT bool operator!=(const QMediaTimeRange&, const QMediaTimeRange&);
+Q_MULTIMEDIA_EXPORT QMediaTimeRange operator+(const QMediaTimeRange&, const QMediaTimeRange&);
+Q_MULTIMEDIA_EXPORT QMediaTimeRange operator-(const QMediaTimeRange&, const QMediaTimeRange&);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug, const QMediaTimeRange &);
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QMEDIATIMERANGE_H
diff --git a/src/multimediakit/qmetadatareadercontrol.cpp b/src/multimediakit/qmetadatareadercontrol.cpp
new file mode 100644
index 000000000..8f9b86acb
--- /dev/null
+++ b/src/multimediakit/qmetadatareadercontrol.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 <qmediacontrol_p.h>
+#include <qmetadatareadercontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ \class QMetaDataReaderControl
+ \inmodule QtMultimediaKit
+ \ingroup multimedia-serv
+ \since 1.0
+
+
+ \brief The QMetaDataReaderControl class provides read access to the
+ meta-data of a QMediaService's media.
+
+ If a QMediaService can provide read or write access to the meta-data of
+ its current media it will implement QMetaDataReaderControl. This control
+ provides functions for both retrieving and setting meta-data values.
+ Meta-data may be addressed by the well defined keys in the
+ QtMultimediaKit::MetaData enumeration using the metaData() functions, or by
+ string keys using the extendedMetaData() functions.
+
+ The functionality provided by this control is exposed to application
+ code by the meta-data members of QMediaObject, and so meta-data access
+ is potentially available in any of the media object classes. Any media
+ service may implement QMetaDataReaderControl.
+
+ The interface name of QMetaDataReaderControl is
+ \c com.nokia.Qt.QMetaDataReaderControl/1.0 as defined in
+ QMetaDataReaderControl_iid.
+
+ \sa QMediaService::requestControl(), QMediaObject
+*/
+
+/*!
+ \macro QMetaDataReaderControl_iid
+
+ \c com.nokia.Qt.QMetaDataReaderControl/1.0
+
+ Defines the interface name of the QMetaDataReaderControl class.
+
+ \relates QMetaDataReaderControl
+*/
+
+/*!
+ Construct a QMetaDataReaderControl with \a parent. This class is meant as a base class
+ for service specific meta data providers so this constructor is protected.
+*/
+
+QMetaDataReaderControl::QMetaDataReaderControl(QObject *parent):
+ QMediaControl(*new QMediaControlPrivate, parent)
+{
+}
+
+/*!
+ Destroy the meta-data object.
+*/
+
+QMetaDataReaderControl::~QMetaDataReaderControl()
+{
+}
+
+/*!
+ \fn bool QMetaDataReaderControl::isMetaDataAvailable() const
+
+ Identifies if meta-data is available from a media service.
+
+ Returns true if the meta-data is available and false otherwise.
+ \since 1.0
+*/
+
+/*!
+ \fn QVariant QMetaDataReaderControl::metaData(QtMultimediaKit::MetaData key) const
+
+ Returns the meta-data for the given \a key.
+ \since 1.0
+*/
+
+/*!
+ \fn QMetaDataReaderControl::availableMetaData() const
+
+ Returns a list of keys there is meta-data available for.
+ \since 1.0
+*/
+
+/*!
+ \fn QMetaDataReaderControl::extendedMetaData(const QString &key) const
+
+ Returns the metaData for an abitrary string \a key.
+
+ The valid selection of keys for extended meta-data is determined by the provider and the meaning
+ and type may differ between providers.
+ \since 1.0
+*/
+
+/*!
+ \fn QMetaDataReaderControl::availableExtendedMetaData() const
+
+ Returns a list of keys there is extended meta-data available for.
+ \since 1.0
+*/
+
+
+/*!
+ \fn void QMetaDataReaderControl::metaDataChanged()
+
+ Signal the changes of meta-data.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMetaDataReaderControl::metaDataAvailableChanged(bool available)
+
+ Signal the availability of meta-data has changed, \a available will
+ be true if the multimedia object has meta-data.
+ \since 1.0
+*/
+
+#include "moc_qmetadatareadercontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmetadatareadercontrol.h b/src/multimediakit/qmetadatareadercontrol.h
new file mode 100644
index 000000000..a2c7d8184
--- /dev/null
+++ b/src/multimediakit/qmetadatareadercontrol.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 QMETADATAREADERCONTROL_H
+#define QMETADATAREADERCONTROL_H
+
+#include <qmediacontrol.h>
+#include <qmediaobject.h>
+
+#include <qmediaresource.h>
+
+#include <qmobilityglobal.h>
+#include "qtmedianamespace.h"
+
+QT_BEGIN_NAMESPACE
+
+
+class Q_MULTIMEDIA_EXPORT QMetaDataReaderControl : public QMediaControl
+{
+ Q_OBJECT
+public:
+ ~QMetaDataReaderControl();
+
+ virtual bool isMetaDataAvailable() const = 0;
+
+ virtual QVariant metaData(QtMultimediaKit::MetaData key) const = 0;
+ virtual QList<QtMultimediaKit::MetaData> availableMetaData() const = 0;
+
+ virtual QVariant extendedMetaData(const QString &key) const = 0;
+ virtual QStringList availableExtendedMetaData() const = 0;
+
+Q_SIGNALS:
+ void metaDataChanged();
+
+ void metaDataAvailableChanged(bool available);
+
+protected:
+ QMetaDataReaderControl(QObject *parent = 0);
+};
+
+#define QMetaDataReaderControl_iid "com.nokia.Qt.QMetaDataReaderControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QMetaDataReaderControl, QMetaDataReaderControl_iid)
+
+QT_END_NAMESPACE
+
+#endif // QMETADATAPROVIDER_H
diff --git a/src/multimediakit/qmetadatawritercontrol.cpp b/src/multimediakit/qmetadatawritercontrol.cpp
new file mode 100644
index 000000000..45b81541c
--- /dev/null
+++ b/src/multimediakit/qmetadatawritercontrol.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** 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 <qmediacontrol_p.h>
+#include <qmetadatawritercontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ \class QMetaDataWriterControl
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+
+ \brief The QMetaDataWriterControl class provides write access to the
+ meta-data of a QMediaService's media.
+
+ If a QMediaService can provide write access to the meta-data of its
+ current media it will implement QMetaDataWriterControl. This control
+ provides functions for both retrieving and setting meta-data values.
+ Meta-data may be addressed by the well defined keys in the
+ QtMultimediaKit::MetaData enumeration using the metaData() functions, or
+ by string keys using the extendedMetaData() functions.
+
+ The functionality provided by this control is exposed to application code
+ by the meta-data members of QMediaObject, and so meta-data access is
+ potentially available in any of the media object classes. Any media
+ service may implement QMetaDataControl.
+
+ The interface name of QMetaDataWriterControl is \c com.nokia.Qt.QMetaDataWriterControl/1.0 as
+ defined in QMetaDataWriterControl_iid.
+
+ \sa QMediaService::requestControl(), QMediaObject
+*/
+
+/*!
+ \macro QMetaDataWriterControl_iid
+
+ \c com.nokia.Qt.QMetaDataWriterControl/1.0
+
+ Defines the interface name of the QMetaDataWriterControl class.
+
+ \relates QMetaDataWriterControl
+*/
+
+/*!
+ Construct a QMetaDataWriterControl with \a parent. This class is meant as a base class
+ for service specific meta data providers so this constructor is protected.
+*/
+
+QMetaDataWriterControl::QMetaDataWriterControl(QObject *parent):
+ QMediaControl(*new QMediaControlPrivate, parent)
+{
+}
+
+/*!
+ Destroy the meta-data writer control.
+*/
+
+QMetaDataWriterControl::~QMetaDataWriterControl()
+{
+}
+
+/*!
+ \fn bool QMetaDataWriterControl::isMetaDataAvailable() const
+
+ Identifies if meta-data is available from a media service.
+
+ Returns true if the meta-data is available and false otherwise.
+ \since 1.0
+*/
+
+/*!
+ \fn bool QMetaDataWriterControl::isWritable() const
+
+ Identifies if a media service's meta-data can be edited.
+
+ Returns true if the meta-data is writable and false otherwise.
+ \since 1.0
+*/
+
+/*!
+ \fn QVariant QMetaDataWriterControl::metaData(QtMultimediaKit::MetaData key) const
+
+ Returns the meta-data for the given \a key.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMetaDataWriterControl::setMetaData(QtMultimediaKit::MetaData key, const QVariant &value)
+
+ Sets the \a value of the meta-data element with the given \a key.
+ \since 1.0
+*/
+
+/*!
+ \fn QMetaDataWriterControl::availableMetaData() const
+
+ Returns a list of keys there is meta-data available for.
+*/
+
+/*!
+ \fn QMetaDataWriterControl::extendedMetaData(const QString &key) const
+
+ Returns the meta-data for an abitrary string \a key.
+
+ The valid selection of keys for extended meta-data is determined by the provider and the meaning
+ and type may differ between providers.
+ \since 1.0
+*/
+
+/*!
+ \fn QMetaDataWriterControl::setExtendedMetaData(const QString &key, const QVariant &value)
+
+ Change the value of the meta-data element with an abitrary string \a key to \a value.
+
+ The valid selection of keys for extended meta-data is determined by the provider and the meaning
+ and type may differ between providers.
+ \since 1.0
+*/
+
+/*!
+ \fn QMetaDataWriterControl::availableExtendedMetaData() const
+
+ Returns a list of keys there is extended meta-data available for.
+ \since 1.0
+*/
+
+
+/*!
+ \fn void QMetaDataWriterControl::metaDataChanged()
+
+ Signal the changes of meta-data.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMetaDataWriterControl::metaDataAvailableChanged(bool available)
+
+ Signal the availability of meta-data has changed, \a available will
+ be true if the multimedia object has meta-data.
+ \since 1.0
+*/
+
+/*!
+ \fn void QMetaDataWriterControl::writableChanged(bool writable)
+
+ Signal a change in the writable status of meta-data, \a writable will be
+ true if meta-data elements can be added or adjusted.
+ \since 1.0
+*/
+
+#include "moc_qmetadatawritercontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qmetadatawritercontrol.h b/src/multimediakit/qmetadatawritercontrol.h
new file mode 100644
index 000000000..1e3388426
--- /dev/null
+++ b/src/multimediakit/qmetadatawritercontrol.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** 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 QMETADATAWRITERCONTROL_H
+#define QMETADATAWRITERCONTROL_H
+
+#include "qmediacontrol.h"
+#include "qmediaobject.h"
+
+#include "qmediaresource.h"
+
+#include <qmobilityglobal.h>
+#include "qtmedianamespace.h"
+
+QT_BEGIN_NAMESPACE
+
+
+class Q_MULTIMEDIA_EXPORT QMetaDataWriterControl : public QMediaControl
+{
+ Q_OBJECT
+public:
+ ~QMetaDataWriterControl();
+
+ virtual bool isWritable() const = 0;
+ virtual bool isMetaDataAvailable() const = 0;
+
+ virtual QVariant metaData(QtMultimediaKit::MetaData key) const = 0;
+ virtual void setMetaData(QtMultimediaKit::MetaData key, const QVariant &value) = 0;
+ virtual QList<QtMultimediaKit::MetaData> availableMetaData() const = 0;
+
+ virtual QVariant extendedMetaData(const QString &key) const = 0;
+ virtual void setExtendedMetaData(const QString &key, const QVariant &value) = 0;
+ virtual QStringList availableExtendedMetaData() const = 0;
+
+
+Q_SIGNALS:
+ void metaDataChanged();
+
+ void writableChanged(bool writable);
+ void metaDataAvailableChanged(bool available);
+
+protected:
+ QMetaDataWriterControl(QObject *parent = 0);
+};
+
+#define QMetaDataWriterControl_iid "com.nokia.Qt.QMetaDataWriterControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QMetaDataWriterControl, QMetaDataWriterControl_iid)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qmobilityglobal.h b/src/multimediakit/qmobilityglobal.h
new file mode 100644
index 000000000..b32b243ce
--- /dev/null
+++ b/src/multimediakit/qmobilityglobal.h
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** 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 QMOBILITYGLOBAL_H
+#define QMOBILITYGLOBAL_H
+
+#define QTM_VERSION_STR "1.2.0"
+/*
+ QTM_VERSION is (major << 16) + (minor << 8) + patch.
+*/
+#define QTM_VERSION 0x010200
+/*
+ can be used like #if (QTM_VERSION >= QTM_VERSION_CHECK(1, 2, 0))
+*/
+#define QTM_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
+
+#define QTM_PACKAGEDATE_STR "YYYY-MM-DD"
+
+#define QTM_PACKAGE_TAG ""
+
+#include <QtCore/qglobal.h>
+#if defined(QTM_BUILD_UNITTESTS) && (defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)) && defined(QT_MAKEDLL)
+# define QM_AUTOTEST_EXPORT Q_DECL_EXPORT
+#elif defined(QTM_BUILD_UNITTESTS) && (defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)) && defined(QT_DLL)
+# define QM_AUTOTEST_EXPORT Q_DECL_IMPORT
+#elif defined(QTM_BUILD_UNITTESTS) && !(defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)) && defined(QT_SHARED)
+# define QM_AUTOTEST_EXPORT Q_DECL_EXPORT
+#else
+# define QM_AUTOTEST_EXPORT
+#endif
+
+
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+# if defined(QT_NODLL)
+# undef QT_MAKEDLL
+# undef QT_DLL
+# elif defined(QT_MAKEDLL)
+# if defined(QT_DLL)
+# undef QT_DLL
+# endif
+# if defined(QT_BUILD_BEARER_LIB)
+# define Q_BEARER_EXPORT Q_DECL_EXPORT
+# else
+# define Q_BEARER_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_CFW_LIB)
+# define Q_PUBLISHSUBSCRIBE_EXPORT Q_DECL_EXPORT
+# else
+# define Q_PUBLISHSUBSCRIBE_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_CONTACTS_LIB)
+# define Q_CONTACTS_EXPORT Q_DECL_EXPORT
+# else
+# define Q_CONTACTS_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_VERSIT_LIB)
+# define Q_VERSIT_EXPORT Q_DECL_EXPORT
+# else
+# define Q_VERSIT_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_VERSIT_ORGANIZER_LIB)
+# define Q_VERSIT_ORGANIZER_EXPORT Q_DECL_EXPORT
+# else
+# define Q_VERSIT_ORGANIZER_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_LOCATION_LIB)
+# define Q_LOCATION_EXPORT Q_DECL_EXPORT
+# else
+# define Q_LOCATION_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_MESSAGING_LIB)
+# define Q_MESSAGING_EXPORT Q_DECL_EXPORT
+# else
+# define Q_MESSAGING_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_MULTIMEDIA_LIB)
+# define Q_MULTIMEDIA_EXPORT Q_DECL_EXPORT
+# else
+# define Q_MULTIMEDIA_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_SFW_LIB)
+# define Q_SERVICEFW_EXPORT Q_DECL_EXPORT
+# else
+# define Q_SERVICEFW_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_SYSINFO_LIB)
+# define Q_SYSINFO_EXPORT Q_DECL_EXPORT
+# else
+# define Q_SYSINFO_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_SENSORS_LIB)
+# define Q_SENSORS_EXPORT Q_DECL_EXPORT
+# else
+# define Q_SENSORS_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_FEEDBACK_LIB)
+# define Q_FEEDBACK_EXPORT Q_DECL_EXPORT
+# else
+# define Q_FEEDBACK_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_GALLERY_LIB)
+# define Q_GALLERY_EXPORT Q_DECL_EXPORT
+# else
+# define Q_GALLERY_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_ORGANIZER_LIB)
+# define Q_ORGANIZER_EXPORT Q_DECL_EXPORT
+# else
+# define Q_ORGANIZER_EXPORT Q_DECL_IMPORT
+# endif
+# if defined(QT_BUILD_CONNECTIVITY_LIB)
+# define Q_CONNECTIVITY_EXPORT Q_DECL_EXPORT
+# else
+# define Q_CONNECTIVITY_EXPORT Q_DECL_IMPORT
+# endif
+# elif defined(QT_DLL) /* use a Qt DLL library */
+# define Q_BEARER_EXPORT Q_DECL_IMPORT
+# define Q_PUBLISHSUBSCRIBE_EXPORT Q_DECL_IMPORT
+# define Q_CONTACTS_EXPORT Q_DECL_IMPORT
+# define Q_VERSIT_EXPORT Q_DECL_IMPORT
+# define Q_VERSIT_ORGANIZER_EXPORT Q_DECL_IMPORT
+# define Q_LOCATION_EXPORT Q_DECL_IMPORT
+# define Q_MULTIMEDIA_EXPORT Q_DECL_IMPORT
+# define Q_MESSAGING_EXPORT Q_DECL_IMPORT
+# if QTM_SERVICEFW_SYMBIAN_DATABASEMANAGER_SERVER
+# define Q_SERVICEFW_EXPORT
+# else
+# define Q_SERVICEFW_EXPORT Q_DECL_IMPORT
+# endif
+# define Q_SYSINFO_EXPORT Q_DECL_IMPORT
+# define Q_SENSORS_EXPORT Q_DECL_IMPORT
+# define Q_FEEDBACK_EXPORT Q_DECL_IMPORT
+# define Q_GALLERY_EXPORT Q_DECL_IMPORT
+# define Q_ORGANIZER_EXPORT Q_DECL_IMPORT
+# define Q_CONNECTIVITY_EXPORT Q_DECL_IMPORT
+# endif
+#endif
+
+#if !defined(Q_SERVICEFW_EXPORT)
+# if defined(QT_SHARED)
+# define Q_BEARER_EXPORT Q_DECL_EXPORT
+# define Q_PUBLISHSUBSCRIBE_EXPORT Q_DECL_EXPORT
+# define Q_CONTACTS_EXPORT Q_DECL_EXPORT
+# define Q_VERSIT_EXPORT Q_DECL_EXPORT
+# define Q_VERSIT_ORGANIZER_EXPORT Q_DECL_EXPORT
+# define Q_LOCATION_EXPORT Q_DECL_EXPORT
+# define Q_MULTIMEDIA_EXPORT Q_DECL_EXPORT
+# define Q_MESSAGING_EXPORT Q_DECL_EXPORT
+# define Q_SERVICEFW_EXPORT Q_DECL_EXPORT
+# define Q_SYSINFO_EXPORT Q_DECL_EXPORT
+# define Q_SENSORS_EXPORT Q_DECL_EXPORT
+# define Q_FEEDBACK_EXPORT Q_DECL_EXPORT
+# define Q_GALLERY_EXPORT Q_DECL_EXPORT
+# define Q_ORGANIZER_EXPORT Q_DECL_EXPORT
+# define Q_CONNECTIVITY_EXPORT Q_DECL_EXPORT
+# else
+# define Q_BEARER_EXPORT
+# define Q_PUBLISHSUBSCRIBE_EXPORT
+# define Q_CONTACTS_EXPORT
+# define Q_VERSIT_EXPORT
+# define Q_VERSIT_ORGANIZER_EXPORT
+# define Q_LOCATION_EXPORT
+# define Q_MULTIMEDIA_EXPORT
+# define Q_MESSAGING_EXPORT
+# define Q_SERVICEFW_EXPORT
+# define Q_SYSINFO_EXPORT
+# define Q_SENSORS_EXPORT
+# define Q_FEEDBACK_EXPORT
+# define Q_GALLERY_EXPORT
+# define Q_ORGANIZER_EXPORT
+# define Q_CONNECTIVITY_EXPORT
+# endif
+#endif
+
+
+#ifdef QTM_SERVICEFW_SYMBIAN_DATABASEMANAGER_SERVER
+# ifdef Q_SERVICEFW_EXPORT
+# undef Q_SERVICEFW_EXPORT
+# endif
+# define Q_SERVICEFW_EXPORT
+# ifdef QM_AUTOTEST_EXPORT
+# undef QM_AUTOTEST_EXPORT
+# endif
+# define QM_AUTOTEST_EXPORT
+#endif
+
+// The namespace is hardcoded as moc has issues resolving
+// macros which would be a prerequisite for a dynmamic namespace
+#define QTM_NAMESPACE QtMobility
+
+#ifdef QTM_NAMESPACE
+# define QTM_PREPEND_NAMESPACE(name) ::QTM_NAMESPACE::name
+# define QTM_BEGIN_NAMESPACE namespace QTM_NAMESPACE {
+# define QTM_END_NAMESPACE }
+# define QTM_USE_NAMESPACE using namespace QTM_NAMESPACE;
+#else
+# define QTM_PREPEND_NAMESPACE(name) ::name
+# define QTM_BEGIN_NAMESPACE
+# define QTM_END_NAMESPACE
+# define QTM_USE_NAMESPACE
+#endif
+
+//in case Qt is in namespace
+QT_USE_NAMESPACE
+
+#endif // QMOBILITYGLOBAL_H
+
diff --git a/src/multimediakit/qpaintervideosurface.cpp b/src/multimediakit/qpaintervideosurface.cpp
new file mode 100644
index 000000000..49148e870
--- /dev/null
+++ b/src/multimediakit/qpaintervideosurface.cpp
@@ -0,0 +1,1728 @@
+/****************************************************************************
+**
+** 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 <qpaintervideosurface_p.h>
+#include <qpaintervideosurface_mac_p.h>
+
+#include <qmath.h>
+
+#include <qpainter.h>
+#include <qvariant.h>
+#include <qvideosurfaceformat.h>
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+#include <qglshaderprogram.h>
+#ifndef GL_CLAMP_TO_EDGE
+#define GL_CLAMP_TO_EDGE 0x812F
+#endif
+#endif
+
+#include <QtDebug>
+QT_BEGIN_NAMESPACE
+
+QVideoSurfacePainter::~QVideoSurfacePainter()
+{
+}
+
+class QVideoSurfaceGenericPainter : public QVideoSurfacePainter
+{
+public:
+ QVideoSurfaceGenericPainter();
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const;
+
+ bool isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const;
+
+ QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame);
+
+ QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source);
+
+ void updateColors(int brightness, int contrast, int hue, int saturation);
+
+private:
+ QList<QVideoFrame::PixelFormat> m_imagePixelFormats;
+ QVideoFrame m_frame;
+ QSize m_imageSize;
+ QImage::Format m_imageFormat;
+ QVideoSurfaceFormat::Direction m_scanLineDirection;
+};
+
+QVideoSurfaceGenericPainter::QVideoSurfaceGenericPainter()
+ : m_imageFormat(QImage::Format_Invalid)
+ , m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
+{
+ m_imagePixelFormats
+ << QVideoFrame::Format_RGB32
+#ifndef QT_OPENGL_ES // The raster formats should be a subset of the GL formats.
+ << QVideoFrame::Format_RGB24
+#endif
+ << QVideoFrame::Format_ARGB32
+ << QVideoFrame::Format_RGB565;
+}
+
+QList<QVideoFrame::PixelFormat> QVideoSurfaceGenericPainter::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ switch (handleType) {
+ case QAbstractVideoBuffer::QPixmapHandle:
+ case QAbstractVideoBuffer::NoHandle:
+ return m_imagePixelFormats;
+ default:
+ ;
+ }
+ return QList<QVideoFrame::PixelFormat>();
+}
+
+bool QVideoSurfaceGenericPainter::isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *) const
+{
+ switch (format.handleType()) {
+ case QAbstractVideoBuffer::QPixmapHandle:
+ return true;
+ case QAbstractVideoBuffer::NoHandle:
+ return m_imagePixelFormats.contains(format.pixelFormat())
+ && !format.frameSize().isEmpty();
+ default:
+ ;
+ }
+ return false;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGenericPainter::start(const QVideoSurfaceFormat &format)
+{
+ m_frame = QVideoFrame();
+ m_imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
+ m_imageSize = format.frameSize();
+ m_scanLineDirection = format.scanLineDirection();
+
+ const QAbstractVideoBuffer::HandleType t = format.handleType();
+ if (t == QAbstractVideoBuffer::NoHandle) {
+ if (m_imageFormat != QImage::Format_Invalid
+#ifdef QT_OPENGL_ES
+ && format.pixelFormat() != QVideoFrame::Format_RGB24
+#endif
+ && !m_imageSize.isEmpty()) {
+ return QAbstractVideoSurface::NoError;
+ }
+ } else if (t == QAbstractVideoBuffer::QPixmapHandle) {
+ return QAbstractVideoSurface::NoError;
+ }
+ return QAbstractVideoSurface::UnsupportedFormatError;
+}
+
+void QVideoSurfaceGenericPainter::stop()
+{
+ m_frame = QVideoFrame();
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGenericPainter::setCurrentFrame(const QVideoFrame &frame)
+{
+ m_frame = frame;
+
+ return QAbstractVideoSurface::NoError;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGenericPainter::paint(
+ const QRectF &target, QPainter *painter, const QRectF &source)
+{
+ if (!m_frame.isValid()) {
+ painter->fillRect(target, Qt::black);
+ return QAbstractVideoSurface::NoError;
+ }
+
+ if (m_frame.handleType() == QAbstractVideoBuffer::QPixmapHandle) {
+ painter->drawPixmap(target, m_frame.handle().value<QPixmap>(), source);
+ } else if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) {
+ QImage image(
+ m_frame.bits(),
+ m_imageSize.width(),
+ m_imageSize.height(),
+ m_frame.bytesPerLine(),
+ m_imageFormat);
+
+ if (m_scanLineDirection == QVideoSurfaceFormat::BottomToTop) {
+ const QTransform oldTransform = painter->transform();
+
+ painter->scale(1, -1);
+ painter->translate(0, -target.bottom());
+ painter->drawImage(
+ QRectF(target.x(), 0, target.width(), target.height()), image, source);
+ painter->setTransform(oldTransform);
+ } else {
+ painter->drawImage(target, image, source);
+ }
+
+ m_frame.unmap();
+ } else if (m_frame.isValid()) {
+ return QAbstractVideoSurface::IncorrectFormatError;
+ } else {
+ painter->fillRect(target, Qt::black);
+ }
+ return QAbstractVideoSurface::NoError;
+}
+
+void QVideoSurfaceGenericPainter::updateColors(int, int, int, int)
+{
+}
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+
+#ifndef Q_WS_MAC
+# ifndef APIENTRYP
+# ifdef APIENTRY
+# define APIENTRYP APIENTRY *
+# else
+# define APIENTRY
+# define APIENTRYP *
+# endif
+# endif
+#else
+# define APIENTRY
+# define APIENTRYP *
+#endif
+
+#ifndef GL_TEXTURE0
+# define GL_TEXTURE0 0x84C0
+# define GL_TEXTURE1 0x84C1
+# define GL_TEXTURE2 0x84C2
+#endif
+#ifndef GL_PROGRAM_ERROR_STRING_ARB
+# define GL_PROGRAM_ERROR_STRING_ARB 0x8874
+#endif
+
+#ifndef GL_UNSIGNED_SHORT_5_6_5
+# define GL_UNSIGNED_SHORT_5_6_5 33635
+#endif
+
+class QVideoSurfaceGLPainter : public QVideoSurfacePainter
+{
+public:
+ QVideoSurfaceGLPainter(QGLContext *context);
+ ~QVideoSurfaceGLPainter();
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const;
+
+ bool isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const;
+
+ QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame);
+
+ QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source);
+
+ void updateColors(int brightness, int contrast, int hue, int saturation);
+ void viewportDestroyed();
+
+protected:
+ void initRgbTextureInfo(GLenum internalFormat, GLuint format, GLenum type, const QSize &size);
+ void initYuv420PTextureInfo(const QSize &size);
+ void initYv12TextureInfo(const QSize &size);
+
+#ifndef QT_OPENGL_ES
+ typedef void (APIENTRY *_glActiveTexture) (GLenum);
+ _glActiveTexture glActiveTexture;
+#endif
+
+ QList<QVideoFrame::PixelFormat> m_imagePixelFormats;
+ QList<QVideoFrame::PixelFormat> m_glPixelFormats;
+ QMatrix4x4 m_colorMatrix;
+ QVideoFrame m_frame;
+
+ QGLContext *m_context;
+ QAbstractVideoBuffer::HandleType m_handleType;
+ QVideoSurfaceFormat::Direction m_scanLineDirection;
+ QVideoSurfaceFormat::YCbCrColorSpace m_colorSpace;
+ GLenum m_textureFormat;
+ GLuint m_textureInternalFormat;
+ GLenum m_textureType;
+ int m_textureCount;
+ GLuint m_textureIds[3];
+ int m_textureWidths[3];
+ int m_textureHeights[3];
+ int m_textureOffsets[3];
+ bool m_yuv;
+};
+
+QVideoSurfaceGLPainter::QVideoSurfaceGLPainter(QGLContext *context)
+ : m_context(context)
+ , m_handleType(QAbstractVideoBuffer::NoHandle)
+ , m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
+ , m_colorSpace(QVideoSurfaceFormat::YCbCr_BT601)
+ , m_textureFormat(0)
+ , m_textureInternalFormat(0)
+ , m_textureType(0)
+ , m_textureCount(0)
+ , m_yuv(false)
+{
+#ifndef QT_OPENGL_ES
+ glActiveTexture = (_glActiveTexture)m_context->getProcAddress(QLatin1String("glActiveTexture"));
+#endif
+}
+
+QVideoSurfaceGLPainter::~QVideoSurfaceGLPainter()
+{
+}
+
+void QVideoSurfaceGLPainter::viewportDestroyed()
+{
+ m_context = 0;
+}
+
+QList<QVideoFrame::PixelFormat> QVideoSurfaceGLPainter::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ switch (handleType) {
+ case QAbstractVideoBuffer::NoHandle:
+ return m_imagePixelFormats;
+ case QAbstractVideoBuffer::QPixmapHandle:
+ case QAbstractVideoBuffer::GLTextureHandle:
+ return m_glPixelFormats;
+ default:
+ ;
+ }
+ return QList<QVideoFrame::PixelFormat>();
+}
+
+bool QVideoSurfaceGLPainter::isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *) const
+{
+ if (format.frameSize().isEmpty()) {
+ return false;
+ } else {
+ switch (format.handleType()) {
+ case QAbstractVideoBuffer::NoHandle:
+ return m_imagePixelFormats.contains(format.pixelFormat());
+ case QAbstractVideoBuffer::QPixmapHandle:
+ case QAbstractVideoBuffer::GLTextureHandle:
+ return m_glPixelFormats.contains(format.pixelFormat());
+ default:
+ ;
+ }
+ }
+ return false;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGLPainter::setCurrentFrame(const QVideoFrame &frame)
+{
+ m_frame = frame;
+
+ if (m_handleType == QAbstractVideoBuffer::GLTextureHandle) {
+ m_textureIds[0] = frame.handle().toInt();
+ } else if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) {
+ m_context->makeCurrent();
+
+ for (int i = 0; i < m_textureCount; ++i) {
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[i]);
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ m_textureInternalFormat,
+ m_textureWidths[i],
+ m_textureHeights[i],
+ 0,
+ m_textureFormat,
+ m_textureType,
+ m_frame.bits() + m_textureOffsets[i]);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ m_frame.unmap();
+ } else if (m_handleType != QAbstractVideoBuffer::QPixmapHandle && m_frame.isValid()) {
+ return QAbstractVideoSurface::IncorrectFormatError;
+ }
+
+ return QAbstractVideoSurface::NoError;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGLPainter::paint(
+ const QRectF &target, QPainter *painter, const QRectF &source)
+{
+ if (!m_frame.isValid()) {
+ painter->fillRect(target, Qt::black);
+ return QAbstractVideoSurface::NoError;
+ }
+
+ if (m_frame.handleType() == QAbstractVideoBuffer::QPixmapHandle) {
+ painter->drawPixmap(target, m_frame.handle().value<QPixmap>(), source);
+ } else if (m_frame.isValid()) {
+ return QAbstractVideoSurface::IncorrectFormatError;
+ } else {
+ painter->fillRect(target, Qt::black);
+ }
+ return QAbstractVideoSurface::NoError;
+}
+
+void QVideoSurfaceGLPainter::updateColors(int brightness, int contrast, int hue, int saturation)
+{
+ const qreal b = brightness / 200.0;
+ const qreal c = contrast / 100.0 + 1.0;
+ const qreal h = hue / 100.0;
+ const qreal s = saturation / 100.0 + 1.0;
+
+ const qreal cosH = qCos(M_PI * h);
+ const qreal sinH = qSin(M_PI * h);
+
+ const qreal h11 = 0.787 * cosH - 0.213 * sinH + 0.213;
+ const qreal h21 = -0.213 * cosH + 0.143 * sinH + 0.213;
+ const qreal h31 = -0.213 * cosH - 0.787 * sinH + 0.213;
+
+ const qreal h12 = -0.715 * cosH - 0.715 * sinH + 0.715;
+ const qreal h22 = 0.285 * cosH + 0.140 * sinH + 0.715;
+ const qreal h32 = -0.715 * cosH + 0.715 * sinH + 0.715;
+
+ const qreal h13 = -0.072 * cosH + 0.928 * sinH + 0.072;
+ const qreal h23 = -0.072 * cosH - 0.283 * sinH + 0.072;
+ const qreal h33 = 0.928 * cosH + 0.072 * sinH + 0.072;
+
+ const qreal sr = (1.0 - s) * 0.3086;
+ const qreal sg = (1.0 - s) * 0.6094;
+ const qreal sb = (1.0 - s) * 0.0820;
+
+ const qreal sr_s = sr + s;
+ const qreal sg_s = sg + s;
+ const qreal sb_s = sr + s;
+
+ const float m4 = (s + sr + sg + sb) * (0.5 - 0.5 * c + b);
+
+ m_colorMatrix(0, 0) = c * (sr_s * h11 + sg * h21 + sb * h31);
+ m_colorMatrix(0, 1) = c * (sr_s * h12 + sg * h22 + sb * h32);
+ m_colorMatrix(0, 2) = c * (sr_s * h13 + sg * h23 + sb * h33);
+ m_colorMatrix(0, 3) = m4;
+
+ m_colorMatrix(1, 0) = c * (sr * h11 + sg_s * h21 + sb * h31);
+ m_colorMatrix(1, 1) = c * (sr * h12 + sg_s * h22 + sb * h32);
+ m_colorMatrix(1, 2) = c * (sr * h13 + sg_s * h23 + sb * h33);
+ m_colorMatrix(1, 3) = m4;
+
+ m_colorMatrix(2, 0) = c * (sr * h11 + sg * h21 + sb_s * h31);
+ m_colorMatrix(2, 1) = c * (sr * h12 + sg * h22 + sb_s * h32);
+ m_colorMatrix(2, 2) = c * (sr * h13 + sg * h23 + sb_s * h33);
+ m_colorMatrix(2, 3) = m4;
+
+ m_colorMatrix(3, 0) = 0.0;
+ m_colorMatrix(3, 1) = 0.0;
+ m_colorMatrix(3, 2) = 0.0;
+ m_colorMatrix(3, 3) = 1.0;
+
+ if (m_yuv) {
+ QMatrix4x4 colorSpaceMatrix;
+
+ switch (m_colorSpace) {
+ case QVideoSurfaceFormat::YCbCr_JPEG:
+ colorSpaceMatrix = QMatrix4x4(
+ 1.0, 0.000, 1.402, -0.701,
+ 1.0, -0.344, -0.714, 0.529,
+ 1.0, 1.772, 0.000, -0.886,
+ 0.0, 0.000, 0.000, 1.0000);
+ break;
+ case QVideoSurfaceFormat::YCbCr_BT709:
+ case QVideoSurfaceFormat::YCbCr_xvYCC709:
+ colorSpaceMatrix = QMatrix4x4(
+ 1.164, 0.000, 1.793, -0.5727,
+ 1.164, -0.534, -0.213, 0.3007,
+ 1.164, 2.115, 0.000, -1.1302,
+ 0.0, 0.000, 0.000, 1.0000);
+ break;
+ default: //BT 601:
+ colorSpaceMatrix = QMatrix4x4(
+ 1.164, 0.000, 1.596, -0.8708,
+ 1.164, -0.392, -0.813, 0.5296,
+ 1.164, 2.017, 0.000, -1.081,
+ 0.0, 0.000, 0.000, 1.0000);
+ }
+
+ m_colorMatrix = m_colorMatrix * colorSpaceMatrix;
+ }
+}
+
+void QVideoSurfaceGLPainter::initRgbTextureInfo(
+ GLenum internalFormat, GLuint format, GLenum type, const QSize &size)
+{
+ m_yuv = false;
+ m_textureInternalFormat = internalFormat;
+ m_textureFormat = format;
+ m_textureType = type;
+ m_textureCount = 1;
+ m_textureWidths[0] = size.width();
+ m_textureHeights[0] = size.height();
+ m_textureOffsets[0] = 0;
+}
+
+void QVideoSurfaceGLPainter::initYuv420PTextureInfo(const QSize &size)
+{
+ int bytesPerLine = (size.width() + 3) & ~3;
+ int bytesPerLine2 = (size.width() / 2 + 3) & ~3;
+
+ m_yuv = true;
+ m_textureInternalFormat = GL_LUMINANCE;
+ m_textureFormat = GL_LUMINANCE;
+ m_textureType = GL_UNSIGNED_BYTE;
+ m_textureCount = 3;
+ m_textureWidths[0] = bytesPerLine;
+ m_textureHeights[0] = size.height();
+ m_textureOffsets[0] = 0;
+ m_textureWidths[1] = bytesPerLine2;
+ m_textureHeights[1] = size.height() / 2;
+ m_textureOffsets[1] = bytesPerLine * size.height();
+ m_textureWidths[2] = bytesPerLine2;
+ m_textureHeights[2] = size.height() / 2;
+ m_textureOffsets[2] = bytesPerLine * size.height() + bytesPerLine2 * size.height()/2;
+}
+
+void QVideoSurfaceGLPainter::initYv12TextureInfo(const QSize &size)
+{
+ int bytesPerLine = (size.width() + 3) & ~3;
+ int bytesPerLine2 = (size.width() / 2 + 3) & ~3;
+
+ m_yuv = true;
+ m_textureInternalFormat = GL_LUMINANCE;
+ m_textureFormat = GL_LUMINANCE;
+ m_textureType = GL_UNSIGNED_BYTE;
+ m_textureCount = 3;
+ m_textureWidths[0] = bytesPerLine;
+ m_textureHeights[0] = size.height();
+ m_textureOffsets[0] = 0;
+ m_textureWidths[1] = bytesPerLine2;
+ m_textureHeights[1] = size.height() / 2;
+ m_textureOffsets[1] = bytesPerLine * size.height() + bytesPerLine2 * size.height()/2;
+ m_textureWidths[2] = bytesPerLine2;
+ m_textureHeights[2] = size.height() / 2;
+ m_textureOffsets[2] = bytesPerLine * size.height();
+}
+
+#ifndef QT_OPENGL_ES
+
+# ifndef GL_FRAGMENT_PROGRAM_ARB
+# define GL_FRAGMENT_PROGRAM_ARB 0x8804
+# define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+# endif
+
+// Paints an RGB32 frame
+static const char *qt_arbfp_xrgbShaderProgram =
+ "!!ARBfp1.0\n"
+ "PARAM matrix[4] = { program.local[0..2],"
+ "{ 0.0, 0.0, 0.0, 1.0 } };\n"
+ "TEMP xrgb;\n"
+ "TEX xrgb.xyz, fragment.texcoord[0], texture[0], 2D;\n"
+ "MOV xrgb.w, matrix[3].w;\n"
+ "DP4 result.color.x, xrgb.zyxw, matrix[0];\n"
+ "DP4 result.color.y, xrgb.zyxw, matrix[1];\n"
+ "DP4 result.color.z, xrgb.zyxw, matrix[2];\n"
+ "END";
+
+// Paints an ARGB frame.
+static const char *qt_arbfp_argbShaderProgram =
+ "!!ARBfp1.0\n"
+ "PARAM matrix[4] = { program.local[0..2],"
+ "{ 0.0, 0.0, 0.0, 1.0 } };\n"
+ "TEMP argb;\n"
+ "TEX argb, fragment.texcoord[0], texture[0], 2D;\n"
+ "MOV argb.w, matrix[3].w;\n"
+ "DP4 result.color.x, argb.zyxw, matrix[0];\n"
+ "DP4 result.color.y, argb.zyxw, matrix[1];\n"
+ "DP4 result.color.z, argb.zyxw, matrix[2];\n"
+ "TEX result.color.w, fragment.texcoord[0], texture, 2D;\n"
+ "END";
+
+// Paints an RGB(A) frame.
+static const char *qt_arbfp_rgbShaderProgram =
+ "!!ARBfp1.0\n"
+ "PARAM matrix[4] = { program.local[0..2],"
+ "{ 0.0, 0.0, 0.0, 1.0 } };\n"
+ "TEMP rgb;\n"
+ "TEX rgb, fragment.texcoord[0], texture[0], 2D;\n"
+ "MOV rgb.w, matrix[3].w;\n"
+ "DP4 result.color.x, rgb, matrix[0];\n"
+ "DP4 result.color.y, rgb, matrix[1];\n"
+ "DP4 result.color.z, rgb, matrix[2];\n"
+ "TEX result.color.w, fragment.texcoord[0], texture, 2D;\n"
+ "END";
+
+// Paints a YUV420P or YV12 frame.
+static const char *qt_arbfp_yuvPlanarShaderProgram =
+ "!!ARBfp1.0\n"
+ "PARAM matrix[4] = { program.local[0..2],"
+ "{ 0.0, 0.0, 0.0, 1.0 } };\n"
+ "TEMP yuv;\n"
+ "TEX yuv.x, fragment.texcoord[0], texture[0], 2D;\n"
+ "TEX yuv.y, fragment.texcoord[0], texture[1], 2D;\n"
+ "TEX yuv.z, fragment.texcoord[0], texture[2], 2D;\n"
+ "MOV yuv.w, matrix[3].w;\n"
+ "DP4 result.color.x, yuv, matrix[0];\n"
+ "DP4 result.color.y, yuv, matrix[1];\n"
+ "DP4 result.color.z, yuv, matrix[2];\n"
+ "END";
+
+// Paints a YUV444 frame.
+static const char *qt_arbfp_xyuvShaderProgram =
+ "!!ARBfp1.0\n"
+ "PARAM matrix[4] = { program.local[0..2],"
+ "{ 0.0, 0.0, 0.0, 1.0 } };\n"
+ "TEMP ayuv;\n"
+ "TEX ayuv, fragment.texcoord[0], texture[0], 2D;\n"
+ "MOV ayuv.x, matrix[3].w;\n"
+ "DP4 result.color.x, ayuv.yzwx, matrix[0];\n"
+ "DP4 result.color.y, ayuv.yzwx, matrix[1];\n"
+ "DP4 result.color.z, ayuv.yzwx, matrix[2];\n"
+ "END";
+
+// Paints a AYUV444 frame.
+static const char *qt_arbfp_ayuvShaderProgram =
+ "!!ARBfp1.0\n"
+ "PARAM matrix[4] = { program.local[0..2],"
+ "{ 0.0, 0.0, 0.0, 1.0 } };\n"
+ "TEMP ayuv;\n"
+ "TEX ayuv, fragment.texcoord[0], texture[0], 2D;\n"
+ "MOV ayuv.x, matrix[3].w;\n"
+ "DP4 result.color.x, ayuv.yzwx, matrix[0];\n"
+ "DP4 result.color.y, ayuv.yzwx, matrix[1];\n"
+ "DP4 result.color.z, ayuv.yzwx, matrix[2];\n"
+ "TEX result.color.w, fragment.texcoord[0], texture, 2D;\n"
+ "END";
+
+class QVideoSurfaceArbFpPainter : public QVideoSurfaceGLPainter
+{
+public:
+ QVideoSurfaceArbFpPainter(QGLContext *context);
+
+ QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source);
+
+private:
+ typedef void (APIENTRY *_glProgramStringARB) (GLenum, GLenum, GLsizei, const GLvoid *);
+ typedef void (APIENTRY *_glBindProgramARB) (GLenum, GLuint);
+ typedef void (APIENTRY *_glDeleteProgramsARB) (GLsizei, const GLuint *);
+ typedef void (APIENTRY *_glGenProgramsARB) (GLsizei, GLuint *);
+ typedef void (APIENTRY *_glProgramLocalParameter4fARB) (
+ GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+ typedef void (APIENTRY *_glActiveTexture) (GLenum);
+
+ _glProgramStringARB glProgramStringARB;
+ _glBindProgramARB glBindProgramARB;
+ _glDeleteProgramsARB glDeleteProgramsARB;
+ _glGenProgramsARB glGenProgramsARB;
+ _glProgramLocalParameter4fARB glProgramLocalParameter4fARB;
+
+ GLuint m_programId;
+ QSize m_frameSize;
+};
+
+QVideoSurfaceArbFpPainter::QVideoSurfaceArbFpPainter(QGLContext *context)
+ : QVideoSurfaceGLPainter(context)
+ , m_programId(0)
+{
+ glProgramStringARB = (_glProgramStringARB) m_context->getProcAddress(
+ QLatin1String("glProgramStringARB"));
+ glBindProgramARB = (_glBindProgramARB) m_context->getProcAddress(
+ QLatin1String("glBindProgramARB"));
+ glDeleteProgramsARB = (_glDeleteProgramsARB) m_context->getProcAddress(
+ QLatin1String("glDeleteProgramsARB"));
+ glGenProgramsARB = (_glGenProgramsARB) m_context->getProcAddress(
+ QLatin1String("glGenProgramsARB"));
+ glProgramLocalParameter4fARB = (_glProgramLocalParameter4fARB) m_context->getProcAddress(
+ QLatin1String("glProgramLocalParameter4fARB"));
+
+ m_imagePixelFormats
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_BGR32
+ << QVideoFrame::Format_ARGB32
+ << QVideoFrame::Format_RGB24
+ << QVideoFrame::Format_BGR24
+ << QVideoFrame::Format_RGB565
+ << QVideoFrame::Format_AYUV444
+ << QVideoFrame::Format_YUV444
+ << QVideoFrame::Format_YV12
+ << QVideoFrame::Format_YUV420P;
+ m_glPixelFormats
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_ARGB32;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::start(const QVideoSurfaceFormat &format)
+{
+ Q_ASSERT(m_textureCount == 0);
+
+ QAbstractVideoSurface::Error error = QAbstractVideoSurface::NoError;
+
+ m_context->makeCurrent();
+
+ const char *program = 0;
+
+ if (format.handleType() == QAbstractVideoBuffer::NoHandle) {
+ switch (format.pixelFormat()) {
+ case QVideoFrame::Format_RGB32:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_xrgbShaderProgram;
+ break;
+ case QVideoFrame::Format_BGR32:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_rgbShaderProgram;
+ break;
+ case QVideoFrame::Format_ARGB32:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_argbShaderProgram;
+ break;
+ case QVideoFrame::Format_RGB24:
+ initRgbTextureInfo(GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_rgbShaderProgram;
+ break;
+ case QVideoFrame::Format_BGR24:
+ initRgbTextureInfo(GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_xrgbShaderProgram;
+ break;
+ case QVideoFrame::Format_RGB565:
+ initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize());
+ program = qt_arbfp_rgbShaderProgram;
+ break;
+ case QVideoFrame::Format_YUV444:
+ initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_xyuvShaderProgram;
+ m_yuv = true;
+ break;
+ case QVideoFrame::Format_AYUV444:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ program = qt_arbfp_ayuvShaderProgram;
+ m_yuv = true;
+ break;
+ case QVideoFrame::Format_YV12:
+ initYv12TextureInfo(format.frameSize());
+ program = qt_arbfp_yuvPlanarShaderProgram;
+ break;
+ case QVideoFrame::Format_YUV420P:
+ initYuv420PTextureInfo(format.frameSize());
+ program = qt_arbfp_yuvPlanarShaderProgram;
+ break;
+ default:
+ break;
+ }
+ } else if (format.handleType() == QAbstractVideoBuffer::GLTextureHandle) {
+ switch (format.pixelFormat()) {
+ case QVideoFrame::Format_RGB32:
+ case QVideoFrame::Format_ARGB32:
+ m_yuv = false;
+ m_textureCount = 1;
+ program = qt_arbfp_rgbShaderProgram;
+ break;
+ default:
+ break;
+ }
+ } else if (format.handleType() == QAbstractVideoBuffer::QPixmapHandle) {
+ m_handleType = QAbstractVideoBuffer::QPixmapHandle;
+ return QAbstractVideoSurface::NoError;
+ }
+
+ if (!program) {
+ error = QAbstractVideoSurface::UnsupportedFormatError;
+ } else {
+ glGenProgramsARB(1, &m_programId);
+
+ GLenum glError = glGetError();
+ if (glError != GL_NO_ERROR) {
+ qWarning("QPainterVideoSurface: ARBfb Shader allocation error %x", int(glError));
+ m_textureCount = 0;
+ m_programId = 0;
+
+ error = QAbstractVideoSurface::ResourceError;
+ } else {
+ glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_programId);
+ glProgramStringARB(
+ GL_FRAGMENT_PROGRAM_ARB,
+ GL_PROGRAM_FORMAT_ASCII_ARB,
+ qstrlen(program),
+ reinterpret_cast<const GLvoid *>(program));
+
+ if ((glError = glGetError()) != GL_NO_ERROR) {
+ const GLubyte* errorString = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
+
+ qWarning("QPainterVideoSurface: ARBfp Shader compile error %x, %s",
+ int(glError),
+ reinterpret_cast<const char *>(errorString));
+ glDeleteProgramsARB(1, &m_programId);
+
+ m_textureCount = 0;
+ m_programId = 0;
+
+ error = QAbstractVideoSurface::ResourceError;
+ } else {
+ m_handleType = format.handleType();
+ m_scanLineDirection = format.scanLineDirection();
+ m_frameSize = format.frameSize();
+ m_colorSpace = format.yCbCrColorSpace();
+
+ if (m_handleType == QAbstractVideoBuffer::NoHandle)
+ glGenTextures(m_textureCount, m_textureIds);
+ }
+ }
+ }
+
+ return error;
+}
+
+void QVideoSurfaceArbFpPainter::stop()
+{
+ if (m_context) {
+ m_context->makeCurrent();
+
+ if (m_handleType != QAbstractVideoBuffer::GLTextureHandle)
+ glDeleteTextures(m_textureCount, m_textureIds);
+ glDeleteProgramsARB(1, &m_programId);
+ }
+
+ m_textureCount = 0;
+ m_programId = 0;
+ m_handleType = QAbstractVideoBuffer::NoHandle;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::paint(
+ const QRectF &target, QPainter *painter, const QRectF &source)
+{
+ if (!m_frame.isValid()) {
+ painter->fillRect(target, Qt::black);
+ return QAbstractVideoSurface::NoError;
+ }
+
+ const QAbstractVideoBuffer::HandleType h = m_frame.handleType();
+ if (h == QAbstractVideoBuffer::NoHandle || h == QAbstractVideoBuffer::GLTextureHandle) {
+ bool stencilTestEnabled = glIsEnabled(GL_STENCIL_TEST);
+ bool scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
+
+ painter->beginNativePainting();
+
+ if (stencilTestEnabled)
+ glEnable(GL_STENCIL_TEST);
+ if (scissorTestEnabled)
+ glEnable(GL_SCISSOR_TEST);
+
+ const float txLeft = source.left() / m_frameSize.width();
+ const float txRight = source.right() / m_frameSize.width();
+ const float txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.top() / m_frameSize.height()
+ : source.bottom() / m_frameSize.height();
+ const float txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.bottom() / m_frameSize.height()
+ : source.top() / m_frameSize.height();
+
+ const float tx_array[] =
+ {
+ txLeft , txBottom,
+ txRight, txBottom,
+ txLeft , txTop,
+ txRight, txTop
+ };
+
+ const GLfloat vTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? target.top()
+ : target.bottom() + 1;
+ const GLfloat vBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? target.bottom() + 1
+ : target.top();
+
+ const GLfloat v_array[] =
+ {
+ GLfloat(target.left()) , GLfloat(vBottom),
+ GLfloat(target.right() + 1), GLfloat(vBottom),
+ GLfloat(target.left()) , GLfloat(vTop),
+ GLfloat(target.right() + 1), GLfloat(vTop)
+ };
+
+ glEnable(GL_FRAGMENT_PROGRAM_ARB);
+ glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_programId);
+
+ glProgramLocalParameter4fARB(
+ GL_FRAGMENT_PROGRAM_ARB,
+ 0,
+ m_colorMatrix(0, 0),
+ m_colorMatrix(0, 1),
+ m_colorMatrix(0, 2),
+ m_colorMatrix(0, 3));
+ glProgramLocalParameter4fARB(
+ GL_FRAGMENT_PROGRAM_ARB,
+ 1,
+ m_colorMatrix(1, 0),
+ m_colorMatrix(1, 1),
+ m_colorMatrix(1, 2),
+ m_colorMatrix(1, 3));
+ glProgramLocalParameter4fARB(
+ GL_FRAGMENT_PROGRAM_ARB,
+ 2,
+ m_colorMatrix(2, 0),
+ m_colorMatrix(2, 1),
+ m_colorMatrix(2, 2),
+ m_colorMatrix(2, 3));
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
+
+ if (m_textureCount == 3) {
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[1]);
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[2]);
+ glActiveTexture(GL_TEXTURE0);
+ }
+
+ glVertexPointer(2, GL_FLOAT, 0, v_array);
+ glTexCoordPointer(2, GL_FLOAT, 0, tx_array);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisable(GL_FRAGMENT_PROGRAM_ARB);
+
+ painter->endNativePainting();
+
+ return QAbstractVideoSurface::NoError;
+ }
+
+ return QVideoSurfaceGLPainter::paint(target, painter, source);
+}
+
+#endif
+
+static const char *qt_glsl_vertexShaderProgram =
+ "attribute highp vec4 vertexCoordArray;\n"
+ "attribute highp vec2 textureCoordArray;\n"
+ "uniform highp mat4 positionMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = positionMatrix * vertexCoordArray;\n"
+ " textureCoord = textureCoordArray;\n"
+ "}\n";
+
+// Paints an RGB32 frame
+static const char *qt_glsl_xrgbShaderProgram =
+ "uniform sampler2D texRgb;\n"
+ "uniform mediump mat4 colorMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).bgr, 1.0);\n"
+ " gl_FragColor = colorMatrix * color;\n"
+ "}\n";
+
+// Paints an ARGB frame.
+static const char *qt_glsl_argbShaderProgram =
+ "uniform sampler2D texRgb;\n"
+ "uniform mediump mat4 colorMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).bgr, 1.0);\n"
+ " color = colorMatrix * color;\n"
+ " gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).a);\n"
+ "}\n";
+
+// Paints an RGB(A) frame.
+static const char *qt_glsl_rgbShaderProgram =
+ "uniform sampler2D texRgb;\n"
+ "uniform mediump mat4 colorMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).rgb, 1.0);\n"
+ " color = colorMatrix * color;\n"
+ " gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).a);\n"
+ "}\n";
+
+// Paints a YUV420P or YV12 frame.
+static const char *qt_glsl_yuvPlanarShaderProgram =
+ "uniform sampler2D texY;\n"
+ "uniform sampler2D texU;\n"
+ "uniform sampler2D texV;\n"
+ "uniform mediump mat4 colorMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " highp vec4 color = vec4(\n"
+ " texture2D(texY, textureCoord.st).r,\n"
+ " texture2D(texU, textureCoord.st).r,\n"
+ " texture2D(texV, textureCoord.st).r,\n"
+ " 1.0);\n"
+ " gl_FragColor = colorMatrix * color;\n"
+ "}\n";
+
+// Paints a YUV444 frame.
+static const char *qt_glsl_xyuvShaderProgram =
+ "uniform sampler2D texRgb;\n"
+ "uniform mediump mat4 colorMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).gba, 1.0);\n"
+ " gl_FragColor = colorMatrix * color;\n"
+ "}\n";
+
+// Paints a AYUV444 frame.
+static const char *qt_glsl_ayuvShaderProgram =
+ "uniform sampler2D texRgb;\n"
+ "uniform mediump mat4 colorMatrix;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main(void)\n"
+ "{\n"
+ " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).gba, 1.0);\n"
+ " color = colorMatrix * color;\n"
+ " gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).r);\n"
+ "}\n";
+
+class QVideoSurfaceGlslPainter : public QVideoSurfaceGLPainter
+{
+public:
+ QVideoSurfaceGlslPainter(QGLContext *context);
+
+ QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source);
+
+private:
+ QGLShaderProgram m_program;
+ QSize m_frameSize;
+};
+
+QVideoSurfaceGlslPainter::QVideoSurfaceGlslPainter(QGLContext *context)
+ : QVideoSurfaceGLPainter(context)
+ , m_program(context)
+{
+ m_imagePixelFormats
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_BGR32
+ << QVideoFrame::Format_ARGB32
+#ifndef QT_OPENGL_ES
+ << QVideoFrame::Format_RGB24
+ << QVideoFrame::Format_BGR24
+#endif
+ << QVideoFrame::Format_RGB565
+ << QVideoFrame::Format_YUV444
+ << QVideoFrame::Format_AYUV444
+ << QVideoFrame::Format_YV12
+ << QVideoFrame::Format_YUV420P;
+ m_glPixelFormats
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_ARGB32;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurfaceFormat &format)
+{
+ Q_ASSERT(m_textureCount == 0);
+
+ QAbstractVideoSurface::Error error = QAbstractVideoSurface::NoError;
+
+ m_context->makeCurrent();
+
+ const char *fragmentProgram = 0;
+
+ if (format.handleType() == QAbstractVideoBuffer::NoHandle) {
+ switch (format.pixelFormat()) {
+ case QVideoFrame::Format_RGB32:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_xrgbShaderProgram;
+ break;
+ case QVideoFrame::Format_BGR32:
+ initRgbTextureInfo(GL_RGB, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_rgbShaderProgram;
+ break;
+ case QVideoFrame::Format_ARGB32:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_argbShaderProgram;
+ break;
+#ifndef QT_OPENGL_ES
+ case QVideoFrame::Format_RGB24:
+ initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_rgbShaderProgram;
+ break;
+ case QVideoFrame::Format_BGR24:
+ initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_argbShaderProgram;
+ break;
+#endif
+ case QVideoFrame::Format_RGB565:
+ initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize());
+ fragmentProgram = qt_glsl_rgbShaderProgram;
+ break;
+ case QVideoFrame::Format_YUV444:
+ initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_xyuvShaderProgram;
+ m_yuv = true;
+ break;
+ case QVideoFrame::Format_AYUV444:
+ initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
+ fragmentProgram = qt_glsl_ayuvShaderProgram;
+ m_yuv = true;
+ break;
+ case QVideoFrame::Format_YV12:
+ initYv12TextureInfo(format.frameSize());
+ fragmentProgram = qt_glsl_yuvPlanarShaderProgram;
+ break;
+ case QVideoFrame::Format_YUV420P:
+ initYuv420PTextureInfo(format.frameSize());
+ fragmentProgram = qt_glsl_yuvPlanarShaderProgram;
+ break;
+ default:
+ break;
+ }
+ } else if (format.handleType() == QAbstractVideoBuffer::GLTextureHandle) {
+ switch (format.pixelFormat()) {
+ case QVideoFrame::Format_RGB32:
+ case QVideoFrame::Format_ARGB32:
+ m_yuv = false;
+ m_textureCount = 1;
+ fragmentProgram = qt_glsl_rgbShaderProgram;
+ break;
+ default:
+ break;
+ }
+ } else if (format.handleType() == QAbstractVideoBuffer::QPixmapHandle) {
+ m_handleType = QAbstractVideoBuffer::QPixmapHandle;
+ return QAbstractVideoSurface::NoError;
+ }
+
+ if (!fragmentProgram) {
+ error = QAbstractVideoSurface::UnsupportedFormatError;
+ } else if (!m_program.addShaderFromSourceCode(QGLShader::Vertex, qt_glsl_vertexShaderProgram)) {
+ qWarning("QPainterVideoSurface: Vertex shader compile error %s",
+ qPrintable(m_program.log()));
+ error = QAbstractVideoSurface::ResourceError;
+ } else if (!m_program.addShaderFromSourceCode(QGLShader::Fragment, fragmentProgram)) {
+ qWarning("QPainterVideoSurface: Shader compile error %s", qPrintable(m_program.log()));
+ error = QAbstractVideoSurface::ResourceError;
+ m_program.removeAllShaders();
+ } else if(!m_program.link()) {
+ qWarning("QPainterVideoSurface: Shader link error %s", qPrintable(m_program.log()));
+ m_program.removeAllShaders();
+ error = QAbstractVideoSurface::ResourceError;
+ } else {
+ m_handleType = format.handleType();
+ m_scanLineDirection = format.scanLineDirection();
+ m_frameSize = format.frameSize();
+ m_colorSpace = format.yCbCrColorSpace();
+
+ if (m_handleType == QAbstractVideoBuffer::NoHandle)
+ glGenTextures(m_textureCount, m_textureIds);
+ }
+
+ return error;
+}
+
+void QVideoSurfaceGlslPainter::stop()
+{
+ if (m_context) {
+ m_context->makeCurrent();
+
+ if (m_handleType != QAbstractVideoBuffer::GLTextureHandle)
+ glDeleteTextures(m_textureCount, m_textureIds);
+ }
+
+ m_program.removeAllShaders();
+
+ m_textureCount = 0;
+ m_handleType = QAbstractVideoBuffer::NoHandle;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::paint(
+ const QRectF &target, QPainter *painter, const QRectF &source)
+{
+ if (!m_frame.isValid()) {
+ painter->fillRect(target, Qt::black);
+ return QAbstractVideoSurface::NoError;
+ }
+
+ const QAbstractVideoBuffer::HandleType h = m_frame.handleType();
+ if (h == QAbstractVideoBuffer::NoHandle || h == QAbstractVideoBuffer::GLTextureHandle) {
+ bool stencilTestEnabled = glIsEnabled(GL_STENCIL_TEST);
+ bool scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
+
+ painter->beginNativePainting();
+
+ if (stencilTestEnabled)
+ glEnable(GL_STENCIL_TEST);
+ if (scissorTestEnabled)
+ glEnable(GL_SCISSOR_TEST);
+
+ const int width = QGLContext::currentContext()->device()->width();
+ const int height = QGLContext::currentContext()->device()->height();
+
+ const QTransform transform = painter->deviceTransform();
+
+ const GLfloat wfactor = 2.0 / width;
+ const GLfloat hfactor = -2.0 / height;
+
+ const GLfloat positionMatrix[4][4] =
+ {
+ {
+ /*(0,0)*/ GLfloat(wfactor * transform.m11() - transform.m13()),
+ /*(0,1)*/ GLfloat(hfactor * transform.m12() + transform.m13()),
+ /*(0,2)*/ 0.0,
+ /*(0,3)*/ GLfloat(transform.m13())
+ }, {
+ /*(1,0)*/ GLfloat(wfactor * transform.m21() - transform.m23()),
+ /*(1,1)*/ GLfloat(hfactor * transform.m22() + transform.m23()),
+ /*(1,2)*/ 0.0,
+ /*(1,3)*/ GLfloat(transform.m23())
+ }, {
+ /*(2,0)*/ 0.0,
+ /*(2,1)*/ 0.0,
+ /*(2,2)*/ -1.0,
+ /*(2,3)*/ 0.0
+ }, {
+ /*(3,0)*/ GLfloat(wfactor * transform.dx() - transform.m33()),
+ /*(3,1)*/ GLfloat(hfactor * transform.dy() + transform.m33()),
+ /*(3,2)*/ 0.0,
+ /*(3,3)*/ GLfloat(transform.m33())
+ }
+ };
+
+ const GLfloat vTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? target.top()
+ : target.bottom() + 1;
+ const GLfloat vBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? target.bottom() + 1
+ : target.top();
+
+
+ const GLfloat vertexCoordArray[] =
+ {
+ GLfloat(target.left()) , GLfloat(vBottom),
+ GLfloat(target.right() + 1), GLfloat(vBottom),
+ GLfloat(target.left()) , GLfloat(vTop),
+ GLfloat(target.right() + 1), GLfloat(vTop)
+ };
+
+ const GLfloat txLeft = source.left() / m_frameSize.width();
+ const GLfloat txRight = source.right() / m_frameSize.width();
+ const GLfloat txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.top() / m_frameSize.height()
+ : source.bottom() / m_frameSize.height();
+ const GLfloat txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.bottom() / m_frameSize.height()
+ : source.top() / m_frameSize.height();
+
+ const GLfloat textureCoordArray[] =
+ {
+ txLeft , txBottom,
+ txRight, txBottom,
+ txLeft , txTop,
+ txRight, txTop
+ };
+
+ m_program.bind();
+
+ m_program.enableAttributeArray("vertexCoordArray");
+ m_program.enableAttributeArray("textureCoordArray");
+ m_program.setAttributeArray("vertexCoordArray", vertexCoordArray, 2);
+ m_program.setAttributeArray("textureCoordArray", textureCoordArray, 2);
+ m_program.setUniformValue("positionMatrix", positionMatrix);
+
+ if (m_textureCount == 3) {
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[1]);
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[2]);
+ glActiveTexture(GL_TEXTURE0);
+
+ m_program.setUniformValue("texY", 0);
+ m_program.setUniformValue("texU", 1);
+ m_program.setUniformValue("texV", 2);
+ } else {
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);
+
+ m_program.setUniformValue("texRgb", 0);
+ }
+ m_program.setUniformValue("colorMatrix", m_colorMatrix);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ m_program.release();
+
+ painter->endNativePainting();
+
+ return QAbstractVideoSurface::NoError;
+ }
+
+ return QVideoSurfaceGLPainter::paint(target, painter, source);
+}
+
+#endif
+
+/*!
+ \class QPainterVideoSurface
+ \since 1.0
+ \internal
+*/
+
+/*!
+*/
+QPainterVideoSurface::QPainterVideoSurface(QObject *parent)
+ : QAbstractVideoSurface(parent)
+ , m_painter(0)
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ , m_glContext(0)
+ , m_shaderTypes(NoShaders)
+ , m_shaderType(NoShaders)
+#endif
+ , m_brightness(0)
+ , m_contrast(0)
+ , m_hue(0)
+ , m_saturation(0)
+ , m_pixelFormat(QVideoFrame::Format_Invalid)
+ , m_colorsDirty(true)
+ , m_ready(false)
+{
+}
+
+/*!
+*/
+QPainterVideoSurface::~QPainterVideoSurface()
+{
+ if (isActive())
+ m_painter->stop();
+
+ delete m_painter;
+}
+
+/*!
+ \since 1.0
+*/
+QList<QVideoFrame::PixelFormat> QPainterVideoSurface::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ if (!m_painter)
+ const_cast<QPainterVideoSurface *>(this)->createPainter();
+
+ return m_painter->supportedPixelFormats(handleType);
+}
+
+/*!
+ \since 1.0
+*/
+bool QPainterVideoSurface::isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const
+{
+ if (!m_painter)
+ const_cast<QPainterVideoSurface *>(this)->createPainter();
+
+ return m_painter->isFormatSupported(format, similar);
+}
+
+/*!
+ \since 1.0
+*/
+bool QPainterVideoSurface::start(const QVideoSurfaceFormat &format)
+{
+ if (isActive())
+ m_painter->stop();
+
+ if (!m_painter)
+ createPainter();
+
+ if (format.frameSize().isEmpty()) {
+ setError(UnsupportedFormatError);
+ } else {
+ QAbstractVideoSurface::Error error = m_painter->start(format);
+
+ if (error != QAbstractVideoSurface::NoError) {
+ setError(error);
+ } else {
+ m_pixelFormat = format.pixelFormat();
+ m_frameSize = format.frameSize();
+ m_sourceRect = format.viewport();
+ m_colorsDirty = true;
+ m_ready = true;
+
+ return QAbstractVideoSurface::start(format);
+ }
+ }
+
+ QAbstractVideoSurface::stop();
+
+ return false;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::stop()
+{
+ if (isActive()) {
+ m_painter->stop();
+ m_ready = false;
+
+ QAbstractVideoSurface::stop();
+ }
+}
+
+/*!
+ \since 1.0
+*/
+bool QPainterVideoSurface::present(const QVideoFrame &frame)
+{
+ if (!m_ready) {
+ if (!isActive())
+ setError(StoppedError);
+ } else if (frame.isValid()
+ && (frame.pixelFormat() != m_pixelFormat || frame.size() != m_frameSize)) {
+ setError(IncorrectFormatError);
+
+ stop();
+ } else {
+ QAbstractVideoSurface::Error error = m_painter->setCurrentFrame(frame);
+
+ if (error != QAbstractVideoSurface::NoError) {
+ setError(error);
+
+ stop();
+ } else {
+ m_ready = false;
+
+ emit frameChanged();
+
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
+ \since 1.0
+*/
+int QPainterVideoSurface::brightness() const
+{
+ return m_brightness;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::setBrightness(int brightness)
+{
+ m_brightness = brightness;
+
+ m_colorsDirty = true;
+}
+
+/*!
+ \since 1.0
+*/
+int QPainterVideoSurface::contrast() const
+{
+ return m_contrast;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::setContrast(int contrast)
+{
+ m_contrast = contrast;
+
+ m_colorsDirty = true;
+}
+
+/*!
+ \since 1.0
+*/
+int QPainterVideoSurface::hue() const
+{
+ return m_hue;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::setHue(int hue)
+{
+ m_hue = hue;
+
+ m_colorsDirty = true;
+}
+
+/*!
+ \since 1.0
+*/
+int QPainterVideoSurface::saturation() const
+{
+ return m_saturation;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::setSaturation(int saturation)
+{
+ m_saturation = saturation;
+
+ m_colorsDirty = true;
+}
+
+/*!
+ \since 1.0
+*/
+bool QPainterVideoSurface::isReady() const
+{
+ return m_ready;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::setReady(bool ready)
+{
+ m_ready = ready;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::paint(QPainter *painter, const QRectF &target, const QRectF &source)
+{
+ if (!isActive()) {
+ painter->fillRect(target, QBrush(Qt::black));
+ } else {
+ if (m_colorsDirty) {
+ m_painter->updateColors(m_brightness, m_contrast, m_hue, m_saturation);
+ m_colorsDirty = false;
+ }
+
+ const QRectF sourceRect(
+ m_sourceRect.x() + m_sourceRect.width() * source.x(),
+ m_sourceRect.y() + m_sourceRect.height() * source.y(),
+ m_sourceRect.width() * source.width(),
+ m_sourceRect.height() * source.height());
+
+ QAbstractVideoSurface::Error error = m_painter->paint(target, painter, sourceRect);
+
+ if (error != QAbstractVideoSurface::NoError) {
+ setError(error);
+
+ stop();
+ }
+ }
+}
+
+/*!
+ \fn QPainterVideoSurface::frameChanged()
+ \since 1.0
+*/
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+
+/*!
+*/
+const QGLContext *QPainterVideoSurface::glContext() const
+{
+ return m_glContext;
+}
+
+/*!
+*/
+void QPainterVideoSurface::setGLContext(QGLContext *context)
+{
+ if (m_glContext == context)
+ return;
+
+ m_glContext = context;
+
+ m_shaderTypes = NoShaders;
+
+ if (m_glContext) {
+ m_glContext->makeCurrent();
+
+ const QByteArray extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
+#ifndef QT_OPENGL_ES
+
+ if (extensions.contains("ARB_fragment_program"))
+ m_shaderTypes |= FragmentProgramShader;
+#endif
+ if (QGLShaderProgram::hasOpenGLShaderPrograms(m_glContext)
+#ifndef QT_OPENGL_ES_2
+ && extensions.contains("ARB_shader_objects")
+#endif
+ )
+ m_shaderTypes |= GlslShader;
+ }
+
+ ShaderType type = (m_shaderType & m_shaderTypes)
+ ? m_shaderType
+ : NoShaders;
+
+ if (type != m_shaderType || type != NoShaders) {
+ m_shaderType = type;
+
+ if (isActive()) {
+ m_painter->stop();
+ delete m_painter;
+ m_painter = 0;
+ m_ready = false;
+
+ setError(ResourceError);
+ QAbstractVideoSurface::stop();
+ }
+ emit supportedFormatsChanged();
+ }
+}
+
+/*!
+ \enum QPainterVideoSurface::ShaderType
+
+ \value NoShaders
+ \value FragmentProgramShader
+ \value HlslShader
+*/
+
+/*!
+ \typedef QPainterVideoSurface::ShaderTypes
+*/
+
+/*!
+ \since 1.0
+*/
+QPainterVideoSurface::ShaderTypes QPainterVideoSurface::supportedShaderTypes() const
+{
+ return m_shaderTypes;
+}
+
+/*!
+ \since 1.0
+*/
+QPainterVideoSurface::ShaderType QPainterVideoSurface::shaderType() const
+{
+ return m_shaderType;
+}
+
+/*!
+ \since 1.0
+*/
+void QPainterVideoSurface::setShaderType(ShaderType type)
+{
+ if (!(type & m_shaderTypes))
+ type = NoShaders;
+
+ if (type != m_shaderType) {
+ m_shaderType = type;
+
+ if (isActive()) {
+ m_painter->stop();
+ delete m_painter;
+ m_painter = 0;
+ m_ready = false;
+
+ setError(ResourceError);
+ QAbstractVideoSurface::stop();
+ } else {
+ delete m_painter;
+ m_painter = 0;
+ }
+ emit supportedFormatsChanged();
+ }
+}
+
+#endif
+
+void QPainterVideoSurface::viewportDestroyed()
+{
+ if (m_painter) {
+ m_painter->viewportDestroyed();
+
+ setError(ResourceError);
+ stop();
+ delete m_painter;
+ m_painter = 0;
+ }
+}
+
+void QPainterVideoSurface::createPainter()
+{
+ Q_ASSERT(!m_painter);
+
+#ifdef Q_WS_MAC
+ if (m_glContext)
+ m_glContext->makeCurrent();
+
+ m_painter = new QVideoSurfaceCoreGraphicsPainter(m_glContext != 0);
+ return;
+#endif
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ switch (m_shaderType) {
+#ifndef QT_OPENGL_ES
+ case FragmentProgramShader:
+ Q_ASSERT(m_glContext);
+ m_glContext->makeCurrent();
+ m_painter = new QVideoSurfaceArbFpPainter(m_glContext);
+ break;
+#endif
+ case GlslShader:
+ Q_ASSERT(m_glContext);
+ m_glContext->makeCurrent();
+ m_painter = new QVideoSurfaceGlslPainter(m_glContext);
+ break;
+ default:
+ m_painter = new QVideoSurfaceGenericPainter;
+ break;
+ }
+#else
+ m_painter = new QVideoSurfaceGenericPainter;
+#endif
+}
+
+#include "moc_qpaintervideosurface_p.cpp"
+QT_END_NAMESPACE
+
+
diff --git a/src/multimediakit/qpaintervideosurface_mac.mm b/src/multimediakit/qpaintervideosurface_mac.mm
new file mode 100644
index 000000000..51aae04bb
--- /dev/null
+++ b/src/multimediakit/qpaintervideosurface_mac.mm
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 "qpaintervideosurface_mac_p.h"
+
+#include <QtCore/qdatetime.h>
+
+#include <qmath.h>
+
+#include <qpainter.h>
+#include <qvariant.h>
+#include <qvideosurfaceformat.h>
+
+#include <QtDebug>
+
+#include <QuartzCore/CIContext.h>
+#include <CGLCurrent.h>
+
+
+QT_BEGIN_NAMESPACE
+
+extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); //qpaintdevice_mac.cpp
+
+QVideoSurfaceCoreGraphicsPainter::QVideoSurfaceCoreGraphicsPainter(bool glSupported)
+ : ciContext(0)
+ , m_imageFormat(QImage::Format_Invalid)
+ , m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
+{
+ //qDebug() << "QVideoSurfaceCoreGraphicsPainter, GL supported:" << glSupported;
+ ciContext = 0;
+ m_imagePixelFormats
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_ARGB32
+ << QVideoFrame::Format_ARGB32_Premultiplied
+ << QVideoFrame::Format_RGB24
+ << QVideoFrame::Format_RGB565
+ << QVideoFrame::Format_RGB555
+ << QVideoFrame::Format_ARGB8565_Premultiplied;
+
+ m_supportedHandles
+ << QAbstractVideoBuffer::NoHandle
+ << QAbstractVideoBuffer::CoreImageHandle;
+
+ if (glSupported)
+ m_supportedHandles << QAbstractVideoBuffer::GLTextureHandle;
+}
+
+QVideoSurfaceCoreGraphicsPainter::~QVideoSurfaceCoreGraphicsPainter()
+{
+ [(CIContext*)ciContext release];
+}
+
+QList<QVideoFrame::PixelFormat> QVideoSurfaceCoreGraphicsPainter::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ return m_supportedHandles.contains(handleType)
+ ? m_imagePixelFormats
+ : QList<QVideoFrame::PixelFormat>();
+}
+
+bool QVideoSurfaceCoreGraphicsPainter::isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *) const
+{
+ return m_supportedHandles.contains(format.handleType())
+ && m_imagePixelFormats.contains(format.pixelFormat())
+ && !format.frameSize().isEmpty();
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceCoreGraphicsPainter::start(const QVideoSurfaceFormat &format)
+{
+ m_frame = QVideoFrame();
+ m_imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
+ m_imageSize = format.frameSize();
+ m_scanLineDirection = format.scanLineDirection();
+
+ return m_supportedHandles.contains(format.handleType())
+ && m_imageFormat != QImage::Format_Invalid
+ && !m_imageSize.isEmpty()
+ ? QAbstractVideoSurface::NoError
+ : QAbstractVideoSurface::UnsupportedFormatError;
+}
+
+void QVideoSurfaceCoreGraphicsPainter::stop()
+{
+ m_frame = QVideoFrame();
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceCoreGraphicsPainter::setCurrentFrame(const QVideoFrame &frame)
+{
+ m_frame = frame;
+
+ return QAbstractVideoSurface::NoError;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceCoreGraphicsPainter::paint(
+ const QRectF &target, QPainter *painter, const QRectF &source)
+{
+ if (m_frame.handleType() == QAbstractVideoBuffer::CoreImageHandle) {
+ if (painter->paintEngine()->type() == QPaintEngine::CoreGraphics ) {
+
+ CIImage *img = (CIImage*)(m_frame.handle().value<void*>());
+
+ if (img) {
+ CGContextRef cgContext = qt_mac_cg_context(painter->device());
+
+ if (cgContext) {
+ painter->beginNativePainting();
+
+ CGRect sRect = CGRectMake(source.x(), source.y(), source.width(), source.height());
+ CGRect dRect = CGRectMake(target.x(), target.y(), target.width(), target.height());
+
+ NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img];
+
+ if (m_scanLineDirection == QVideoSurfaceFormat::TopToBottom) {
+ CGContextSaveGState( cgContext );
+ CGContextTranslateCTM(cgContext, 0, dRect.origin.y + CGRectGetMaxY(dRect));
+ CGContextScaleCTM(cgContext, 1, -1);
+
+ CGContextDrawImage(cgContext, dRect, [bitmap CGImage]);
+
+ CGContextRestoreGState(cgContext);
+ } else {
+ CGContextDrawImage(cgContext, dRect, [bitmap CGImage]);
+ }
+
+ [bitmap release];
+
+ painter->endNativePainting();
+
+ return QAbstractVideoSurface::NoError;
+ }
+ }
+ } else if (painter->paintEngine()->type() == QPaintEngine::OpenGL2 ||
+ painter->paintEngine()->type() == QPaintEngine::OpenGL) {
+ CIImage *img = (CIImage*)(m_frame.handle().value<void*>());
+
+ if (img) {
+ CGLContextObj cglContext = CGLGetCurrentContext();
+
+ if (cglContext) {
+
+ if (!ciContext) {
+ CGLContextObj cglContext = CGLGetCurrentContext();
+ NSOpenGLPixelFormat *nsglPixelFormat = [NSOpenGLView defaultPixelFormat];
+ CGLPixelFormatObj cglPixelFormat = static_cast<CGLPixelFormatObj>([nsglPixelFormat CGLPixelFormatObj]);
+
+ ciContext = [CIContext contextWithCGLContext:cglContext
+ pixelFormat:cglPixelFormat
+ options:nil];
+
+ [(CIContext*)ciContext retain];
+ }
+
+ CGRect sRect = CGRectMake(source.x(), source.y(), source.width(), source.height());
+ CGRect dRect = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom ?
+ CGRectMake(target.x(), target.y()+target.height(), target.width(), -target.height()) :
+ CGRectMake(target.x(), target.y(), target.width(), target.height());
+
+
+ painter->beginNativePainting();
+
+ [(CIContext*)ciContext drawImage:img inRect:dRect fromRect:sRect];
+
+ painter->endNativePainting();
+
+ return QAbstractVideoSurface::NoError;
+ }
+ }
+ }
+ }
+
+ if (m_frame.handleType() == QAbstractVideoBuffer::GLTextureHandle &&
+ (painter->paintEngine()->type() == QPaintEngine::OpenGL2 ||
+ painter->paintEngine()->type() == QPaintEngine::OpenGL)) {
+
+ painter->beginNativePainting();
+ GLuint texture = m_frame.handle().toUInt();
+
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_2D);
+
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ const float txLeft = source.left() / m_frame.width();
+ const float txRight = source.right() / m_frame.width();
+ const float txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.top() / m_frame.height()
+ : source.bottom() / m_frame.height();
+ const float txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.bottom() / m_frame.height()
+ : source.top() / m_frame.height();
+
+ glBegin(GL_QUADS);
+ QRectF rect = target;
+ glTexCoord2f(txLeft, txBottom);
+ glVertex2f(rect.topLeft().x(), rect.topLeft().y());
+ glTexCoord2f(txRight, txBottom);
+ glVertex2f(rect.topRight().x() + 1, rect.topRight().y());
+ glTexCoord2f(txRight, txTop);
+ glVertex2f(rect.bottomRight().x() + 1, rect.bottomRight().y() + 1);
+ glTexCoord2f(txLeft, txTop);
+ glVertex2f(rect.bottomLeft().x(), rect.bottomLeft().y() + 1);
+ glEnd();
+ painter->endNativePainting();
+
+ return QAbstractVideoSurface::NoError;
+ }
+
+ //fallback case, software rendering
+ if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) {
+ QImage image(
+ m_frame.bits(),
+ m_imageSize.width(),
+ m_imageSize.height(),
+ m_frame.bytesPerLine(),
+ m_imageFormat);
+
+ if (m_scanLineDirection == QVideoSurfaceFormat::BottomToTop) {
+ const QTransform oldTransform = painter->transform();
+
+ painter->scale(1, -1);
+ painter->translate(0, -target.bottom());
+ painter->drawImage(
+ QRectF(target.x(), 0, target.width(), target.height()), image, source);
+ painter->setTransform(oldTransform);
+ } else {
+ painter->drawImage(target, image, source);
+ }
+
+ m_frame.unmap();
+ } else if (m_frame.isValid()) {
+ return QAbstractVideoSurface::IncorrectFormatError;
+ } else {
+ painter->fillRect(target, Qt::black);
+ }
+
+ return QAbstractVideoSurface::NoError;
+}
+
+void QVideoSurfaceCoreGraphicsPainter::updateColors(int, int, int, int)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/multimediakit/qpaintervideosurface_mac_p.h b/src/multimediakit/qpaintervideosurface_mac_p.h
new file mode 100644
index 000000000..9ec801218
--- /dev/null
+++ b/src/multimediakit/qpaintervideosurface_mac_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QPAINTERVIDEOSURFACE_MAC_P_H
+#define QPAINTERVIDEOSURFACE_MAC_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 "qpaintervideosurface_p.h"
+#include <qvideosurfaceformat.h>
+#include <qvideoframe.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QVideoSurfaceCoreGraphicsPainter : public QVideoSurfacePainter
+{
+public:
+ QVideoSurfaceCoreGraphicsPainter(bool glSupported);
+ ~QVideoSurfaceCoreGraphicsPainter();
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const;
+
+ bool isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const;
+
+ QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame);
+
+ QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source);
+
+ void updateColors(int brightness, int contrast, int hue, int saturation);
+
+private:
+ void* ciContext;
+ QList<QVideoFrame::PixelFormat> m_imagePixelFormats;
+ QVideoFrame m_frame;
+ QSize m_imageSize;
+ QImage::Format m_imageFormat;
+ QVector<QAbstractVideoBuffer::HandleType> m_supportedHandles;
+ QVideoSurfaceFormat::Direction m_scanLineDirection;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/multimediakit/qpaintervideosurface_p.h b/src/multimediakit/qpaintervideosurface_p.h
new file mode 100644
index 000000000..b48759479
--- /dev/null
+++ b/src/multimediakit/qpaintervideosurface_p.h
@@ -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$
+**
+****************************************************************************/
+
+#ifndef QPAINTERVIDEOSURFACE_P_H
+#define QPAINTERVIDEOSURFACE_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/qsize.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qpaintengine.h>
+#include <qabstractvideosurface.h>
+#include <qvideoframe.h>
+
+QT_BEGIN_NAMESPACE
+class QGLContext;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class QVideoSurfacePainter
+{
+public:
+ virtual ~QVideoSurfacePainter();
+
+ virtual QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const = 0;
+
+ virtual bool isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const = 0;
+
+ virtual QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format) = 0;
+ virtual void stop() = 0;
+
+ virtual QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame) = 0;
+
+ virtual QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source) = 0;
+
+ virtual void updateColors(int brightness, int contrast, int hue, int saturation) = 0;
+ virtual void viewportDestroyed() {}
+};
+
+
+class Q_AUTOTEST_EXPORT QPainterVideoSurface : public QAbstractVideoSurface
+{
+ Q_OBJECT
+public:
+ explicit QPainterVideoSurface(QObject *parent = 0);
+ ~QPainterVideoSurface();
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
+
+ bool isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar = 0) const;
+
+ bool start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ bool present(const QVideoFrame &frame);
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ bool isReady() const;
+ void setReady(bool ready);
+
+ void paint(QPainter *painter, const QRectF &target, const QRectF &source = QRectF(0, 0, 1, 1));
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ const QGLContext *glContext() const;
+ void setGLContext(QGLContext *context);
+
+ enum ShaderType
+ {
+ NoShaders = 0x00,
+ FragmentProgramShader = 0x01,
+ GlslShader = 0x02
+ };
+
+ Q_DECLARE_FLAGS(ShaderTypes, ShaderType)
+
+ ShaderTypes supportedShaderTypes() const;
+
+ ShaderType shaderType() const;
+ void setShaderType(ShaderType type);
+#endif
+
+public Q_SLOTS:
+ void viewportDestroyed();
+
+Q_SIGNALS:
+ void frameChanged();
+
+private:
+ void createPainter();
+
+ QVideoSurfacePainter *m_painter;
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ QGLContext *m_glContext;
+ ShaderTypes m_shaderTypes;
+ ShaderType m_shaderType;
+#endif
+ int m_brightness;
+ int m_contrast;
+ int m_hue;
+ int m_saturation;
+
+ QVideoFrame::PixelFormat m_pixelFormat;
+ QSize m_frameSize;
+ QRect m_sourceRect;
+ bool m_colorsDirty;
+ bool m_ready;
+};
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QPainterVideoSurface::ShaderTypes)
+#endif
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qradiotuner.cpp b/src/multimediakit/qradiotuner.cpp
new file mode 100644
index 000000000..21a2b1c33
--- /dev/null
+++ b/src/multimediakit/qradiotuner.cpp
@@ -0,0 +1,614 @@
+/****************************************************************************
+**
+** 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 "qradiotuner.h"
+#include "qmediaservice.h"
+#include "qmediaobject_p.h"
+#include "qradiotunercontrol.h"
+
+#include <QPair>
+
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QRadioTuner
+ \brief The QRadioTuner class provides an interface to the systems analog radio device.
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ You can control the systems analog radio device using this interface, for example:
+
+ \snippet doc/src/snippets/multimedia-snippets/media.cpp Radio tuner
+
+ The radio object will emit signals for any changes in state such as:
+ bandChanged(), frequencyChanged(), stereoStatusChanged(), searchingChanged(),
+ signalStrengthChanged(), volumeChanged(), mutedChanged().
+
+ You can change between the frequency bands using setBand() however it is recommended
+ that you check to make sure the band is available first using isBandSupported().
+
+*/
+
+
+class QRadioTunerPrivate : public QMediaObjectPrivate
+{
+public:
+ QRadioTunerPrivate():provider(0), control(0) {}
+ QMediaServiceProvider *provider;
+ QRadioTunerControl* control;
+};
+
+
+
+/*!
+ Constructs a radio tuner based on a media service allocated by a media service \a provider.
+
+ The \a parent is passed to QMediaObject.
+ \since 1.0
+*/
+
+QRadioTuner::QRadioTuner(QObject *parent, QMediaServiceProvider* provider):
+ QMediaObject(*new QRadioTunerPrivate, parent, provider->requestService(Q_MEDIASERVICE_RADIO))
+{
+ Q_D(QRadioTuner);
+
+ d->provider = provider;
+
+ if (d->service != 0) {
+ d->control = qobject_cast<QRadioTunerControl*>(d->service->requestControl(QRadioTunerControl_iid));
+ if (d->control != 0) {
+ connect(d->control, SIGNAL(stateChanged(QRadioTuner::State)), SIGNAL(stateChanged(QRadioTuner::State)));
+ connect(d->control, SIGNAL(bandChanged(QRadioTuner::Band)), SIGNAL(bandChanged(QRadioTuner::Band)));
+ connect(d->control, SIGNAL(frequencyChanged(int)), SIGNAL(frequencyChanged(int)));
+ connect(d->control, SIGNAL(stereoStatusChanged(bool)), SIGNAL(stereoStatusChanged(bool)));
+ connect(d->control, SIGNAL(searchingChanged(bool)), SIGNAL(searchingChanged(bool)));
+ connect(d->control, SIGNAL(signalStrengthChanged(int)), SIGNAL(signalStrengthChanged(int)));
+ connect(d->control, SIGNAL(volumeChanged(int)), SIGNAL(volumeChanged(int)));
+ connect(d->control, SIGNAL(mutedChanged(bool)), SIGNAL(mutedChanged(bool)));
+ connect(d->control, SIGNAL(error(QRadioTuner::Error)), SIGNAL(error(QRadioTuner::Error)));
+ }
+ }
+}
+
+/*!
+ Destroys a radio tuner.
+*/
+
+QRadioTuner::~QRadioTuner()
+{
+ Q_D(QRadioTuner);
+
+ if (d->service && d->control)
+ d->service->releaseControl(d->control);
+
+ d->provider->releaseService(d->service);
+}
+
+/*!
+ Returns true if the radio tuner service is ready to use.
+ \since 1.0
+*/
+bool QRadioTuner::isAvailable() const
+{
+ if (d_func()->control != NULL)
+ return d_func()->control->isAvailable();
+ else
+ return false;
+}
+
+/*!
+ Returns the availability error state.
+ \since 1.0
+*/
+QtMultimediaKit::AvailabilityError QRadioTuner::availabilityError() const
+{
+ if (d_func()->control != NULL)
+ return d_func()->control->availabilityError();
+ else
+ return QtMultimediaKit::ServiceMissingError;
+}
+
+/*!
+ \property QRadioTuner::state
+ Return the current radio tuner state.
+
+ \since 1.0
+ \sa QRadioTuner::State
+*/
+
+QRadioTuner::State QRadioTuner::state() const
+{
+ return d_func()->control ?
+ d_func()->control->state() : QRadioTuner::StoppedState;
+}
+
+/*!
+ \property QRadioTuner::band
+ \brief the frequency band a radio tuner is tuned to.
+
+ \since 1.0
+ \sa QRadioTuner::Band
+*/
+
+QRadioTuner::Band QRadioTuner::band() const
+{
+ Q_D(const QRadioTuner);
+
+ if (d->control != 0)
+ return d->control->band();
+
+ return QRadioTuner::FM;
+}
+
+/*!
+ \property QRadioTuner::frequency
+ \brief the frequency in Hertz a radio tuner is tuned to.
+ \since 1.0
+*/
+
+int QRadioTuner::frequency() const
+{
+ Q_D(const QRadioTuner);
+
+ if (d->control != 0)
+ return d->control->frequency();
+
+ return 0;
+}
+
+/*!
+ Returns the number of Hertz to increment the frequency by when stepping through frequencies
+ within a given \a band.
+ \since 1.0
+*/
+
+int QRadioTuner::frequencyStep(QRadioTuner::Band band) const
+{
+ Q_D(const QRadioTuner);
+
+ if(d->control != 0)
+ return d->control->frequencyStep(band);
+
+ return 0;
+}
+
+/*!
+ Returns a frequency \a band's minimum and maximum frequency.
+ \since 1.0
+*/
+
+QPair<int,int> QRadioTuner::frequencyRange(QRadioTuner::Band band) const
+{
+ Q_D(const QRadioTuner);
+
+ if(d->control != 0)
+ return d->control->frequencyRange(band);
+
+ return qMakePair<int,int>(0,0);
+}
+
+/*!
+ \property QRadioTuner::stereo
+ \brief whether a radio tuner is receiving a stereo signal.
+ \since 1.0
+*/
+
+bool QRadioTuner::isStereo() const
+{
+ Q_D(const QRadioTuner);
+
+ if (d->control != 0)
+ return d->control->isStereo();
+
+ return false;
+}
+
+
+/*!
+ \property QRadioTuner::stereoMode
+ \brief the stereo mode of a radio tuner.
+ \since 1.0
+*/
+
+QRadioTuner::StereoMode QRadioTuner::stereoMode() const
+{
+ Q_D(const QRadioTuner);
+
+ if (d->control != 0)
+ return d->control->stereoMode();
+
+ return QRadioTuner::Auto;
+}
+
+void QRadioTuner::setStereoMode(QRadioTuner::StereoMode mode)
+{
+ Q_D(QRadioTuner);
+
+ if (d->control != 0)
+ return d->control->setStereoMode(mode);
+}
+
+/*!
+ Identifies if a frequency \a band is supported by a radio tuner.
+
+ Returns true if the band is supported, and false if it is not.
+ \since 1.0
+*/
+
+bool QRadioTuner::isBandSupported(QRadioTuner::Band band) const
+{
+ Q_D(const QRadioTuner);
+
+ if (d->control != 0)
+ return d->control->isBandSupported(band);
+
+ return false;
+}
+
+/*!
+ Activate the radio device.
+ \since 1.0
+*/
+
+void QRadioTuner::start()
+{
+ Q_D(const QRadioTuner);
+
+ if (d->control != 0)
+ d->control->start();
+}
+
+/*!
+ Deactivate the radio device.
+ \since 1.0
+*/
+
+void QRadioTuner::stop()
+{
+ Q_D(const QRadioTuner);
+
+ if (d->control != 0)
+ d->control->stop();
+}
+
+/*!
+ \property QRadioTuner::signalStrength
+ \brief the strength of the current radio signal as a percentage.
+ \since 1.0
+*/
+
+int QRadioTuner::signalStrength() const
+{
+ Q_D(const QRadioTuner);
+
+ if (d->control != 0)
+ return d->control->signalStrength();
+
+ return 0;
+}
+
+/*!
+ \property QRadioTuner::volume
+ \brief the volume of a radio tuner's audio output as a percentage.
+ \since 1.0
+*/
+
+
+int QRadioTuner::volume() const
+{
+ Q_D(const QRadioTuner);
+
+ if (d->control != 0)
+ return d->control->volume();
+
+ return 0;
+}
+
+/*!
+ \property QRadioTuner::muted
+ \brief whether a radio tuner's audio output is muted.
+ \since 1.0
+*/
+
+bool QRadioTuner::isMuted() const
+{
+ Q_D(const QRadioTuner);
+
+ if (d->control != 0)
+ return d->control->isMuted();
+
+ return false;
+}
+
+/*!
+ Sets a radio tuner's frequency \a band.
+
+ Changing the band will reset the \l frequency to the new band's minimum frequency.
+ \since 1.0
+*/
+
+void QRadioTuner::setBand(QRadioTuner::Band band)
+{
+ Q_D(QRadioTuner);
+
+ if (d->control != 0)
+ d->control->setBand(band);
+}
+
+/*!
+ Sets a radio tuner's \a frequency.
+
+ If the tuner is set to a frequency outside the current \l band, the band will be changed to
+ one occupied by the new frequency.
+ \since 1.0
+*/
+
+void QRadioTuner::setFrequency(int frequency)
+{
+ Q_D(QRadioTuner);
+
+ if (d->control != 0)
+ d->control->setFrequency(frequency);
+}
+
+void QRadioTuner::setVolume(int volume)
+{
+ Q_D(QRadioTuner);
+
+ if (d->control != 0)
+ d->control->setVolume(volume);
+}
+
+void QRadioTuner::setMuted(bool muted)
+{
+ Q_D(QRadioTuner);
+
+ if (d->control != 0)
+ d->control->setMuted(muted);
+}
+
+/*!
+ \property QRadioTuner::searching
+ \brief whether a radio tuner is currently scanning for a signal.
+
+ \sa searchForward(), searchBackward(), cancelSearch()
+ \since 1.0
+*/
+
+bool QRadioTuner::isSearching() const
+{
+ Q_D(const QRadioTuner);
+
+ if (d->control != 0)
+ return d->control->isSearching();
+
+ return false;
+}
+
+/*!
+ Starts a forward scan for a signal, starting from the current \l frequency.
+
+ \since 1.0
+ \sa searchBackward(), cancelSearch(), searching
+*/
+
+void QRadioTuner::searchForward()
+{
+ Q_D(QRadioTuner);
+
+ if (d->control != 0)
+ d->control->searchForward();
+}
+
+/*!
+ Starts a backwards scan for a signal, starting from the current \l frequency.
+
+ \since 1.0
+ \sa searchForward(), cancelSearch(), searching
+*/
+
+void QRadioTuner::searchBackward()
+{
+ Q_D(QRadioTuner);
+
+ if (d->control != 0)
+ d->control->searchBackward();
+}
+
+/*!
+ Stops scanning for a signal.
+
+ \since 1.0
+ \sa searchForward(), searchBackward(), searching
+*/
+
+void QRadioTuner::cancelSearch()
+{
+ Q_D(QRadioTuner);
+
+ if (d->control != 0)
+ d->control->cancelSearch();
+}
+
+/*!
+ Returns the error state of a radio tuner.
+
+ \since 1.0
+ \sa errorString()
+*/
+
+QRadioTuner::Error QRadioTuner::error() const
+{
+ Q_D(const QRadioTuner);
+
+ if (d->control != 0)
+ return d->control->error();
+
+ return QRadioTuner::ResourceError;
+}
+
+/*!
+ Returns a description of a radio tuner's error state.
+
+ \since 1.0
+ \sa error()
+*/
+
+QString QRadioTuner::errorString() const
+{
+ Q_D(const QRadioTuner);
+
+ if (d->control != 0)
+ return d->control->errorString();
+
+ return QString();
+}
+
+/*!
+ \fn void QRadioTuner::bandChanged(QRadioTuner::Band band)
+
+ Signals a radio tuner's \a band has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTuner::frequencyChanged(int frequency)
+
+ Signals that the \a frequency a radio tuner is tuned to has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTuner::mutedChanged(bool muted)
+
+ Signals that the \a muted state of a radio tuner's audio output has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTuner::volumeChanged(int volume)
+
+ Signals that the \a volume of a radio tuner's audio output has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTuner::searchingChanged(bool searching)
+
+ Signals that the \a searching state of a radio tuner has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTuner::stereoStatusChanged(bool stereo)
+
+ Signals that the \a stereo state of a radio tuner has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTuner::signalStrengthChanged(int strength)
+
+ Signals that the \a strength of the signal received by a radio tuner has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTuner::error(QRadioTuner::Error error)
+
+ Signals that an \a error occurred.
+ \since 1.0
+*/
+
+/*!
+ \enum QRadioTuner::State
+
+ Enumerates radio tuner states.
+
+ \value ActiveState The tuner is started and active.
+ \value StoppedState The tuner device is stopped.
+*/
+
+
+/*!
+ \enum QRadioTuner::Band
+
+ Enumerates radio frequency bands.
+
+ \value AM 520 to 1610 kHz, 9 or 10kHz channel spacing, extended 1610 to 1710 kHz
+ \value FM 87.5 to 108.0 MHz, except Japan 76-90 MHz
+ \value SW 1.711 to 30.0 MHz, divided into 15 bands. 5kHz channel spacing
+ \value LW 148.5 to 283.5 kHz, 9kHz channel spacing (Europe, Africa, Asia)
+ \value FM2 range not defined, used when area supports more than one FM range.
+*/
+
+/*!
+ \enum QRadioTuner::Error
+
+ Enumerates radio tuner error conditions.
+
+ \value NoError No errors have occurred.
+ \value ResourceError There is no radio service available.
+ \value OpenError Unable to open radio device.
+ \value OutOfRangeError An attempt to set a frequency or band that is not supported by radio device.
+*/
+
+/*!
+ \enum QRadioTuner::StereoMode
+
+ Enumerates radio tuner policy for receiving stereo signals.
+
+ \value Auto Uses the stereo mode matching the station.
+ \value ForceStereo Provide stereo mode, converting if required.
+ \value ForceMono Provide mono mode, converting if required.
+*/
+
+/*! \fn void QRadioTuner::stateChanged(QRadioTuner::State state)
+ This signal is emitted when the state changes to \a state.
+ \since 1.0
+ */
+
+#include "moc_qradiotuner.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qradiotuner.h b/src/multimediakit/qradiotuner.h
new file mode 100644
index 000000000..31510cf0c
--- /dev/null
+++ b/src/multimediakit/qradiotuner.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** 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 QRADIOTUNER_H
+#define QRADIOTUNER_H
+
+#include <QtCore/qobject.h>
+
+#include "qmediaobject.h"
+#include "qmediaserviceprovider.h"
+#include <qmediaenumdebug.h>
+
+#include <QPair>
+
+QT_BEGIN_NAMESPACE
+
+class QRadioTunerPrivate;
+class Q_MULTIMEDIA_EXPORT QRadioTuner : public QMediaObject
+{
+ Q_OBJECT
+ Q_PROPERTY(State state READ state NOTIFY stateChanged)
+ Q_PROPERTY(Band band READ band WRITE setBand NOTIFY bandChanged)
+ Q_PROPERTY(int frequency READ frequency WRITE setFrequency NOTIFY frequencyChanged)
+ Q_PROPERTY(bool stereo READ isStereo NOTIFY stereoStatusChanged)
+ Q_PROPERTY(StereoMode stereoMode READ stereoMode WRITE setStereoMode)
+ Q_PROPERTY(int signalStrength READ signalStrength NOTIFY signalStrengthChanged)
+ Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged)
+ Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
+ Q_PROPERTY(bool searching READ isSearching NOTIFY searchingChanged)
+ Q_ENUMS(State)
+ Q_ENUMS(Band)
+ Q_ENUMS(Error)
+ Q_ENUMS(StereoMode)
+
+public:
+ enum State { ActiveState, StoppedState };
+ enum Band { AM, FM, SW, LW, FM2 };
+ enum Error { NoError, ResourceError, OpenError, OutOfRangeError };
+ enum StereoMode { ForceStereo, ForceMono, Auto };
+
+ QRadioTuner(QObject *parent = 0, QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider());
+ ~QRadioTuner();
+
+ bool isAvailable() const;
+ QtMultimediaKit::AvailabilityError availabilityError() const;
+
+ State state() const;
+
+ Band band() const;
+
+ bool isBandSupported(Band b) const;
+
+ int frequency() const;
+ int frequencyStep(Band band) const;
+ QPair<int,int> frequencyRange(Band band) const;
+
+ bool isStereo() const;
+ void setStereoMode(QRadioTuner::StereoMode mode);
+ StereoMode stereoMode() const;
+
+ int signalStrength() const;
+
+ int volume() const;
+ bool isMuted() const;
+
+ bool isSearching() const;
+
+ Error error() const;
+ QString errorString() const;
+
+public Q_SLOTS:
+ void searchForward();
+ void searchBackward();
+ void cancelSearch();
+
+ void setBand(Band band);
+ void setFrequency(int frequency);
+
+ void setVolume(int volume);
+ void setMuted(bool muted);
+
+ void start();
+ void stop();
+
+Q_SIGNALS:
+ void stateChanged(QRadioTuner::State state);
+ void bandChanged(QRadioTuner::Band band);
+ void frequencyChanged(int frequency);
+ void stereoStatusChanged(bool stereo);
+ void searchingChanged(bool searching);
+ void signalStrengthChanged(int signalStrength);
+ void volumeChanged(int volume);
+ void mutedChanged(bool muted);
+ void error(QRadioTuner::Error error);
+
+private:
+ Q_DISABLE_COPY(QRadioTuner)
+ Q_DECLARE_PRIVATE(QRadioTuner)
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QRadioTuner::State)
+Q_DECLARE_METATYPE(QRadioTuner::Band)
+Q_DECLARE_METATYPE(QRadioTuner::Error)
+Q_DECLARE_METATYPE(QRadioTuner::StereoMode)
+
+Q_MEDIA_ENUM_DEBUG(QRadioTuner, State)
+Q_MEDIA_ENUM_DEBUG(QRadioTuner, Band)
+Q_MEDIA_ENUM_DEBUG(QRadioTuner, Error)
+Q_MEDIA_ENUM_DEBUG(QRadioTuner, StereoMode)
+
+#endif // QRADIOPLAYER_H
diff --git a/src/multimediakit/qradiotunercontrol.cpp b/src/multimediakit/qradiotunercontrol.cpp
new file mode 100644
index 000000000..39c39b4b3
--- /dev/null
+++ b/src/multimediakit/qradiotunercontrol.cpp
@@ -0,0 +1,364 @@
+/****************************************************************************
+**
+** 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 <qmobilityglobal.h>
+#include "qradiotunercontrol.h"
+#include "qmediacontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ \class QRadioTunerControl
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+
+ \brief The QRadioTunerControl class provides access to the radio tuning
+ functionality of a QMediaService.
+
+ If a QMediaService can tune an analog radio device it will implement
+ QRadioTunerControl. This control provides a means to tune a radio device
+ to a specific \l {setFrequency()}{frequency} as well as search \l
+ {searchForward()}{forwards} and \l {searchBackward()}{backwards} for a
+ signal.
+
+ The functionality provided by this control is exposed to application code
+ through the QRadioTuner class.
+
+ The interface name of QRadioTunerControl is \c com.nokia.Qt.QRadioTunerControl/1.0 as
+ defined in QRadioTunerControl_iid.
+
+ \sa QMediaService::requestControl(), QRadioTuner
+*/
+
+/*!
+ \macro QRadioTunerControl_iid
+
+ \c com.nokia.Qt.QRadioTunerControl/1.0
+
+ Defines the interface name of the QRadioTunerControl class.
+
+ \relates QRadioTunerControl
+*/
+
+/*!
+ Constructs a radio tuner control with the given \a parent.
+*/
+
+QRadioTunerControl::QRadioTunerControl(QObject *parent):
+ QMediaControl(*new QMediaControlPrivate, parent)
+{
+}
+
+/*!
+ Destroys a radio tuner control.
+*/
+
+QRadioTunerControl::~QRadioTunerControl()
+{
+}
+
+/*!
+ \fn bool QRadioTunerControl::isAvailable() const
+
+ Returns true if the radio service is ready to use.
+ \since 1.0
+*/
+
+/*!
+ \fn QtMultimediaKit::AvailabilityError QRadioTunerControl::availabilityError() const
+
+ Returns the error state of the radio service.
+ \since 1.0
+*/
+
+/*!
+ \fn QRadioTuner::State QRadioTunerControl::state() const
+
+ Returns the current radio tuner state.
+ \since 1.0
+*/
+
+/*!
+ \fn QRadioTuner::Band QRadioTunerControl::band() const
+
+ Returns the frequency band a radio tuner is tuned to.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::bandChanged(QRadioTuner::Band band)
+
+ Signals that the frequency \a band a radio tuner is tuned to has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::setBand(QRadioTuner::Band band)
+
+ Sets the frequecy \a band a radio tuner is tuned to.
+
+ Changing the frequency band will reset the frequency to the minimum frequency of the new band.
+ \since 1.0
+*/
+
+/*!
+ \fn bool QRadioTunerControl::isBandSupported(QRadioTuner::Band band) const
+
+ Identifies if a frequency \a band is supported.
+
+ Returns true if the band is supported, and false if it is not.
+ \since 1.0
+*/
+
+/*!
+ \fn int QRadioTunerControl::frequency() const
+
+ Returns the frequency a radio tuner is tuned to.
+ \since 1.0
+*/
+
+/*!
+ \fn int QRadioTunerControl::frequencyStep(QRadioTuner::Band band) const
+
+ Returns the number of Hertz to increment the frequency by when stepping through frequencies
+ within a given \a band.
+ \since 1.0
+*/
+
+/*!
+ \fn QPair<int,int> QRadioTunerControl::frequencyRange(QRadioTuner::Band band) const
+
+ Returns a frequency \a band's minimum and maximum frequency.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::setFrequency(int frequency)
+
+ Sets the \a frequency a radio tuner is tuned to.
+ \since 1.0
+*/
+
+/*!
+ \fn bool QRadioTunerControl::isStereo() const
+
+ Identifies if a radio tuner is receiving a stereo signal.
+
+ Returns true if the tuner is receiving a stereo signal, and false if it is not.
+ \since 1.0
+*/
+
+/*!
+ \fn QRadioTuner::StereoMode QRadioTunerControl::stereoMode() const
+
+ Returns a radio tuner's stereo mode.
+
+ \since 1.0
+ \sa QRadioTuner::StereoMode
+*/
+
+/*!
+ \fn void QRadioTunerControl::setStereoMode(QRadioTuner::StereoMode mode)
+
+ Sets a radio tuner's stereo \a mode.
+
+ \since 1.0
+ \sa QRadioTuner::StereoMode
+*/
+
+/*!
+ \fn int QRadioTunerControl::signalStrength() const
+
+ Return a radio tuner's current signal strength as a percentage.
+ \since 1.0
+*/
+
+/*!
+ \fn int QRadioTunerControl::volume() const
+
+ Returns the volume of a radio tuner's audio output as a percentage.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::setVolume(int volume)
+
+ Sets the percentage \a volume of a radio tuner's audio output.
+ \since 1.0
+*/
+
+/*!
+ \fn bool QRadioTunerControl::isMuted() const
+
+ Identifies if a radio tuner's audio output is muted.
+
+ Returns true if the audio is muted, and false if it is not.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::setMuted(bool muted)
+
+ Sets the \a muted state of a radio tuner's audio output.
+ \since 1.0
+*/
+
+/*!
+ \fn bool QRadioTunerControl::isSearching() const
+
+ Identifies if a radio tuner is currently scanning for signal.
+
+ Returns true if the tuner is scanning, and false if it is not.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::searchForward()
+
+ Starts a forward scan for a signal, starting from the current \l frequency().
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::searchBackward()
+
+ Starts a backwards scan for a signal, starting from the current \l frequency().
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::cancelSearch()
+
+ Stops scanning for a signal.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::start()
+
+ Activate the radio device.
+ \since 1.0
+*/
+
+/*!
+ \fn QRadioTunerControl::stop()
+
+ Deactivate the radio device.
+ \since 1.0
+*/
+
+/*!
+ \fn QRadioTuner::Error QRadioTunerControl::error() const
+
+ Returns the error state of a radio tuner.
+ \since 1.0
+*/
+
+/*!
+ \fn QString QRadioTunerControl::errorString() const
+
+ Returns a string describing a radio tuner's error state.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::stateChanged(QRadioTuner::State state)
+
+ Signals that the \a state of a radio tuner has changed.
+ \since 1.0
+*/
+
+
+/*!
+ \fn void QRadioTunerControl::frequencyChanged(int frequency)
+
+ Signals that the \a frequency a radio tuner is tuned to has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::stereoStatusChanged(bool stereo)
+
+ Signals that the \a stereo state of a radio tuner has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::searchingChanged(bool searching)
+
+ Signals that the \a searching state of a radio tuner has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::signalStrengthChanged(int strength)
+
+ Signals that the percentage \a strength of the signal received by a radio tuner has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::volumeChanged(int volume)
+
+ Signals that the percentage \a volume of radio tuner's audio output has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::mutedChanged(bool muted)
+
+ Signals that the \a muted state of a radio tuner's audio output has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn void QRadioTunerControl::error(QRadioTuner::Error error)
+
+ Signals that an \a error has occurred.
+ \since 1.0
+*/
+
+#include "moc_qradiotunercontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qradiotunercontrol.h b/src/multimediakit/qradiotunercontrol.h
new file mode 100644
index 000000000..d21946a98
--- /dev/null
+++ b/src/multimediakit/qradiotunercontrol.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** 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 QRADIOTUNERCONTROL_H
+#define QRADIOTUNERCONTROL_H
+
+#include "qmediacontrol.h"
+#include "qradiotuner.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QRadioTunerControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ ~QRadioTunerControl();
+
+ virtual bool isAvailable() const = 0;
+ virtual QtMultimediaKit::AvailabilityError availabilityError() const = 0;
+
+ virtual QRadioTuner::State state() const = 0;
+
+ virtual QRadioTuner::Band band() const = 0;
+ virtual void setBand(QRadioTuner::Band b) = 0;
+ virtual bool isBandSupported(QRadioTuner::Band b) const = 0;
+
+ virtual int frequency() const = 0;
+ virtual int frequencyStep(QRadioTuner::Band b) const = 0;
+ virtual QPair<int,int> frequencyRange(QRadioTuner::Band b) const = 0;
+ virtual void setFrequency(int frequency) = 0;
+
+ virtual bool isStereo() const = 0;
+ virtual QRadioTuner::StereoMode stereoMode() const = 0;
+ virtual void setStereoMode(QRadioTuner::StereoMode mode) = 0;
+
+ virtual int signalStrength() const = 0;
+
+ virtual int volume() const = 0;
+ virtual void setVolume(int volume) = 0;
+
+ virtual bool isMuted() const = 0;
+ virtual void setMuted(bool muted) = 0;
+
+ virtual bool isSearching() const = 0;
+
+ virtual void searchForward() = 0;
+ virtual void searchBackward() = 0;
+ virtual void cancelSearch() = 0;
+
+ virtual void start() = 0;
+ virtual void stop() = 0;
+
+ virtual QRadioTuner::Error error() const = 0;
+ virtual QString errorString() const = 0;
+
+Q_SIGNALS:
+ void stateChanged(QRadioTuner::State state);
+ void bandChanged(QRadioTuner::Band band);
+ void frequencyChanged(int frequency);
+ void stereoStatusChanged(bool stereo);
+ void searchingChanged(bool stereo);
+ void signalStrengthChanged(int signalStrength);
+ void volumeChanged(int volume);
+ void mutedChanged(bool muted);
+ void error(QRadioTuner::Error err);
+
+protected:
+ QRadioTunerControl(QObject *parent = 0);
+};
+
+#define QRadioTunerControl_iid "com.nokia.Qt.QRadioTunerControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QRadioTunerControl, QRadioTunerControl_iid)
+
+QT_END_NAMESPACE
+
+#endif // QRADIOTUNERCONTROL_H
diff --git a/src/multimediakit/qtmedianamespace.h b/src/multimediakit/qtmedianamespace.h
new file mode 100644
index 000000000..1f2b800ca
--- /dev/null
+++ b/src/multimediakit/qtmedianamespace.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** 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 QTMEDIANAMESPACE_H
+#define QTMEDIANAMESPACE_H
+
+#include <QtCore/qpair.h>
+#include <QtCore/qmetatype.h>
+
+#include <qmobilityglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtMultimediaKit
+{
+ enum MetaData
+ {
+ // Common
+ Title,
+ SubTitle,
+ Author,
+ Comment,
+ Description,
+ Category,
+ Genre,
+ Year,
+ Date,
+ UserRating,
+ Keywords,
+ Language,
+ Publisher,
+ Copyright,
+ ParentalRating,
+ RatingOrganisation,
+
+ // Media
+ Size,
+ MediaType,
+ Duration,
+
+ // Audio
+ AudioBitRate,
+ AudioCodec,
+ AverageLevel,
+ ChannelCount,
+ PeakValue,
+ SampleRate,
+
+ // Music
+ AlbumTitle,
+ AlbumArtist,
+ ContributingArtist,
+ Composer,
+ Conductor,
+ Lyrics,
+ Mood,
+ TrackNumber,
+ TrackCount,
+
+ CoverArtUrlSmall,
+ CoverArtUrlLarge,
+
+ // Image/Video
+ Resolution,
+ PixelAspectRatio,
+
+ // Video
+ VideoFrameRate,
+ VideoBitRate,
+ VideoCodec,
+
+ PosterUrl,
+
+ // Movie
+ ChapterNumber,
+ Director,
+ LeadPerformer,
+ Writer,
+
+ // Photos
+ CameraManufacturer,
+ CameraModel,
+ Event,
+ Subject,
+ Orientation,
+ ExposureTime,
+ FNumber,
+ ExposureProgram,
+ ISOSpeedRatings,
+ ExposureBiasValue,
+ DateTimeOriginal,
+ DateTimeDigitized,
+ SubjectDistance,
+ MeteringMode,
+ LightSource,
+ Flash,
+ FocalLength,
+ ExposureMode,
+ WhiteBalance,
+ DigitalZoomRatio,
+ FocalLengthIn35mmFilm,
+ SceneCaptureType,
+ GainControl,
+ Contrast,
+ Saturation,
+ Sharpness,
+ DeviceSettingDescription,
+
+ PosterImage,
+ CoverArtImage,
+ ThumbnailImage
+
+ };
+
+ enum SupportEstimate
+ {
+ NotSupported,
+ MaybeSupported,
+ ProbablySupported,
+ PreferredService
+ };
+
+ enum EncodingQuality
+ {
+ VeryLowQuality,
+ LowQuality,
+ NormalQuality,
+ HighQuality,
+ VeryHighQuality
+ };
+
+ enum EncodingMode
+ {
+ ConstantQualityEncoding,
+ ConstantBitRateEncoding,
+ AverageBitRateEncoding,
+ TwoPassEncoding
+ };
+
+ enum AvailabilityError
+ {
+ NoError,
+ ServiceMissingError,
+ BusyError,
+ ResourceError
+ };
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qtmedianamespace.qdoc b/src/multimediakit/qtmedianamespace.qdoc
new file mode 100644
index 000000000..a5a642ff0
--- /dev/null
+++ b/src/multimediakit/qtmedianamespace.qdoc
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \namespace QtMultimediaKit
+ \ingroup multimedia
+ \inmodule QtMultimediaKit
+
+ \brief The QtMultimediaKit namespace contains miscellaneous identifiers used throughout the Qt Media services library.
+
+ QtMultimediaKit is a module containing the low level, low latency,
+ Multimedia APIs which were introduced in Qt 4.6 and also includes the
+ high level QtMultimedia APIs which were introduced in QtMobility 1.0.
+
+*/
+
+/*!
+ \enum QtMultimediaKit::MetaData
+
+ This enum provides identifiers for meta-data attributes.
+
+ \note Not all identifiers are supported on all platforms. Please consult vendor documentation for specific support
+ on different platforms.
+
+ Common attributes
+ \value Title The title of the media. QString.
+ \value SubTitle The sub-title of the media. QString.
+ \value Author The authors of the media. QStringList.
+ \value Comment A user comment about the media. QString.
+ \value Description A description of the media. QString
+ \value Category The category of the media. QStringList.
+ \value Genre The genre of the media. QStringList.
+ \value Year The year of release of the media. int.
+ \value Date The date of the media. QDate.
+ \value UserRating A user rating of the media. int [0..100].
+ \value Keywords A list of keywords describing the media. QStringList.
+ \value Language The language of media, as an ISO 639-2 code.
+
+ \value Publisher The publisher of the media. QString.
+ \value Copyright The media's copyright notice. QString.
+ \value ParentalRating The parental rating of the media. QString.
+ \value RatingOrganisation The organisation responsible for the parental rating of the media.
+ QString.
+
+ Media attributes
+ \value Size The size in bytes of the media. qint64
+ \value MediaType The type of the media (audio, video, etc). QString.
+ \value Duration The duration in millseconds of the media. qint64.
+
+ Audio attributes
+ \value AudioBitRate The bit rate of the media's audio stream in bits per second. int.
+ \value AudioCodec The codec of the media's audio stream. QString.
+ \value AverageLevel The average volume level of the media. int.
+ \value ChannelCount The number of channels in the media's audio stream. int.
+ \value PeakValue The peak volume of the media's audio stream. int
+ \value SampleRate The sample rate of the media's audio stream in hertz. int
+
+ Music attributes
+ \value AlbumTitle The title of the album the media belongs to. QString.
+ \value AlbumArtist The principal artist of the album the media belongs to. QString.
+ \value ContributingArtist The artists contributing to the media. QStringList.
+ \value Composer The composer of the media. QStringList.
+ \value Conductor The conductor of the media. QString.
+ \value Lyrics The lyrics to the media. QString.
+ \value Mood The mood of the media. QString.
+ \value TrackNumber The track number of the media. int.
+ \value TrackCount The number of tracks on the album containing the media. int.
+
+ \value CoverArtUrlSmall The URL of a small cover art image. QUrl.
+ \value CoverArtUrlLarge The URL of a large cover art image. QUrl.
+ \value CoverArtImage An embedded cover art image. QImage.
+
+ Image and video attributes
+ \value Resolution The dimensions of an image or video. QSize.
+ \value PixelAspectRatio The pixel aspect ratio of an image or video. QSize.
+
+ Video attributes
+ \value VideoFrameRate The frame rate of the media's video stream. qreal.
+ \value VideoBitRate The bit rate of the media's video stream in bits per second. int.
+ \value VideoCodec The codec of the media's video stream. QString.
+
+ \value PosterUrl The URL of a poster image. QUrl.
+ \value PosterImage An embedded poster image. QImage.
+
+ Movie attributes
+ \value ChapterNumber The chapter number of the media. int.
+ \value Director The director of the media. QString.
+ \value LeadPerformer The lead performer in the media. QStringList.
+ \value Writer The writer of the media. QStringList.
+
+ Photo attributes.
+ \value CameraManufacturer The manufacturer of the camera used to capture the media. QString.
+ \value CameraModel The model of the camera used to capture the media. QString.
+ \value Event The event during which the media was captured. QString.
+ \value Subject The subject of the media. QString.
+ \value Orientation Orientation of image.
+ \value ExposureTime Exposure time, given in seconds.
+ \value FNumber The F Number.
+ \value ExposureProgram
+ The class of the program used by the camera to set exposure when the picture is taken.
+ \value ISOSpeedRatings
+ Indicates the ISO Speed and ISO Latitude of the camera or input device as specified in ISO 12232.
+ \value ExposureBiasValue
+ The exposure bias.
+ The unit is the APEX (Additive System of Photographic Exposure) setting.
+ \value DateTimeOriginal The date and time when the original image data was generated.
+ \value DateTimeDigitized The date and time when the image was stored as digital data.
+ \value SubjectDistance The distance to the subject, given in meters.
+ \value MeteringMode The metering mode.
+ \value LightSource
+ The kind of light source.
+ \value Flash
+ Status of flash when the image was shot.
+ \value FocalLength
+ The actual focal length of the lens, in mm.
+ \value ExposureMode
+ Indicates the exposure mode set when the image was shot.
+ \value WhiteBalance
+ Indicates the white balance mode set when the image was shot.
+ \value DigitalZoomRatio
+ Indicates the digital zoom ratio when the image was shot.
+ \value FocalLengthIn35mmFilm
+ Indicates the equivalent focal length assuming a 35mm film camera, in mm.
+ \value SceneCaptureType
+ Indicates the type of scene that was shot.
+ It can also be used to record the mode in which the image was shot.
+ \value GainControl
+ Indicates the degree of overall image gain adjustment.
+ \value Contrast
+ Indicates the direction of contrast processing applied by the camera when the image was shot.
+ \value Saturation
+ Indicates the direction of saturation processing applied by the camera when the image was shot.
+ \value Sharpness
+ Indicates the direction of sharpness processing applied by the camera when the image was shot.
+ \value DeviceSettingDescription
+ Exif tag, indicates information on the picture-taking conditions of a particular camera model. QString
+
+ \value ThumbnailImage An embedded thumbnail image. QImage.
+*/
+
+/*!
+ \enum QtMultimediaKit::SupportEstimate
+
+ Enumerates the levels of support a media service provider may have for a feature.
+
+ \value NotSupported The feature is not supported.
+ \value MaybeSupported The feature may be supported.
+ \value ProbablySupported The feature is probably supported.
+ \value PreferredService The service is the preferred provider of a service.
+*/
+
+/*!
+ \enum QtMultimediaKit::EncodingQuality
+
+ Enumerates quality encoding levels.
+
+ \value VeryLowQuality
+ \value LowQuality
+ \value NormalQuality
+ \value HighQuality
+ \value VeryHighQuality
+*/
+
+/*!
+ \enum QtMultimediaKit::EncodingMode
+
+ Enumerates encoding modes.
+
+ \value ConstantQualityEncoding
+ \value ConstantBitRateEncoding
+ \value AverageBitRateEncoding
+ \value TwoPassEncoding
+*/
+
+/*!
+ \enum QtMultimediaKit::AvailabilityError
+
+ Enumerates Service status errors.
+
+ \value NoError The service is operating correctly.
+ \value ServiceMissingError There is no service available to provide the requested functionality.
+ \value ResourceError The service could not allocate resources required to function correctly.
+ \value BusyError The service must wait for access to necessary resources.
+*/
diff --git a/src/multimediakit/qvideodevicecontrol.cpp b/src/multimediakit/qvideodevicecontrol.cpp
new file mode 100644
index 000000000..27fe122f9
--- /dev/null
+++ b/src/multimediakit/qvideodevicecontrol.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** 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 "qvideodevicecontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVideoDeviceControl
+
+ \brief The QVideoDeviceControl class provides an video device selector media control.
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ The QVideoDeviceControl class provides descriptions of the video devices
+ available on a system and allows one to be selected as the endpoint of a
+ media service.
+
+ The interface name of QVideoDeviceControl is \c com.nokia.Qt.VideoDeviceControl as
+ defined in QVideoDeviceControl_iid.
+*/
+
+/*!
+ \macro QVideoDeviceControl_iid
+
+ \c com.nokia.Qt.VideoDeviceControl
+
+ Defines the interface name of the QVideoDeviceControl class.
+
+ \relates QVideoDeviceControl
+*/
+
+/*!
+ Constructs a video device control with the given \a parent.
+*/
+QVideoDeviceControl::QVideoDeviceControl(QObject *parent)
+ :QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys a video device control.
+*/
+QVideoDeviceControl::~QVideoDeviceControl()
+{
+}
+
+/*!
+ \fn QVideoDeviceControl::deviceCount() const
+
+ Returns the number of available video devices;
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoDeviceControl::deviceName(int index) const
+
+ Returns the name of the video device at \a index.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoDeviceControl::deviceDescription(int index) const
+
+ Returns a description of the video device at \a index.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoDeviceControl::deviceIcon(int index) const
+
+ Returns an icon for the video device at \a index.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoDeviceControl::defaultDevice() const
+
+ Returns the index of the default video device.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoDeviceControl::selectedDevice() const
+
+ Returns the index of the selected video device.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoDeviceControl::setSelectedDevice(int index)
+
+ Sets the selected video device \a index.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoDeviceControl::devicesChanged()
+
+ Signals that the list of available video devices has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoDeviceControl::selectedDeviceChanged(int index)
+
+ Signals that the selected video device \a index has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoDeviceControl::selectedDeviceChanged(const QString &name)
+
+ Signals that the selected video device \a name has changed.
+ \since 1.0
+*/
+
+#include "moc_qvideodevicecontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qvideodevicecontrol.h b/src/multimediakit/qvideodevicecontrol.h
new file mode 100644
index 000000000..0d204739c
--- /dev/null
+++ b/src/multimediakit/qvideodevicecontrol.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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 QVIDEODEVICECONTROL_H
+#define QVIDEODEVICECONTROL_H
+
+#include "qmediacontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QVideoDeviceControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ virtual ~QVideoDeviceControl();
+
+ virtual int deviceCount() const = 0;
+
+ virtual QString deviceName(int index) const = 0;
+ virtual QString deviceDescription(int index) const = 0;
+ virtual QIcon deviceIcon(int index) const = 0;
+
+ virtual int defaultDevice() const = 0;
+ virtual int selectedDevice() const = 0;
+
+public Q_SLOTS:
+ virtual void setSelectedDevice(int index) = 0;
+
+Q_SIGNALS:
+ void selectedDeviceChanged(int index);
+ void selectedDeviceChanged(const QString &deviceName);
+ void devicesChanged();
+
+protected:
+ QVideoDeviceControl(QObject *parent = 0);
+};
+
+#define QVideoDeviceControl_iid "com.nokia.Qt.QVideoDeviceControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QVideoDeviceControl, QVideoDeviceControl_iid)
+
+
+QT_END_NAMESPACE
+
+#endif // QVIDEODEVICECONTROL_H
diff --git a/src/multimediakit/qvideoencodercontrol.cpp b/src/multimediakit/qvideoencodercontrol.cpp
new file mode 100644
index 000000000..b06286f9b
--- /dev/null
+++ b/src/multimediakit/qvideoencodercontrol.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** 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 "qvideoencodercontrol.h"
+#include <QtCore/qstringlist.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVideoEncoderControl
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ \brief The QVideoEncoderControl class provides access to the settings
+ of a media service that performs video encoding.
+
+ If a QMediaService supports encoding video data it will implement
+ QVideoEncoderControl. This control provides information about the limits
+ of restricted video encoder options and allows the selection of a set of
+ video encoder settings as specified in a QVideoEncoderSettings object.
+
+ The functionality provided by this control is exposed to application code
+ through the QMediaRecorder class.
+
+ The interface name of QVideoEncoderControl is \c com.nokia.Qt.QVideoEncoderControl/1.0 as
+ defined in QVideoEncoderControl_iid.
+
+ \sa QMediaRecorder, QVideoEncoderSettings, QMediaService::requestControl()
+*/
+
+/*!
+ \macro QVideoEncoderControl_iid
+
+ \c com.nokia.Qt.QVideoEncoderControl/1.0
+
+ Defines the interface name of the QVideoEncoderControl class.
+
+ \relates QVideoEncoderControl
+*/
+
+/*!
+ Create a new video encoder control object with the given \a parent.
+*/
+QVideoEncoderControl::QVideoEncoderControl(QObject *parent)
+ :QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys a video encoder control.
+*/
+QVideoEncoderControl::~QVideoEncoderControl()
+{
+}
+
+/*!
+ \fn QVideoEncoderControl::supportedVideoCodecs() const
+
+ Returns the list of supported video codecs.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoEncoderControl::videoCodecDescription(const QString &codec) const
+
+ Returns a description of a video \a codec.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoEncoderControl::supportedEncodingOptions(const QString &codec) const
+
+ Returns a list of supported encoding options for a video \a codec.
+
+ The names and types of the options in the list is system dependent.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoEncoderControl::encodingOption(const QString &codec, const QString &option) const
+
+ Returns the value of a video \a codec \a option.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoEncoderControl::setEncodingOption(const QString &codec, const QString &option, const QVariant &value)
+
+ Sets the \a value of a \a codec specific \a option.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoEncoderControl::supportedResolutions(const QVideoEncoderSettings &settings = QVideoEncoderSettings(),
+ bool *continuous = 0) const
+
+ Returns a list of supported resolutions.
+
+ If non null video \a settings parameter is passed,
+ the returned list is reduced to resolution supported with partial settings like
+ \l {QVideoEncoderSettings::setCodec()}{video codec} or
+ \l {QVideoEncoderSettings::setFrameRate()}{frame rate} applied.
+
+ If the encoder supports arbitrary resolutions within the supported resolutions range,
+ *\a continuous is set to true, otherwise *\a continuous is set to false.
+
+ \since 1.0
+ \sa QVideoEncoderSettings::resolution()
+*/
+
+/*!
+ \fn QVideoEncoderControl::supportedFrameRates(const QVideoEncoderSettings &settings = QVideoEncoderSettings(),
+ bool *continuous = 0) const
+
+ Returns a list of supported frame rates.
+
+ If non null video \a settings parameter is passed,
+ the returned list is reduced to frame rates supported with partial settings like
+ \l {QVideoEncoderSettings::setCodec()}{video codec} or
+ \l {QVideoEncoderSettings::setResolution()}{video resolution} applied.
+
+ If the encoder supports arbitrary frame rates within the supported range,
+ *\a continuous is set to true, otherwise *\a continuous is set to false.
+
+ \since 1.0
+ \sa QVideoEncoderSettings::frameRate()
+*/
+
+/*!
+ \fn QVideoEncoderControl::videoSettings() const
+
+ Returns the video encoder settings.
+
+ The returned value may be different tha passed to QVideoEncoderControl::setVideoSettings()
+ if the settings contains the default or undefined parameters.
+ In this case if the undefined parameters are already resolved, they should be returned.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoEncoderControl::setVideoSettings(const QVideoEncoderSettings &settings)
+
+ Sets the selected video encoder \a settings.
+ \since 1.0
+*/
+
+#include "moc_qvideoencodercontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qvideoencodercontrol.h b/src/multimediakit/qvideoencodercontrol.h
new file mode 100644
index 000000000..2952d7a71
--- /dev/null
+++ b/src/multimediakit/qvideoencodercontrol.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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 QVIDEOENCODERCONTROL_H
+#define QVIDEOENCODERCONTROL_H
+
+#include "qmediacontrol.h"
+#include "qmediarecorder.h"
+
+#include <QtCore/qpair.h>
+#include <QtCore/qsize.h>
+
+QT_BEGIN_NAMESPACE
+class QByteArray;
+class QStringList;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QVideoEncoderControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ virtual ~QVideoEncoderControl();
+
+ virtual QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings,
+ bool *continuous = 0) const = 0;
+
+ virtual QList<qreal> supportedFrameRates(const QVideoEncoderSettings &settings,
+ bool *continuous = 0) const = 0;
+
+ virtual QStringList supportedVideoCodecs() const = 0;
+ virtual QString videoCodecDescription(const QString &codecName) const = 0;
+
+ virtual QVideoEncoderSettings videoSettings() const = 0;
+ virtual void setVideoSettings(const QVideoEncoderSettings &settings) = 0;
+
+ virtual QStringList supportedEncodingOptions(const QString &codec) const = 0;
+ virtual QVariant encodingOption(const QString &codec, const QString &name) const = 0;
+ virtual void setEncodingOption(const QString &codec, const QString &name, const QVariant &value) = 0;
+
+protected:
+ QVideoEncoderControl(QObject *parent = 0);
+};
+
+#define QVideoEncoderControl_iid "com.nokia.Qt.QVideoEncoderControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QVideoEncoderControl, QVideoEncoderControl_iid)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qvideorenderercontrol.cpp b/src/multimediakit/qvideorenderercontrol.cpp
new file mode 100644
index 000000000..1368fb0b7
--- /dev/null
+++ b/src/multimediakit/qvideorenderercontrol.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qvideorenderercontrol.h"
+
+#include "qmediacontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVideoRendererControl
+
+
+ \brief The QVideoRendererControl class provides a control for rendering
+ to a video surface.
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ Using the surface() property of QVideoRendererControl a
+ QAbstractVideoSurface may be set as the video render target of a
+ QMediaService.
+
+ \snippet doc/src/snippets/multimedia-snippets/video.cpp Video renderer control
+
+ QVideoRendererControl is one of a number of possible video output controls.
+
+ The interface name of QVideoRendererControl is \c com.nokia.Qt.QVideoRendererControl/1.0 as
+ defined in QVideoRendererControl_iid.
+
+ \sa QMediaService::requestControl(), QVideoWidget
+*/
+
+/*!
+ \macro QVideoRendererControl_iid
+
+ \c com.nokia.Qt.QVideoRendererControl/1.0
+
+ Defines the interface name of the QVideoRendererControl class.
+
+ \relates QVideoRendererControl
+*/
+
+/*!
+ Constructs a new video renderer media end point with the given \a parent.
+*/
+QVideoRendererControl::QVideoRendererControl(QObject *parent)
+ : QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys a video renderer media end point.
+*/
+QVideoRendererControl::~QVideoRendererControl()
+{
+}
+
+/*!
+ \fn QVideoRendererControl::surface() const
+
+ Returns the surface a video producer renders to.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
+
+ Sets the \a surface a video producer renders to.
+ \since 1.0
+*/
+
+#include "moc_qvideorenderercontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qvideorenderercontrol.h b/src/multimediakit/qvideorenderercontrol.h
new file mode 100644
index 000000000..aa815b986
--- /dev/null
+++ b/src/multimediakit/qvideorenderercontrol.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** 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 QVIDEORENDERERCONTROL_H
+#define QVIDEORENDERERCONTROL_H
+
+#include "qmediacontrol.h"
+
+QT_BEGIN_NAMESPACE
+class QAbstractVideoSurface;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+
+class Q_MULTIMEDIA_EXPORT QVideoRendererControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ ~QVideoRendererControl();
+
+ virtual QAbstractVideoSurface *surface() const = 0;
+ virtual void setSurface(QAbstractVideoSurface *surface) = 0;
+
+protected:
+ QVideoRendererControl(QObject *parent = 0);
+};
+
+#define QVideoRendererControl_iid "com.nokia.Qt.QVideoRendererControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QVideoRendererControl, QVideoRendererControl_iid)
+
+QT_END_NAMESPACE
+
+#endif // QVIDEORENDERERCONTROL_H
diff --git a/src/multimediakit/qvideosurfaceoutput.cpp b/src/multimediakit/qvideosurfaceoutput.cpp
new file mode 100644
index 000000000..9dfbaaa43
--- /dev/null
+++ b/src/multimediakit/qvideosurfaceoutput.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qvideosurfaceoutput_p.h"
+
+#include <qabstractvideosurface.h>
+#include <qmediaservice.h>
+#include <qvideorenderercontrol.h>
+
+
+QVideoSurfaceOutput::QVideoSurfaceOutput(QObject*parent)
+ : QObject(parent)
+{
+}
+
+QVideoSurfaceOutput::~QVideoSurfaceOutput()
+{
+ if (m_control) {
+ m_control.data()->setSurface(0);
+ m_service.data()->releaseControl(m_control.data());
+ }
+}
+
+QMediaObject *QVideoSurfaceOutput::mediaObject() const
+{
+ return m_object.data();
+}
+
+void QVideoSurfaceOutput::setVideoSurface(QAbstractVideoSurface *surface)
+{
+ m_surface = surface;
+
+ if (m_control)
+ m_control.data()->setSurface(surface);
+}
+
+bool QVideoSurfaceOutput::setMediaObject(QMediaObject *object)
+{
+ if (m_control) {
+ m_control.data()->setSurface(0);
+ m_service.data()->releaseControl(m_control.data());
+ }
+ m_control.clear();
+ m_service.clear();
+ m_object.clear();
+
+ if (object) {
+ if (QMediaService *service = object->service()) {
+ if (QMediaControl *control = service->requestControl(QVideoRendererControl_iid)) {
+ if ((m_control = qobject_cast<QVideoRendererControl *>(control))) {
+ m_service = service;
+ m_object = object;
+ m_control.data()->setSurface(m_surface.data());
+
+ return true;
+ }
+ service->releaseControl(control);
+ }
+ }
+ }
+ return false;
+}
diff --git a/src/multimediakit/qvideosurfaceoutput_p.h b/src/multimediakit/qvideosurfaceoutput_p.h
new file mode 100644
index 000000000..3ef93fd27
--- /dev/null
+++ b/src/multimediakit/qvideosurfaceoutput_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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 QVIDEOSURFACEOUTPUT_P_H
+#define QVIDEOSURFACEOUTPUT_P_H
+
+#include <qmediabindableinterface.h>
+
+#include <QtCore/qsharedpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractVideoSurface;
+class QVideoRendererControl;
+
+class QVideoSurfaceOutput : public QObject, public QMediaBindableInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaBindableInterface)
+public:
+ QVideoSurfaceOutput(QObject*parent = 0);
+ ~QVideoSurfaceOutput();
+
+ QMediaObject *mediaObject() const;
+
+ void setVideoSurface(QAbstractVideoSurface *surface);
+
+protected:
+ bool setMediaObject(QMediaObject *object);
+
+private:
+ QWeakPointer<QAbstractVideoSurface> m_surface;
+ QWeakPointer<QVideoRendererControl> m_control;
+ QWeakPointer<QMediaService> m_service;
+ QWeakPointer<QMediaObject> m_object;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qvideowidget.cpp b/src/multimediakit/qvideowidget.cpp
new file mode 100644
index 000000000..6d6811d6f
--- /dev/null
+++ b/src/multimediakit/qvideowidget.cpp
@@ -0,0 +1,1049 @@
+/****************************************************************************
+**
+** 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 "qvideowidget_p.h"
+
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qvideowindowcontrol.h>
+#include <qvideowidgetcontrol.h>
+
+#include <qpaintervideosurface_p.h>
+#include <qvideorenderercontrol.h>
+#include <qvideosurfaceformat.h>
+#include <qpainter.h>
+
+#include <qapplication.h>
+#include <qevent.h>
+#include <qdialog.h>
+#include <qboxlayout.h>
+#include <qnamespace.h>
+
+using namespace Qt;
+
+QT_BEGIN_NAMESPACE
+
+QVideoWidgetControlBackend::QVideoWidgetControlBackend(
+ QMediaService *service, QVideoWidgetControl *control, QWidget *widget)
+ : m_service(service)
+ , m_widgetControl(control)
+{
+ connect(control, SIGNAL(brightnessChanged(int)), widget, SLOT(_q_brightnessChanged(int)));
+ connect(control, SIGNAL(contrastChanged(int)), widget, SLOT(_q_contrastChanged(int)));
+ connect(control, SIGNAL(hueChanged(int)), widget, SLOT(_q_hueChanged(int)));
+ connect(control, SIGNAL(saturationChanged(int)), widget, SLOT(_q_saturationChanged(int)));
+ connect(control, SIGNAL(fullScreenChanged(bool)), widget, SLOT(_q_fullScreenChanged(bool)));
+
+ QBoxLayout *layout = new QVBoxLayout;
+ layout->setMargin(0);
+ layout->setSpacing(0);
+
+#ifdef Q_OS_SYMBIAN
+ // On some cases the flag is not reset automatically
+ // This would lead to viewfinder not being visible on Symbian
+ control->videoWidget()->setAttribute(Qt::WA_WState_ExplicitShowHide, false);
+#endif // Q_OS_SYMBIAN
+
+ layout->addWidget(control->videoWidget());
+
+ widget->setLayout(layout);
+}
+
+void QVideoWidgetControlBackend::releaseControl()
+{
+ m_service->releaseControl(m_widgetControl);
+}
+
+void QVideoWidgetControlBackend::setBrightness(int brightness)
+{
+ m_widgetControl->setBrightness(brightness);
+}
+
+void QVideoWidgetControlBackend::setContrast(int contrast)
+{
+ m_widgetControl->setContrast(contrast);
+}
+
+void QVideoWidgetControlBackend::setHue(int hue)
+{
+ m_widgetControl->setHue(hue);
+}
+
+void QVideoWidgetControlBackend::setSaturation(int saturation)
+{
+ m_widgetControl->setSaturation(saturation);
+}
+
+void QVideoWidgetControlBackend::setFullScreen(bool fullScreen)
+{
+ m_widgetControl->setFullScreen(fullScreen);
+}
+
+
+Qt::AspectRatioMode QVideoWidgetControlBackend::aspectRatioMode() const
+{
+ return m_widgetControl->aspectRatioMode();
+}
+
+void QVideoWidgetControlBackend::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_widgetControl->setAspectRatioMode(mode);
+}
+
+QRendererVideoWidgetBackend::QRendererVideoWidgetBackend(
+ QMediaService *service, QVideoRendererControl *control, QWidget *widget)
+ : m_service(service)
+ , m_rendererControl(control)
+ , m_widget(widget)
+ , m_surface(new QPainterVideoSurface)
+ , m_aspectRatioMode(Qt::KeepAspectRatio)
+ , m_updatePaintDevice(true)
+{
+ connect(this, SIGNAL(brightnessChanged(int)), m_widget, SLOT(_q_brightnessChanged(int)));
+ connect(this, SIGNAL(contrastChanged(int)), m_widget, SLOT(_q_contrastChanged(int)));
+ connect(this, SIGNAL(hueChanged(int)), m_widget, SLOT(_q_hueChanged(int)));
+ connect(this, SIGNAL(saturationChanged(int)), m_widget, SLOT(_q_saturationChanged(int)));
+ connect(m_surface, SIGNAL(frameChanged()), this, SLOT(frameChanged()));
+ connect(m_surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SLOT(formatChanged(QVideoSurfaceFormat)));
+
+ m_rendererControl->setSurface(m_surface);
+}
+
+QRendererVideoWidgetBackend::~QRendererVideoWidgetBackend()
+{
+ delete m_surface;
+}
+
+void QRendererVideoWidgetBackend::releaseControl()
+{
+ m_service->releaseControl(m_rendererControl);
+}
+
+void QRendererVideoWidgetBackend::clearSurface()
+{
+ m_rendererControl->setSurface(0);
+}
+
+void QRendererVideoWidgetBackend::setBrightness(int brightness)
+{
+ m_surface->setBrightness(brightness);
+
+ emit brightnessChanged(brightness);
+}
+
+void QRendererVideoWidgetBackend::setContrast(int contrast)
+{
+ m_surface->setContrast(contrast);
+
+ emit contrastChanged(contrast);
+}
+
+void QRendererVideoWidgetBackend::setHue(int hue)
+{
+ m_surface->setHue(hue);
+
+ emit hueChanged(hue);
+}
+
+void QRendererVideoWidgetBackend::setSaturation(int saturation)
+{
+ m_surface->setSaturation(saturation);
+
+ emit saturationChanged(saturation);
+}
+
+Qt::AspectRatioMode QRendererVideoWidgetBackend::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void QRendererVideoWidgetBackend::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_aspectRatioMode = mode;
+
+ m_widget->updateGeometry();
+}
+
+void QRendererVideoWidgetBackend::setFullScreen(bool)
+{
+}
+
+QSize QRendererVideoWidgetBackend::sizeHint() const
+{
+ return m_surface->surfaceFormat().sizeHint();
+}
+
+void QRendererVideoWidgetBackend::showEvent()
+{
+}
+
+void QRendererVideoWidgetBackend::hideEvent(QHideEvent *)
+{
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ m_updatePaintDevice = true;
+ m_surface->setGLContext(0);
+#endif
+}
+
+void QRendererVideoWidgetBackend::resizeEvent(QResizeEvent *)
+{
+ updateRects();
+}
+
+void QRendererVideoWidgetBackend::moveEvent(QMoveEvent *)
+{
+}
+
+void QRendererVideoWidgetBackend::paintEvent(QPaintEvent *event)
+{
+ QPainter painter(m_widget);
+
+ if (m_widget->testAttribute(Qt::WA_OpaquePaintEvent)) {
+ QRegion borderRegion = event->region();
+ borderRegion = borderRegion.subtracted(m_boundingRect);
+
+ QBrush brush = m_widget->palette().window();
+
+ QVector<QRect> rects = borderRegion.rects();
+ for (QVector<QRect>::iterator it = rects.begin(), end = rects.end(); it != end; ++it) {
+ painter.fillRect(*it, brush);
+ }
+ }
+
+ if (m_surface->isActive() && m_boundingRect.intersects(event->rect())) {
+ m_surface->paint(&painter, m_boundingRect, m_sourceRect);
+
+ m_surface->setReady(true);
+ } else {
+ #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+ if (m_updatePaintDevice && (painter.paintEngine()->type() == QPaintEngine::OpenGL
+ || painter.paintEngine()->type() == QPaintEngine::OpenGL2)) {
+ m_updatePaintDevice = false;
+
+ m_surface->setGLContext(const_cast<QGLContext *>(QGLContext::currentContext()));
+ if (m_surface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) {
+ m_surface->setShaderType(QPainterVideoSurface::GlslShader);
+ } else {
+ m_surface->setShaderType(QPainterVideoSurface::FragmentProgramShader);
+ }
+ }
+#endif
+ }
+
+}
+
+void QRendererVideoWidgetBackend::formatChanged(const QVideoSurfaceFormat &format)
+{
+ m_nativeSize = format.sizeHint();
+
+ updateRects();
+
+ m_widget->updateGeometry();
+ m_widget->update();
+}
+
+void QRendererVideoWidgetBackend::frameChanged()
+{
+ m_widget->update(m_boundingRect);
+}
+
+void QRendererVideoWidgetBackend::updateRects()
+{
+ QRect rect = m_widget->rect();
+
+ if (m_nativeSize.isEmpty()) {
+ m_boundingRect = QRect();
+ } else if (m_aspectRatioMode == Qt::IgnoreAspectRatio) {
+ m_boundingRect = rect;
+ m_sourceRect = QRectF(0, 0, 1, 1);
+ } else if (m_aspectRatioMode == Qt::KeepAspectRatio) {
+ QSize size = m_nativeSize;
+ size.scale(rect.size(), Qt::KeepAspectRatio);
+
+ m_boundingRect = QRect(0, 0, size.width(), size.height());
+ m_boundingRect.moveCenter(rect.center());
+
+ m_sourceRect = QRectF(0, 0, 1, 1);
+ } else if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
+ m_boundingRect = rect;
+
+ QSizeF size = rect.size();
+ size.scale(m_nativeSize, Qt::KeepAspectRatio);
+
+ m_sourceRect = QRectF(
+ 0, 0, size.width() / m_nativeSize.width(), size.height() / m_nativeSize.height());
+ m_sourceRect.moveCenter(QPointF(0.5, 0.5));
+ }
+}
+
+QWindowVideoWidgetBackend::QWindowVideoWidgetBackend(
+ QMediaService *service, QVideoWindowControl *control, QWidget *widget)
+ : m_service(service)
+ , m_windowControl(control)
+ , m_widget(widget)
+ , m_aspectRatioMode(Qt::KeepAspectRatio)
+{
+ connect(control, SIGNAL(brightnessChanged(int)), m_widget, SLOT(_q_brightnessChanged(int)));
+ connect(control, SIGNAL(contrastChanged(int)), m_widget, SLOT(_q_contrastChanged(int)));
+ connect(control, SIGNAL(hueChanged(int)), m_widget, SLOT(_q_hueChanged(int)));
+ connect(control, SIGNAL(saturationChanged(int)), m_widget, SLOT(_q_saturationChanged(int)));
+ connect(control, SIGNAL(fullScreenChanged(bool)), m_widget, SLOT(_q_fullScreenChanged(bool)));
+ connect(control, SIGNAL(nativeSizeChanged()), m_widget, SLOT(_q_dimensionsChanged()));
+
+ control->setWinId(widget->winId());
+}
+
+QWindowVideoWidgetBackend::~QWindowVideoWidgetBackend()
+{
+}
+
+void QWindowVideoWidgetBackend::releaseControl()
+{
+ m_service->releaseControl(m_windowControl);
+}
+
+void QWindowVideoWidgetBackend::setBrightness(int brightness)
+{
+ m_windowControl->setBrightness(brightness);
+}
+
+void QWindowVideoWidgetBackend::setContrast(int contrast)
+{
+ m_windowControl->setContrast(contrast);
+}
+
+void QWindowVideoWidgetBackend::setHue(int hue)
+{
+ m_windowControl->setHue(hue);
+}
+
+void QWindowVideoWidgetBackend::setSaturation(int saturation)
+{
+ m_windowControl->setSaturation(saturation);
+}
+
+void QWindowVideoWidgetBackend::setFullScreen(bool fullScreen)
+{
+ m_windowControl->setFullScreen(fullScreen);
+}
+
+Qt::AspectRatioMode QWindowVideoWidgetBackend::aspectRatioMode() const
+{
+ return m_windowControl->aspectRatioMode();
+}
+
+void QWindowVideoWidgetBackend::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_windowControl->setAspectRatioMode(mode);
+}
+
+QSize QWindowVideoWidgetBackend::sizeHint() const
+{
+ return m_windowControl->nativeSize();
+}
+
+void QWindowVideoWidgetBackend::showEvent()
+{
+ m_windowControl->setWinId(m_widget->winId());
+
+ m_windowControl->setDisplayRect(m_widget->rect());
+
+#if defined(Q_WS_WIN)
+ m_widget->setUpdatesEnabled(false);
+#endif
+}
+
+void QWindowVideoWidgetBackend::hideEvent(QHideEvent *)
+{
+#if defined(Q_WS_WIN)
+ m_widget->setUpdatesEnabled(true);
+#endif
+}
+
+void QWindowVideoWidgetBackend::moveEvent(QMoveEvent *)
+{
+ m_windowControl->setDisplayRect(m_widget->rect());
+}
+
+void QWindowVideoWidgetBackend::resizeEvent(QResizeEvent *)
+{
+ m_windowControl->setDisplayRect(m_widget->rect());
+}
+
+void QWindowVideoWidgetBackend::paintEvent(QPaintEvent *event)
+{
+ if (m_widget->testAttribute(Qt::WA_OpaquePaintEvent)) {
+ QPainter painter(m_widget);
+
+ painter.fillRect(event->rect(), m_widget->palette().window());
+ }
+
+ m_windowControl->repaint();
+
+ event->accept();
+}
+
+#if defined(Q_WS_WIN)
+bool QWindowVideoWidgetBackend::winEvent(MSG *message, long *)
+{
+ if (message->message == WM_PAINT)
+ m_windowControl->repaint();
+
+ return false;
+}
+#endif
+
+void QVideoWidgetPrivate::setCurrentControl(QVideoWidgetControlInterface *control)
+{
+ if (currentControl != control) {
+ currentControl = control;
+
+ currentControl->setBrightness(brightness);
+ currentControl->setContrast(contrast);
+ currentControl->setHue(hue);
+ currentControl->setSaturation(saturation);
+ currentControl->setAspectRatioMode(aspectRatioMode);
+ }
+}
+
+void QVideoWidgetPrivate::clearService()
+{
+ if (service) {
+ QObject::disconnect(service, SIGNAL(destroyed()), q_func(), SLOT(_q_serviceDestroyed()));
+
+ if (widgetBackend) {
+ QLayout *layout = q_func()->layout();
+
+ for (QLayoutItem *item = layout->takeAt(0); item; item = layout->takeAt(0)) {
+ item->widget()->setParent(0);
+ delete item;
+ }
+ delete layout;
+
+ widgetBackend->releaseControl();
+
+ delete widgetBackend;
+ widgetBackend = 0;
+ } else if (rendererBackend) {
+ rendererBackend->clearSurface();
+ rendererBackend->releaseControl();
+
+ delete rendererBackend;
+ rendererBackend = 0;
+ } else {
+ windowBackend->releaseControl();
+
+ delete windowBackend;
+ windowBackend = 0;
+ }
+
+ currentBackend = 0;
+ currentControl = 0;
+ service = 0;
+ }
+}
+
+bool QVideoWidgetPrivate::createWidgetBackend()
+{
+ if (QMediaControl *control = service->requestControl(QVideoWidgetControl_iid)) {
+ if (QVideoWidgetControl *widgetControl = qobject_cast<QVideoWidgetControl *>(control)) {
+ widgetBackend = new QVideoWidgetControlBackend(service, widgetControl, q_func());
+
+ setCurrentControl(widgetBackend);
+
+ return true;
+ }
+ service->releaseControl(control);
+ }
+ return false;
+}
+
+bool QVideoWidgetPrivate::createWindowBackend()
+{
+ if (QMediaControl *control = service->requestControl(QVideoWindowControl_iid)) {
+ if (QVideoWindowControl *windowControl = qobject_cast<QVideoWindowControl *>(control)) {
+ windowBackend = new QWindowVideoWidgetBackend(service, windowControl, q_func());
+ currentBackend = windowBackend;
+
+ setCurrentControl(windowBackend);
+
+ return true;
+ }
+ service->releaseControl(control);
+ }
+ return false;
+}
+
+bool QVideoWidgetPrivate::createRendererBackend()
+{
+ if (QMediaControl *control = service->requestControl(QVideoRendererControl_iid)) {
+ if (QVideoRendererControl *rendererControl = qobject_cast<QVideoRendererControl *>(control)) {
+ rendererBackend = new QRendererVideoWidgetBackend(service, rendererControl, q_func());
+ currentBackend = rendererBackend;
+
+ setCurrentControl(rendererBackend);
+
+ return true;
+ }
+ service->releaseControl(control);
+ }
+ return false;
+}
+
+void QVideoWidgetPrivate::_q_serviceDestroyed()
+{
+ if (widgetBackend)
+ delete q_func()->layout();
+
+ delete widgetBackend;
+ delete windowBackend;
+ delete rendererBackend;
+
+ widgetBackend = 0;
+ windowBackend = 0;
+ rendererBackend = 0;
+ currentControl = 0;
+ currentBackend = 0;
+ service = 0;
+}
+
+void QVideoWidgetPrivate::_q_brightnessChanged(int b)
+{
+ if (b != brightness)
+ emit q_func()->brightnessChanged(brightness = b);
+}
+
+void QVideoWidgetPrivate::_q_contrastChanged(int c)
+{
+ if (c != contrast)
+ emit q_func()->contrastChanged(contrast = c);
+}
+
+void QVideoWidgetPrivate::_q_hueChanged(int h)
+{
+ if (h != hue)
+ emit q_func()->hueChanged(hue = h);
+}
+
+void QVideoWidgetPrivate::_q_saturationChanged(int s)
+{
+ if (s != saturation)
+ emit q_func()->saturationChanged(saturation = s);
+}
+
+
+void QVideoWidgetPrivate::_q_fullScreenChanged(bool fullScreen)
+{
+ if (!fullScreen && q_func()->isFullScreen())
+ q_func()->showNormal();
+}
+
+void QVideoWidgetPrivate::_q_dimensionsChanged()
+{
+ q_func()->updateGeometry();
+ q_func()->update();
+}
+
+/*!
+ \class QVideoWidget
+
+
+ \brief The QVideoWidget class provides a widget which presents video
+ produced by a media object.
+ \ingroup multimedia
+ \inmodule QtMultimediaKit
+ \since 1.0
+
+ \inmodule QtMultimediaKit
+
+ Attaching a QVideoWidget to a QMediaObject allows it to display the
+ video or image output of that media object. A QVideoWidget is attached
+ to media object by passing a pointer to the QMediaObject in its
+ constructor, and detached by destroying the QVideoWidget.
+
+ \snippet doc/src/snippets/multimedia-snippets/video.cpp Video widget
+
+ \bold {Note}: Only a single display output can be attached to a media
+ object at one time.
+
+ \sa QMediaObject, QMediaPlayer, QGraphicsVideoItem
+*/
+
+/*!
+ Constructs a new video widget.
+
+ The \a parent is passed to QWidget.
+*/
+QVideoWidget::QVideoWidget(QWidget *parent)
+ : QWidget(parent, 0)
+ , d_ptr(new QVideoWidgetPrivate)
+{
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ \internal
+*/
+QVideoWidget::QVideoWidget(QVideoWidgetPrivate &dd, QWidget *parent)
+ : QWidget(parent, 0)
+ , d_ptr(&dd)
+{
+ d_ptr->q_ptr = this;
+
+ QPalette palette = QWidget::palette();
+ palette.setColor(QPalette::Background, Qt::black);
+ setPalette(palette);
+}
+
+/*!
+ Destroys a video widget.
+*/
+QVideoWidget::~QVideoWidget()
+{
+ d_ptr->clearService();
+
+ delete d_ptr;
+}
+
+/*!
+ \property QVideoWidget::mediaObject
+ \brief the media object which provides the video displayed by a widget.
+ \since 1.0
+*/
+
+QMediaObject *QVideoWidget::mediaObject() const
+{
+ return d_func()->mediaObject;
+}
+
+/*!
+ \internal
+ \since 1.0
+*/
+bool QVideoWidget::setMediaObject(QMediaObject *object)
+{
+ Q_D(QVideoWidget);
+
+ if (object == d->mediaObject)
+ return true;
+
+ d->clearService();
+
+ d->mediaObject = object;
+
+ if (d->mediaObject)
+ d->service = d->mediaObject->service();
+
+ if (d->service) {
+ if (d->createWidgetBackend()) {
+ // Nothing to do here.
+ } else if ((!window() || !window()->testAttribute(Qt::WA_DontShowOnScreen))
+ && d->createWindowBackend()) {
+ if (isVisible())
+ d->windowBackend->showEvent();
+ } else if (d->createRendererBackend()) {
+ if (isVisible())
+ d->rendererBackend->showEvent();
+ } else {
+ d->service = 0;
+ d->mediaObject = 0;
+
+ return false;
+ }
+
+ connect(d->service, SIGNAL(destroyed()), SLOT(_q_serviceDestroyed()));
+ } else {
+ d->mediaObject = 0;
+
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \property QVideoWidget::aspectRatioMode
+ \brief how video is scaled with respect to its aspect ratio.
+ \since 1.0
+*/
+
+Qt::AspectRatioMode QVideoWidget::aspectRatioMode() const
+{
+ return d_func()->aspectRatioMode;
+}
+
+void QVideoWidget::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ Q_D(QVideoWidget);
+
+ if (d->currentControl) {
+ d->currentControl->setAspectRatioMode(mode);
+ d->aspectRatioMode = d->currentControl->aspectRatioMode();
+ } else {
+ d->aspectRatioMode = mode;
+ }
+}
+
+/*!
+ \property QVideoWidget::fullScreen
+ \brief whether video display is confined to a window or is fullScreen.
+ \since 1.0
+*/
+
+void QVideoWidget::setFullScreen(bool fullScreen)
+{
+ Q_D(QVideoWidget);
+
+ if (fullScreen) {
+ Qt::WindowFlags flags = windowFlags();
+
+ d->nonFullScreenFlags = flags & (Qt::Window | Qt::SubWindow);
+ flags |= Qt::Window;
+ flags &= ~Qt::SubWindow;
+ setWindowFlags(flags);
+
+ showFullScreen();
+ } else {
+ showNormal();
+ }
+}
+
+/*!
+ \fn QVideoWidget::fullScreenChanged(bool fullScreen)
+
+ Signals that the \a fullScreen mode of a video widget has changed.
+
+ \since 1.0
+ \sa fullScreen
+*/
+
+/*!
+ \property QVideoWidget::brightness
+ \brief an adjustment to the brightness of displayed video.
+
+ Valid brightness values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+int QVideoWidget::brightness() const
+{
+ return d_func()->brightness;
+}
+
+void QVideoWidget::setBrightness(int brightness)
+{
+ Q_D(QVideoWidget);
+
+ int boundedBrightness = qBound(-100, brightness, 100);
+
+ if (d->currentControl)
+ d->currentControl->setBrightness(boundedBrightness);
+ else if (d->brightness != boundedBrightness)
+ emit brightnessChanged(d->brightness = boundedBrightness);
+}
+
+/*!
+ \fn QVideoWidget::brightnessChanged(int brightness)
+
+ Signals that a video widgets's \a brightness adjustment has changed.
+
+ \since 1.0
+ \sa brightness
+*/
+
+/*!
+ \property QVideoWidget::contrast
+ \brief an adjustment to the contrast of displayed video.
+
+ Valid contrast values range between -100 and 100, the default is 0.
+
+ \since 1.0
+*/
+
+int QVideoWidget::contrast() const
+{
+ return d_func()->contrast;
+}
+
+void QVideoWidget::setContrast(int contrast)
+{
+ Q_D(QVideoWidget);
+
+ int boundedContrast = qBound(-100, contrast, 100);
+
+ if (d->currentControl)
+ d->currentControl->setContrast(boundedContrast);
+ else if (d->contrast != boundedContrast)
+ emit contrastChanged(d->contrast = boundedContrast);
+}
+
+/*!
+ \fn QVideoWidget::contrastChanged(int contrast)
+
+ Signals that a video widgets's \a contrast adjustment has changed.
+
+ \since 1.0
+ \sa contrast
+*/
+
+/*!
+ \property QVideoWidget::hue
+ \brief an adjustment to the hue of displayed video.
+
+ Valid hue values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+int QVideoWidget::hue() const
+{
+ return d_func()->hue;
+}
+
+void QVideoWidget::setHue(int hue)
+{
+ Q_D(QVideoWidget);
+
+ int boundedHue = qBound(-100, hue, 100);
+
+ if (d->currentControl)
+ d->currentControl->setHue(boundedHue);
+ else if (d->hue != boundedHue)
+ emit hueChanged(d->hue = boundedHue);
+}
+
+/*!
+ \fn QVideoWidget::hueChanged(int hue)
+
+ Signals that a video widgets's \a hue has changed.
+
+ \since 1.0
+ \sa hue
+*/
+
+/*!
+ \property QVideoWidget::saturation
+ \brief an adjustment to the saturation of displayed video.
+
+ Valid saturation values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+int QVideoWidget::saturation() const
+{
+ return d_func()->saturation;
+}
+
+void QVideoWidget::setSaturation(int saturation)
+{
+ Q_D(QVideoWidget);
+
+ int boundedSaturation = qBound(-100, saturation, 100);
+
+ if (d->currentControl)
+ d->currentControl->setSaturation(boundedSaturation);
+ else if (d->saturation != boundedSaturation)
+ emit saturationChanged(d->saturation = boundedSaturation);
+
+}
+
+/*!
+ \fn QVideoWidget::saturationChanged(int saturation)
+
+ Signals that a video widgets's \a saturation has changed.
+
+ \since 1.0
+ \sa saturation
+*/
+
+/*!
+ Returns the size hint for the current back end,
+ if there is one, or else the size hint from QWidget.
+ \since 1.0
+ */
+QSize QVideoWidget::sizeHint() const
+{
+ Q_D(const QVideoWidget);
+
+ if (d->currentBackend)
+ return d->currentBackend->sizeHint();
+ else
+ return QWidget::sizeHint();
+
+
+}
+
+/*!
+ Current event \a event.
+ Returns the value of the baseclass QWidget::event(QEvent *event) function.
+ \since 1.0
+*/
+bool QVideoWidget::event(QEvent *event)
+{
+ Q_D(QVideoWidget);
+
+ if (event->type() == QEvent::WindowStateChange) {
+ Qt::WindowFlags flags = windowFlags();
+
+ if (windowState() & Qt::WindowFullScreen) {
+ if (d->currentControl)
+ d->currentControl->setFullScreen(true);
+
+ if (!d->wasFullScreen)
+ emit fullScreenChanged(d->wasFullScreen = true);
+ } else {
+ if (d->currentControl)
+ d->currentControl->setFullScreen(false);
+
+ if (d->wasFullScreen) {
+ flags &= ~(Qt::Window | Qt::SubWindow); //clear the flags...
+ flags |= d->nonFullScreenFlags; //then we reset the flags (window and subwindow)
+ setWindowFlags(flags);
+
+ emit fullScreenChanged(d->wasFullScreen = false);
+ }
+ }
+ }
+ return QWidget::event(event);
+}
+
+/*!
+ Handles the show \a event.
+ \since 1.0
+ */
+void QVideoWidget::showEvent(QShowEvent *event)
+{
+ Q_D(QVideoWidget);
+
+ QWidget::showEvent(event);
+
+ // The window backend won't work for re-directed windows so use the renderer backend instead.
+ if (d->windowBackend && window()->testAttribute(Qt::WA_DontShowOnScreen)) {
+ d->windowBackend->releaseControl();
+
+ delete d->windowBackend;
+ d->windowBackend = 0;
+
+ d->createRendererBackend();
+ }
+
+ if (d->currentBackend)
+ d->currentBackend->showEvent();
+}
+
+/*!
+
+ Handles the hide \a event.
+ \since 1.0
+*/
+void QVideoWidget::hideEvent(QHideEvent *event)
+{
+ Q_D(QVideoWidget);
+
+ if (d->currentBackend)
+ d->currentBackend->hideEvent(event);
+
+ QWidget::hideEvent(event);
+}
+
+/*!
+ Handles the resize \a event.
+ \since 1.0
+ */
+void QVideoWidget::resizeEvent(QResizeEvent *event)
+{
+ Q_D(QVideoWidget);
+
+ QWidget::resizeEvent(event);
+
+ if (d->currentBackend)
+ d->currentBackend->resizeEvent(event);
+}
+
+/*!
+ Handles the move \a event.
+ \since 1.0
+ */
+void QVideoWidget::moveEvent(QMoveEvent *event)
+{
+ Q_D(QVideoWidget);
+
+ if (d->currentBackend)
+ d->currentBackend->moveEvent(event);
+}
+
+/*!
+ Handles the paint \a event.
+ \since 1.0
+ */
+void QVideoWidget::paintEvent(QPaintEvent *event)
+{
+ Q_D(QVideoWidget);
+
+ if (d->currentBackend) {
+ d->currentBackend->paintEvent(event);
+ } else if (testAttribute(Qt::WA_OpaquePaintEvent)) {
+ QPainter painter(this);
+
+ painter.fillRect(event->rect(), palette().window());
+ }
+}
+
+
+#if defined(Q_WS_WIN)
+/*!
+ \reimp
+ \internal
+ \since 1.1
+*/
+bool QVideoWidget::winEvent(MSG *message, long *result)
+{
+ return d_func()->windowBackend && d_func()->windowBackend->winEvent(message, result)
+ ? true
+ : QWidget::winEvent(message, result);
+}
+#endif
+
+
+#include "moc_qvideowidget.cpp"
+#include "moc_qvideowidget_p.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qvideowidget.h b/src/multimediakit/qvideowidget.h
new file mode 100644
index 000000000..87da76588
--- /dev/null
+++ b/src/multimediakit/qvideowidget.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** 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 QVIDEOWIDGET_H
+#define QVIDEOWIDGET_H
+
+#include <QtGui/qwidget.h>
+
+#include <qmobilityglobal.h>
+#include <qmediabindableinterface.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMediaObject;
+
+class QVideoWidgetPrivate;
+class Q_MULTIMEDIA_EXPORT QVideoWidget : public QWidget, public QMediaBindableInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaBindableInterface)
+ Q_PROPERTY(QMediaObject* mediaObject READ mediaObject WRITE setMediaObject)
+ Q_PROPERTY(bool fullScreen READ isFullScreen WRITE setFullScreen NOTIFY fullScreenChanged)
+ Q_PROPERTY(Qt::AspectRatioMode aspectRatioMode READ aspectRatioMode WRITE setAspectRatioMode)
+ Q_PROPERTY(int brightness READ brightness WRITE setBrightness NOTIFY brightnessChanged)
+ Q_PROPERTY(int contrast READ contrast WRITE setContrast NOTIFY contrastChanged)
+ Q_PROPERTY(int hue READ hue WRITE setHue NOTIFY hueChanged)
+ Q_PROPERTY(int saturation READ saturation WRITE setSaturation NOTIFY saturationChanged)
+
+public:
+ QVideoWidget(QWidget *parent = 0);
+ ~QVideoWidget();
+
+ QMediaObject *mediaObject() const;
+
+#ifdef Q_QDOC
+ bool isFullScreen() const;
+#endif
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+
+ int brightness() const;
+ int contrast() const;
+ int hue() const;
+ int saturation() const;
+
+ QSize sizeHint() const;
+
+public Q_SLOTS:
+ void setFullScreen(bool fullScreen);
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+ void setBrightness(int brightness);
+ void setContrast(int contrast);
+ void setHue(int hue);
+ void setSaturation(int saturation);
+
+Q_SIGNALS:
+ void fullScreenChanged(bool fullScreen);
+ void brightnessChanged(int brightness);
+ void contrastChanged(int contrast);
+ void hueChanged(int hue);
+ void saturationChanged(int saturation);
+
+protected:
+ bool event(QEvent *event);
+ void showEvent(QShowEvent *event);
+ void hideEvent(QHideEvent *event);
+ void resizeEvent(QResizeEvent *event);
+ void moveEvent(QMoveEvent *event);
+ void paintEvent(QPaintEvent *event);
+
+ bool setMediaObject(QMediaObject *object);
+
+#if defined(Q_WS_WIN)
+ bool winEvent(MSG *message, long *result);
+#endif
+
+ QVideoWidget(QVideoWidgetPrivate &dd, QWidget *parent);
+ QVideoWidgetPrivate *d_ptr;
+
+private:
+ Q_DECLARE_PRIVATE(QVideoWidget)
+ Q_PRIVATE_SLOT(d_func(), void _q_serviceDestroyed())
+ Q_PRIVATE_SLOT(d_func(), void _q_brightnessChanged(int))
+ Q_PRIVATE_SLOT(d_func(), void _q_contrastChanged(int))
+ Q_PRIVATE_SLOT(d_func(), void _q_hueChanged(int))
+ Q_PRIVATE_SLOT(d_func(), void _q_saturationChanged(int))
+ Q_PRIVATE_SLOT(d_func(), void _q_fullScreenChanged(bool))
+ Q_PRIVATE_SLOT(d_func(), void _q_dimensionsChanged())
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qvideowidget_p.h b/src/multimediakit/qvideowidget_p.h
new file mode 100644
index 000000000..b5cc704f4
--- /dev/null
+++ b/src/multimediakit/qvideowidget_p.h
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** 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 QVIDEOWIDGET_P_H
+#define QVIDEOWIDGET_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 "qvideowidget.h"
+
+#ifndef QT_NO_OPENGL
+#include <QGLWidget>
+#endif
+
+#include "qpaintervideosurface_p.h"
+
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMediaService;
+
+class QVideoWidgetControlInterface
+{
+public:
+ virtual ~QVideoWidgetControlInterface() {}
+
+ virtual void setBrightness(int brightness) = 0;
+ virtual void setContrast(int contrast) = 0;
+ virtual void setHue(int hue) = 0;
+ virtual void setSaturation(int saturation) = 0;
+
+ virtual void setFullScreen(bool fullScreen) = 0;
+
+ virtual Qt::AspectRatioMode aspectRatioMode() const = 0;
+ virtual void setAspectRatioMode(Qt::AspectRatioMode mode) = 0;
+};
+
+class QVideoWidgetBackend : public QObject, public QVideoWidgetControlInterface
+{
+ Q_OBJECT
+public:
+ virtual QSize sizeHint() const = 0;
+
+ virtual void showEvent() = 0;
+ virtual void hideEvent(QHideEvent *event) = 0;
+ virtual void resizeEvent(QResizeEvent *event) = 0;
+ virtual void moveEvent(QMoveEvent *event) = 0;
+ virtual void paintEvent(QPaintEvent *event) = 0;
+};
+
+class QVideoWidgetControl;
+
+class QVideoWidgetControlBackend : public QObject, public QVideoWidgetControlInterface
+{
+ Q_OBJECT
+public:
+ QVideoWidgetControlBackend(QMediaService *service, QVideoWidgetControl *control, QWidget *widget);
+
+ void releaseControl();
+
+ void setBrightness(int brightness);
+ void setContrast(int contrast);
+ void setHue(int hue);
+ void setSaturation(int saturation);
+
+ void setFullScreen(bool fullScreen);
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+private:
+ QMediaService *m_service;
+ QVideoWidgetControl *m_widgetControl;
+};
+
+
+class QVideoRendererControl;
+
+class QRendererVideoWidgetBackend : public QVideoWidgetBackend
+{
+ Q_OBJECT
+public:
+ QRendererVideoWidgetBackend(QMediaService *service, QVideoRendererControl *control, QWidget *widget);
+ ~QRendererVideoWidgetBackend();
+
+ void releaseControl();
+ void clearSurface();
+
+ void setBrightness(int brightness);
+ void setContrast(int contrast);
+ void setHue(int hue);
+ void setSaturation(int saturation);
+
+ void setFullScreen(bool fullScreen);
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ QSize sizeHint() const;
+
+ void showEvent();
+ void hideEvent(QHideEvent *event);
+ void resizeEvent(QResizeEvent *event);
+ void moveEvent(QMoveEvent *event);
+ void paintEvent(QPaintEvent *event);
+
+Q_SIGNALS:
+ void fullScreenChanged(bool fullScreen);
+ void brightnessChanged(int brightness);
+ void contrastChanged(int contrast);
+ void hueChanged(int hue);
+ void saturationChanged(int saturation);
+
+private Q_SLOTS:
+ void formatChanged(const QVideoSurfaceFormat &format);
+ void frameChanged();
+
+private:
+ void updateRects();
+
+ QMediaService *m_service;
+ QVideoRendererControl *m_rendererControl;
+ QWidget *m_widget;
+ QPainterVideoSurface *m_surface;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QRect m_boundingRect;
+ QRectF m_sourceRect;
+ QSize m_nativeSize;
+ bool m_updatePaintDevice;
+};
+
+class QVideoWindowControl;
+
+class QWindowVideoWidgetBackend : public QVideoWidgetBackend
+{
+ Q_OBJECT
+public:
+ QWindowVideoWidgetBackend(QMediaService *service, QVideoWindowControl *control, QWidget *widget);
+ ~QWindowVideoWidgetBackend();
+
+ void releaseControl();
+
+ void setBrightness(int brightness);
+ void setContrast(int contrast);
+ void setHue(int hue);
+ void setSaturation(int saturation);
+
+ void setFullScreen(bool fullScreen);
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ QSize sizeHint() const;
+
+ void showEvent();
+ void hideEvent(QHideEvent *event);
+ void resizeEvent(QResizeEvent *event);
+ void moveEvent(QMoveEvent *event);
+ void paintEvent(QPaintEvent *event);
+
+#if defined(Q_WS_WIN)
+ bool winEvent(MSG *message, long *result);
+#endif
+
+private:
+ QMediaService *m_service;
+ QVideoWindowControl *m_windowControl;
+ QWidget *m_widget;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QSize m_pixelAspectRatio;
+};
+
+class QMediaService;
+class QVideoOutputControl;
+
+class QVideoWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(QVideoWidget)
+public:
+ QVideoWidgetPrivate()
+ : q_ptr(0)
+ , mediaObject(0)
+ , service(0)
+ , widgetBackend(0)
+ , windowBackend(0)
+ , rendererBackend(0)
+ , currentControl(0)
+ , currentBackend(0)
+ , brightness(0)
+ , contrast(0)
+ , hue(0)
+ , saturation(0)
+ , aspectRatioMode(Qt::KeepAspectRatio)
+ , nonFullScreenFlags(0)
+ , wasFullScreen(false)
+ {
+ }
+
+ QVideoWidget *q_ptr;
+ QPointer<QMediaObject> mediaObject;
+ QMediaService *service;
+ QVideoWidgetControlBackend *widgetBackend;
+ QWindowVideoWidgetBackend *windowBackend;
+ QRendererVideoWidgetBackend *rendererBackend;
+ QVideoWidgetControlInterface *currentControl;
+ QVideoWidgetBackend *currentBackend;
+ int brightness;
+ int contrast;
+ int hue;
+ int saturation;
+ Qt::AspectRatioMode aspectRatioMode;
+ Qt::WindowFlags nonFullScreenFlags;
+ bool wasFullScreen;
+
+ bool createWidgetBackend();
+ bool createWindowBackend();
+ bool createRendererBackend();
+
+ void setCurrentControl(QVideoWidgetControlInterface *control);
+ void clearService();
+
+ void _q_serviceDestroyed();
+ void _q_brightnessChanged(int brightness);
+ void _q_contrastChanged(int contrast);
+ void _q_hueChanged(int hue);
+ void _q_saturationChanged(int saturation);
+ void _q_fullScreenChanged(bool fullScreen);
+ void _q_dimensionsChanged();
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qvideowidgetcontrol.cpp b/src/multimediakit/qvideowidgetcontrol.cpp
new file mode 100644
index 000000000..e6e5743ec
--- /dev/null
+++ b/src/multimediakit/qvideowidgetcontrol.cpp
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** 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 "qvideowidgetcontrol.h"
+#include "qmediacontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVideoWidgetControl
+
+
+ \brief The QVideoWidgetControl class provides a media control which
+ implements a video widget.
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \since 1.0
+
+ The videoWidget() property of QVideoWidgetControl provides a pointer to a
+ video widget implemented by the control's media service. This widget is
+ owned by the media service and so care should be taken not to delete it.
+
+ \snippet doc/src/snippets/multimedia-snippets/video.cpp Video widget control
+
+ QVideoWidgetControl is one of number of possible video output controls.
+
+ The interface name of QVideoWidgetControl is \c com.nokia.Qt.QVideoWidgetControl/1.0 as
+ defined in QVideoWidgetControl_iid.
+
+ \sa QMediaService::requestControl(), QVideoWidget
+*/
+
+/*!
+ \macro QVideoWidgetControl_iid
+
+ \c com.nokia.Qt.QVideoWidgetControl/1.0
+
+ Defines the interface name of the QVideoWidgetControl class.
+
+ \relates QVideoWidgetControl
+*/
+
+/*!
+ Constructs a new video widget control with the given \a parent.
+*/
+QVideoWidgetControl::QVideoWidgetControl(QObject *parent)
+ :QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys a video widget control.
+*/
+QVideoWidgetControl::~QVideoWidgetControl()
+{
+}
+
+/*!
+ \fn QVideoWidgetControl::isFullScreen() const
+
+ Returns true if the video is shown using the complete screen.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::setFullScreen(bool fullScreen)
+
+ Sets whether a video widget is in \a fullScreen mode.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::fullScreenChanged(bool fullScreen)
+
+ Signals that the \a fullScreen state of a video widget has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::aspectRatioMode() const
+
+ Returns how video is scaled to fit the widget with respect to its aspect ratio.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::setAspectRatioMode(Qt::AspectRatioMode mode)
+
+ Sets the aspect ratio \a mode which determines how video is scaled to the fit the widget with
+ respect to its aspect ratio.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::brightness() const
+
+ Returns the brightness adjustment applied to a video.
+
+ Valid brightness values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::setBrightness(int brightness)
+
+ Sets a \a brightness adjustment for a video.
+
+ Valid brightness values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::brightnessChanged(int brightness)
+
+ Signals that a video widget's \a brightness adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::contrast() const
+
+ Returns the contrast adjustment applied to a video.
+
+ Valid contrast values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::setContrast(int contrast)
+
+ Sets the contrast adjustment for a video widget to \a contrast.
+
+ Valid contrast values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+
+/*!
+ \fn QVideoWidgetControl::contrastChanged(int contrast)
+
+ Signals that a video widget's \a contrast adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::hue() const
+
+ Returns the hue adjustment applied to a video widget.
+
+ Value hue values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::setHue(int hue)
+
+ Sets a \a hue adjustment for a video widget.
+
+ Valid hue values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+
+/*!
+ \fn QVideoWidgetControl::hueChanged(int hue)
+
+ Signals that a video widget's \a hue adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::saturation() const
+
+ Returns the saturation adjustment applied to a video widget.
+
+ Value saturation values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+
+/*!
+ \fn QVideoWidgetControl::setSaturation(int saturation)
+
+ Sets a \a saturation adjustment for a video widget.
+
+ Valid saturation values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::saturationChanged(int saturation)
+
+ Signals that a video widget's \a saturation adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWidgetControl::videoWidget()
+
+ Returns the QWidget.
+ \since 1.0
+*/
+
+#include "moc_qvideowidgetcontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qvideowidgetcontrol.h b/src/multimediakit/qvideowidgetcontrol.h
new file mode 100644
index 000000000..44e11bedc
--- /dev/null
+++ b/src/multimediakit/qvideowidgetcontrol.h
@@ -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$
+**
+****************************************************************************/
+
+#ifndef QVIDEOWIDGETCONTROL_H
+#define QVIDEOWIDGETCONTROL_H
+
+#include "qvideowidget.h"
+#include "qmediacontrol.h"
+
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_NAMESPACE
+
+class QVideoWidgetControlPrivate;
+
+class Q_MULTIMEDIA_EXPORT QVideoWidgetControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ virtual ~QVideoWidgetControl();
+
+ virtual QWidget *videoWidget() = 0;
+
+ virtual Qt::AspectRatioMode aspectRatioMode() const = 0;
+ virtual void setAspectRatioMode(Qt::AspectRatioMode mode) = 0;
+
+ virtual bool isFullScreen() const = 0;
+ virtual void setFullScreen(bool fullScreen) = 0;
+
+ virtual int brightness() const = 0;
+ virtual void setBrightness(int brightness) = 0;
+
+ virtual int contrast() const = 0;
+ virtual void setContrast(int contrast) = 0;
+
+ virtual int hue() const = 0;
+ virtual void setHue(int hue) = 0;
+
+ virtual int saturation() const = 0;
+ virtual void setSaturation(int saturation) = 0;
+
+Q_SIGNALS:
+ void fullScreenChanged(bool fullScreen);
+ void brightnessChanged(int brightness);
+ void contrastChanged(int contrast);
+ void hueChanged(int hue);
+ void saturationChanged(int saturation);
+
+protected:
+ QVideoWidgetControl(QObject *parent = 0);
+};
+
+#define QVideoWidgetControl_iid "com.nokia.Qt.QVideoWidgetControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QVideoWidgetControl, QVideoWidgetControl_iid)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qvideowindowcontrol.cpp b/src/multimediakit/qvideowindowcontrol.cpp
new file mode 100644
index 000000000..fec15e002
--- /dev/null
+++ b/src/multimediakit/qvideowindowcontrol.cpp
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** 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 "qvideowindowcontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVideoWindowControl
+
+ \inmodule QtMultimediaKit
+ \ingroup multimedia
+ \brief The QVideoWindowControl class provides a media control for rendering video to a window.
+ \since 1.0
+
+
+ The winId() property QVideoWindowControl allows a platform specific window
+ ID to be set as the video render target of a QMediaService. The
+ displayRect() property is used to set the region of the window the video
+ should be rendered to, and the aspectRatioMode() property indicates how the
+ video should be scaled to fit the displayRect().
+
+ \snippet doc/src/snippets/multimedia-snippets/video.cpp Video window control
+
+ QVideoWindowControl is one of a number of possible video output controls.
+
+ The interface name of QVideoWindowControl is \c com.nokia.Qt.QVideoWindowControl/1.0 as
+ defined in QVideoWindowControl_iid.
+
+ \sa QMediaService::requestControl(), QVideoWidget
+*/
+
+/*!
+ \macro QVideoWindowControl_iid
+
+ \c com.nokia.Qt.QVideoWindowControl/1.0
+
+ Defines the interface name of the QVideoWindowControl class.
+
+ \relates QVideoWindowControl
+*/
+
+/*!
+ Constructs a new video window control with the given \a parent.
+*/
+QVideoWindowControl::QVideoWindowControl(QObject *parent)
+ : QMediaControl(parent)
+{
+}
+
+/*!
+ Destroys a video window control.
+*/
+QVideoWindowControl::~QVideoWindowControl()
+{
+}
+
+/*!
+ \fn QVideoWindowControl::winId() const
+
+ Returns the ID of the window a video overlay end point renders to.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setWinId(WId id)
+
+ Sets the \a id of the window a video overlay end point renders to.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::displayRect() const
+ Returns the sub-rect of a window where video is displayed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setDisplayRect(const QRect &rect)
+ Sets the sub-\a rect of a window where video is displayed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::isFullScreen() const
+
+ Identifies if a video overlay is a fullScreen overlay.
+
+ Returns true if the video overlay is fullScreen, and false otherwise.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setFullScreen(bool fullScreen)
+
+ Sets whether a video overlay is a \a fullScreen overlay.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::fullScreenChanged(bool fullScreen)
+
+ Signals that the \a fullScreen state of a video overlay has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::repaint()
+
+ Repaints the last frame.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::nativeSize() const
+
+ Returns a suggested size for the video display based on the resolution and aspect ratio of the
+ video.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::nativeSizeChanged()
+
+ Signals that the native dimensions of the video have changed.
+ \since 1.0
+*/
+
+
+/*!
+ \fn QVideoWindowControl::aspectRatioMode() const
+
+ Returns how video is scaled to fit the display region with respect to its aspect ratio.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setAspectRatioMode(Qt::AspectRatioMode mode)
+
+ Sets the aspect ratio \a mode which determines how video is scaled to the fit the display region
+ with respect to its aspect ratio.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::brightness() const
+
+ Returns the brightness adjustment applied to a video overlay.
+
+ Valid brightness values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setBrightness(int brightness)
+
+ Sets a \a brightness adjustment for a video overlay.
+
+ Valid brightness values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::brightnessChanged(int brightness)
+
+ Signals that a video overlay's \a brightness adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::contrast() const
+
+ Returns the contrast adjustment applied to a video overlay.
+
+ Valid contrast values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setContrast(int contrast)
+
+ Sets the \a contrast adjustment for a video overlay.
+
+ Valid contrast values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::contrastChanged(int contrast)
+
+ Signals that a video overlay's \a contrast adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::hue() const
+
+ Returns the hue adjustment applied to a video overlay.
+
+ Value hue values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setHue(int hue)
+
+ Sets a \a hue adjustment for a video overlay.
+
+ Valid hue values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::hueChanged(int hue)
+
+ Signals that a video overlay's \a hue adjustment has changed.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::saturation() const
+
+ Returns the saturation adjustment applied to a video overlay.
+
+ Value saturation values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::setSaturation(int saturation)
+ Sets a \a saturation adjustment for a video overlay.
+
+ Valid saturation values range between -100 and 100, the default is 0.
+ \since 1.0
+*/
+
+/*!
+ \fn QVideoWindowControl::saturationChanged(int saturation)
+
+ Signals that a video overlay's \a saturation adjustment has changed.
+ \since 1.0
+*/
+
+#include "moc_qvideowindowcontrol.cpp"
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/qvideowindowcontrol.h b/src/multimediakit/qvideowindowcontrol.h
new file mode 100644
index 000000000..addb0b633
--- /dev/null
+++ b/src/multimediakit/qvideowindowcontrol.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** 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 QVIDEOWINDOWCONTROL_H
+#define QVIDEOWINDOWCONTROL_H
+
+#include "qmediacontrol.h"
+#include "qvideowidget.h"
+
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT QVideoWindowControl : public QMediaControl
+{
+ Q_OBJECT
+
+public:
+ ~QVideoWindowControl();
+
+ virtual WId winId() const = 0;
+ virtual void setWinId(WId id) = 0;
+
+ virtual QRect displayRect() const = 0;
+ virtual void setDisplayRect(const QRect &rect) = 0;
+
+ virtual bool isFullScreen() const = 0;
+ virtual void setFullScreen(bool fullScreen) = 0;
+
+ virtual void repaint() = 0;
+
+ virtual QSize nativeSize() const = 0;
+
+ virtual Qt::AspectRatioMode aspectRatioMode() const = 0;
+ virtual void setAspectRatioMode(Qt::AspectRatioMode mode) = 0;
+
+ virtual int brightness() const = 0;
+ virtual void setBrightness(int brightness) = 0;
+
+ virtual int contrast() const = 0;
+ virtual void setContrast(int contrast) = 0;
+
+ virtual int hue() const = 0;
+ virtual void setHue(int hue) = 0;
+
+ virtual int saturation() const = 0;
+ virtual void setSaturation(int saturation) = 0;
+
+Q_SIGNALS:
+ void fullScreenChanged(bool fullScreen);
+ void brightnessChanged(int brightness);
+ void contrastChanged(int contrast);
+ void hueChanged(int hue);
+ void saturationChanged(int saturation);
+ void nativeSizeChanged();
+
+protected:
+ QVideoWindowControl(QObject *parent = 0);
+};
+
+#define QVideoWindowControl_iid "com.nokia.Qt.QVideoWindowControl/1.0"
+Q_MEDIA_DECLARE_CONTROL(QVideoWindowControl, QVideoWindowControl_iid)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/qxvideosurface_maemo5.cpp b/src/multimediakit/qxvideosurface_maemo5.cpp
new file mode 100644
index 000000000..1289055f2
--- /dev/null
+++ b/src/multimediakit/qxvideosurface_maemo5.cpp
@@ -0,0 +1,497 @@
+/****************************************************************************
+**
+** 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 <QtGui/qx11info_x11.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qvariant.h>
+#include <qvideosurfaceformat.h>
+
+#include "qxvideosurface_maemo5_p.h"
+
+//#define DEBUG_XV_SURFACE
+
+struct XvFormatRgb
+{
+ QVideoFrame::PixelFormat pixelFormat;
+ int bits_per_pixel;
+ int format;
+ int num_planes;
+
+ int depth;
+ unsigned int red_mask;
+ unsigned int green_mask;
+ unsigned int blue_mask;
+
+};
+
+bool operator ==(const XvImageFormatValues &format, const XvFormatRgb &rgb)
+{
+ return format.type == XvRGB
+ && format.bits_per_pixel == rgb.bits_per_pixel
+ && format.format == rgb.format
+ && format.num_planes == rgb.num_planes
+ && format.depth == rgb.depth
+ && format.red_mask == rgb.red_mask
+ && format.blue_mask == rgb.blue_mask;
+}
+
+static const XvFormatRgb qt_xvRgbLookup[] =
+{
+ { QVideoFrame::Format_ARGB32, 32, XvPacked, 1, 32, 0x00FF0000, 0x0000FF00, 0x000000FF },
+ { QVideoFrame::Format_RGB32 , 32, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF },
+ { QVideoFrame::Format_RGB24 , 24, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF },
+ { QVideoFrame::Format_RGB565, 16, XvPacked, 1, 16, 0x0000F800, 0x000007E0, 0x0000001F },
+ { QVideoFrame::Format_BGRA32, 32, XvPacked, 1, 32, 0xFF000000, 0x00FF0000, 0x0000FF00 },
+ { QVideoFrame::Format_BGR32 , 32, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF },
+ { QVideoFrame::Format_BGR24 , 24, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF },
+ { QVideoFrame::Format_BGR565, 16, XvPacked, 1, 16, 0x0000F800, 0x000007E0, 0x0000001F }
+};
+
+struct XvFormatYuv
+{
+ QVideoFrame::PixelFormat pixelFormat;
+ int bits_per_pixel;
+ int format;
+ int num_planes;
+
+ unsigned int y_sample_bits;
+ unsigned int u_sample_bits;
+ unsigned int v_sample_bits;
+ unsigned int horz_y_period;
+ unsigned int horz_u_period;
+ unsigned int horz_v_period;
+ unsigned int vert_y_period;
+ unsigned int vert_u_period;
+ unsigned int vert_v_period;
+ char component_order[32];
+};
+
+bool operator ==(const XvImageFormatValues &format, const XvFormatYuv &yuv)
+{
+ return format.type == XvYUV
+ && format.bits_per_pixel == yuv.bits_per_pixel
+ && format.format == yuv.format
+ && format.num_planes == yuv.num_planes
+ && format.y_sample_bits == yuv.y_sample_bits
+ && format.u_sample_bits == yuv.u_sample_bits
+ && format.v_sample_bits == yuv.v_sample_bits
+ && format.horz_y_period == yuv.horz_y_period
+ && format.horz_u_period == yuv.horz_u_period
+ && format.horz_v_period == yuv.horz_v_period
+ && format.horz_y_period == yuv.vert_y_period
+ && format.vert_u_period == yuv.vert_u_period
+ && format.vert_v_period == yuv.vert_v_period
+ && qstrncmp(format.component_order, yuv.component_order, 32) == 0;
+}
+
+static const XvFormatYuv qt_xvYuvLookup[] =
+{
+ { QVideoFrame::Format_YUV444 , 24, XvPacked, 1, 8, 8, 8, 1, 1, 1, 1, 1, 1, "YUV" },
+ { QVideoFrame::Format_YUV420P, 12, XvPlanar, 3, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YUV" },
+ { QVideoFrame::Format_YV12 , 12, XvPlanar, 3, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU" },
+ { QVideoFrame::Format_UYVY , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "UYVY" },
+ { QVideoFrame::Format_YUYV , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "YUY2" },
+ { QVideoFrame::Format_YUYV , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "YUYV" },
+ { QVideoFrame::Format_NV12 , 12, XvPlanar, 2, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YUV" },
+ { QVideoFrame::Format_NV12 , 12, XvPlanar, 2, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU" },
+ { QVideoFrame::Format_Y8 , 8 , XvPlanar, 1, 8, 0, 0, 1, 0, 0, 1, 0, 0, "Y" }
+};
+
+QXVideoSurface::QXVideoSurface(QObject *parent)
+ : QAbstractVideoSurface(parent)
+ , m_winId(0)
+ , m_portId(0)
+ , m_gc(0)
+ , m_image(0)
+ , m_colorKey(24,0,24)
+{
+}
+
+QXVideoSurface::~QXVideoSurface()
+{
+ if (m_gc)
+ XFreeGC(QX11Info::display(), m_gc);
+
+ if (m_portId != 0)
+ XvUngrabPort(QX11Info::display(), m_portId, 0);
+}
+
+WId QXVideoSurface::winId() const
+{
+ return m_winId;
+}
+
+void QXVideoSurface::setWinId(WId id)
+{
+ if (id == m_winId)
+ return;
+
+#ifdef DEBUG_XV_SURFACE
+ qDebug() << "QXVideoSurface::setWinId" << id;
+#endif
+
+ if (m_image)
+ XFree(m_image);
+
+ if (m_gc) {
+ XFreeGC(QX11Info::display(), m_gc);
+ m_gc = 0;
+ }
+
+ if (m_portId != 0)
+ XvUngrabPort(QX11Info::display(), m_portId, 0);
+
+ QList<QVideoFrame::PixelFormat> prevFormats = m_supportedPixelFormats;
+ m_supportedPixelFormats.clear();
+ m_formatIds.clear();
+
+ m_winId = id;
+
+ if (m_winId && findPort()) {
+ querySupportedFormats();
+
+ m_gc = XCreateGC(QX11Info::display(), m_winId, 0, 0);
+
+ if (m_image) {
+ m_image = 0;
+
+ if (!start(surfaceFormat()))
+ QAbstractVideoSurface::stop();
+ }
+ } else if (m_image) {
+ m_image = 0;
+
+ QAbstractVideoSurface::stop();
+ }
+
+ if (m_supportedPixelFormats != prevFormats) {
+#ifdef DEBUG_XV_SURFACE
+ qDebug() << "QXVideoSurface: supportedFormatsChanged";
+#endif
+ emit supportedFormatsChanged();
+ }
+}
+
+QRect QXVideoSurface::displayRect() const
+{
+ return m_displayRect;
+}
+
+void QXVideoSurface::setDisplayRect(const QRect &rect)
+{
+ m_displayRect = rect;
+}
+
+QColor QXVideoSurface::colorKey() const
+{
+ return m_colorKey;
+}
+
+void QXVideoSurface::setColorKey(QColor key)
+{
+ m_colorKey = key;
+}
+
+int QXVideoSurface::getAttribute(const char *attribute) const
+{
+ if (m_portId != 0) {
+ Display *display = QX11Info::display();
+
+ Atom atom = XInternAtom(display, attribute, True);
+
+ int value = 0;
+
+ XvGetPortAttribute(display, m_portId, atom, &value);
+
+ return value;
+ } else {
+ return 0;
+ }
+}
+
+void QXVideoSurface::setAttribute(const char *attribute, int value)
+{
+ if (m_portId != 0) {
+ Display *display = QX11Info::display();
+
+ Atom atom = XInternAtom(display, attribute, True);
+
+ XvSetPortAttribute(display, m_portId, atom, value);
+ }
+}
+
+QList<QVideoFrame::PixelFormat> QXVideoSurface::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ if ( handleType == QAbstractVideoBuffer::NoHandle ||
+ handleType == QAbstractVideoBuffer::XvShmImageHandle )
+ return m_supportedPixelFormats;
+ else
+ return QList<QVideoFrame::PixelFormat>();
+}
+
+bool QXVideoSurface::start(const QVideoSurfaceFormat &format)
+{
+#ifdef DEBUG_XV_SURFACE
+ qDebug() << "QXVideoSurface::start" << format;
+#endif
+
+ m_lastFrame = QVideoFrame();
+
+ if (m_image)
+ XFree(m_image);
+
+ m_xvFormatId = 0;
+ for (int i = 0; i < m_supportedPixelFormats.count(); ++i) {
+ if (m_supportedPixelFormats.at(i) == format.pixelFormat()) {
+ m_xvFormatId = m_formatIds.at(i);
+ break;
+ }
+ }
+
+ if (m_xvFormatId == 0) {
+ setError(UnsupportedFormatError);
+ } else {
+ XvImage *image = XvShmCreateImage(
+ QX11Info::display(),
+ m_portId,
+ m_xvFormatId,
+ 0,
+ format.frameWidth(),
+ format.frameHeight(),
+ &m_shminfo
+ );
+
+ if (!image) {
+ setError(ResourceError);
+ return false;
+ }
+
+ m_shminfo.shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777);
+ m_shminfo.shmaddr = image->data = (char*)shmat(m_shminfo.shmid, 0, 0);
+ m_shminfo.readOnly = False;
+
+ if (!XShmAttach(QX11Info::display(), &m_shminfo)) {
+ qWarning() << "XShmAttach failed" << format;
+ return false;
+ }
+
+ if (!image) {
+ setError(ResourceError);
+ } else {
+ m_viewport = format.viewport();
+ m_image = image;
+
+ quint32 c = m_colorKey.rgb();
+ quint16 colorKey16 = ((c >> 3) & 0x001f)
+ | ((c >> 5) & 0x07e0)
+ | ((c >> 8) & 0xf800);
+
+ setAttribute("XV_AUTOPAINT_COLORKEY", 0);
+ setAttribute("XV_COLORKEY", colorKey16);
+ setAttribute("XV_OMAP_VSYNC", 1);
+ setAttribute("XV_DOUBLE_BUFFER", 0);
+
+ QVideoSurfaceFormat newFormat = format;
+ newFormat.setProperty("portId", QVariant(quint64(m_portId)));
+ newFormat.setProperty("xvFormatId", m_xvFormatId);
+ newFormat.setProperty("dataSize", image->data_size);
+
+ return QAbstractVideoSurface::start(newFormat);
+ }
+ }
+
+ if (m_image) {
+ m_image = 0;
+
+ QAbstractVideoSurface::stop();
+ }
+
+ return false;
+}
+
+void QXVideoSurface::stop()
+{
+ if (m_image) {
+ XFree(m_image);
+ m_image = 0;
+ m_lastFrame = QVideoFrame();
+
+ QAbstractVideoSurface::stop();
+ }
+}
+
+bool QXVideoSurface::present(const QVideoFrame &frame)
+{
+ if (!m_image) {
+ setError(StoppedError);
+ return false;
+ } else if (m_image->width != frame.width() || m_image->height != frame.height()) {
+ setError(IncorrectFormatError);
+ return false;
+ } else {
+ m_lastFrame = frame;
+
+ if (!m_lastFrame.map(QAbstractVideoBuffer::ReadOnly)) {
+ qWarning() << "Failed to map video frame";
+ setError(IncorrectFormatError);
+ return false;
+ } else {
+ bool presented = false;
+
+ if (frame.handleType() != QAbstractVideoBuffer::XvShmImageHandle &&
+ m_image->data_size > m_lastFrame.mappedBytes()) {
+ qWarning("Insufficient frame buffer size");
+ setError(IncorrectFormatError);
+ } else if (frame.handleType() != QAbstractVideoBuffer::XvShmImageHandle &&
+ m_image->num_planes > 0 &&
+ m_image->pitches[0] != m_lastFrame.bytesPerLine()) {
+ qWarning("Incompatible frame pitches");
+ setError(IncorrectFormatError);
+ } else {
+ XvImage *img = 0;
+
+ if (frame.handleType() == QAbstractVideoBuffer::XvShmImageHandle) {
+ img = frame.handle().value<XvImage*>();
+ } else {
+ img = m_image;
+ memcpy(m_image->data, m_lastFrame.bits(), qMin(m_lastFrame.mappedBytes(), m_image->data_size));
+ }
+
+ if (img)
+ XvShmPutImage(
+ QX11Info::display(),
+ m_portId,
+ m_winId,
+ m_gc,
+ img,
+ m_viewport.x(),
+ m_viewport.y(),
+ m_viewport.width(),
+ m_viewport.height(),
+ m_displayRect.x(),
+ m_displayRect.y(),
+ m_displayRect.width(),
+ m_displayRect.height(),
+ false);
+
+ presented = true;
+ }
+
+ m_lastFrame.unmap();
+
+ return presented;
+ }
+ }
+}
+
+void QXVideoSurface::repaintLastFrame()
+{
+ if (m_lastFrame.isValid())
+ present(QVideoFrame(m_lastFrame));
+}
+
+bool QXVideoSurface::findPort()
+{
+ unsigned int count = 0;
+ XvAdaptorInfo *adaptors = 0;
+ bool portFound = false;
+
+ if (XvQueryAdaptors(QX11Info::display(), m_winId, &count, &adaptors) == Success) {
+ for (unsigned int i = 0; i < count && !portFound; ++i) {
+ if (adaptors[i].type & XvImageMask) {
+ m_portId = adaptors[i].base_id;
+
+ for (unsigned int j = 0; j < adaptors[i].num_ports && !portFound; ++j, ++m_portId)
+ portFound = XvGrabPort(QX11Info::display(), m_portId, 0) == Success;
+ }
+ }
+ XvFreeAdaptorInfo(adaptors);
+ }
+
+ if (!portFound)
+ qWarning() << "QXVideoSurface::findPort: failed to find XVideo port";
+
+ return portFound;
+}
+
+void QXVideoSurface::querySupportedFormats()
+{
+ int count = 0;
+ if (XvImageFormatValues *imageFormats = XvListImageFormats(
+ QX11Info::display(), m_portId, &count)) {
+ const int rgbCount = sizeof(qt_xvRgbLookup) / sizeof(XvFormatRgb);
+ const int yuvCount = sizeof(qt_xvYuvLookup) / sizeof(XvFormatYuv);
+
+ for (int i = 0; i < count; ++i) {
+ switch (imageFormats[i].type) {
+ case XvRGB:
+ for (int j = 0; j < rgbCount; ++j) {
+ if (imageFormats[i] == qt_xvRgbLookup[j]) {
+ m_supportedPixelFormats.append(qt_xvRgbLookup[j].pixelFormat);
+ m_formatIds.append(imageFormats[i].id);
+ break;
+ }
+ }
+ break;
+ case XvYUV:
+ for (int j = 0; j < yuvCount; ++j) {
+ //skip YUV420P and YV12 formats, they don't work correctly and slow,
+ //YUV2 == YUYV is just slow
+ if (imageFormats[i] == qt_xvYuvLookup[j] &&
+ qt_xvYuvLookup[j].pixelFormat != QVideoFrame::Format_YUV420P &&
+ qt_xvYuvLookup[j].pixelFormat != QVideoFrame::Format_YV12) {
+ m_supportedPixelFormats.append(qt_xvYuvLookup[j].pixelFormat);
+ m_formatIds.append(imageFormats[i].id);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ XFree(imageFormats);
+ }
+
+#ifdef DEBUG_XV_SURFACE
+ qDebug() << "Supported pixel formats:" << m_supportedPixelFormats;
+#endif
+
+}
diff --git a/src/multimediakit/qxvideosurface_maemo5_p.h b/src/multimediakit/qxvideosurface_maemo5_p.h
new file mode 100644
index 000000000..351cf8805
--- /dev/null
+++ b/src/multimediakit/qxvideosurface_maemo5_p.h
@@ -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 QXVIDEOSURFACE_MAEMO5_H
+#define QXVIDEOSURFACE_MAEMO5_H
+
+#include <QtCore/qhash.h>
+#include <QtGui/qwidget.h>
+#include <qabstractvideosurface.h>
+
+#include <X11/Xlib.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/extensions/XShm.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+
+QT_USE_NAMESPACE
+
+class QXVideoSurface : public QAbstractVideoSurface
+{
+ Q_OBJECT
+public:
+ QXVideoSurface(QObject *parent = 0);
+ ~QXVideoSurface();
+
+ WId winId() const;
+ void setWinId(WId id);
+
+ QRect displayRect() const;
+ void setDisplayRect(const QRect &rect);
+
+ QColor colorKey() const;
+ void setColorKey(QColor key);
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
+
+ QVideoFrame lastFrame() const { return m_lastFrame; }
+
+public slots:
+ bool start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ bool present(const QVideoFrame &frame);
+ void repaintLastFrame();
+
+private:
+ WId m_winId;
+ XvPortID m_portId;
+ int m_xvFormatId;
+ GC m_gc;
+ XvImage *m_image;
+ XShmSegmentInfo m_shminfo;
+ QList<QVideoFrame::PixelFormat> m_supportedPixelFormats;
+ QVector<int> m_formatIds;
+ QRect m_viewport;
+ QRect m_displayRect;
+ QColor m_colorKey;
+
+ QVideoFrame m_lastFrame;
+
+ bool findPort();
+ void querySupportedFormats();
+
+ int getAttribute(const char *attribute) const;
+ void setAttribute(const char *attribute, int value);
+};
+
+Q_DECLARE_METATYPE(XvImage*)
+
+#endif
diff --git a/src/multimediakit/video/qabstractvideobuffer.cpp b/src/multimediakit/video/qabstractvideobuffer.cpp
new file mode 100644
index 000000000..2ed2ddad5
--- /dev/null
+++ b/src/multimediakit/video/qabstractvideobuffer.cpp
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** 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 "qabstractvideobuffer_p.h"
+
+#include <qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractVideoBuffer
+ \brief The QAbstractVideoBuffer class is an abstraction for video data.
+ \since 1.0
+ \inmodule QtMultimediaKit
+
+ The QVideoFrame class makes use of a QAbstractVideoBuffer internally to reference a buffer of
+ video data. Creating a subclass of QAbstractVideoBuffer will allow you to construct video
+ frames from preallocated or static buffers.
+
+ XXX where do these come from?
+
+ The contents of a buffer can be accessed by mapping the buffer to memory using the map()
+ function which returns a pointer to memory containing the contents of the the video buffer.
+ The memory returned by map() is released by calling the unmap() function.
+
+ The handle() of a buffer may also be used to manipulate its contents using type specific APIs.
+ The type of a buffer's handle is given by the handleType() function.
+
+ XXX example of handle stuff (opengl etc)
+
+ \sa QVideoFrame
+*/
+
+/*!
+ \enum QAbstractVideoBuffer::HandleType
+
+ Identifies the type of a video buffers handle.
+
+ \value NoHandle The buffer has no handle, its data can only be accessed by mapping the buffer.
+ \value GLTextureHandle The handle of the buffer is an OpenGL texture ID.
+ \value XvShmImageHandle The handle contains pointer to shared memory XVideo image.
+ \value CoreImageHandle The handle contains pointer to Mac OS X CIImage.
+ \value QPixmapHandle The handle of the buffer is a QPixmap.
+ \value UserHandle Start value for user defined handle types.
+
+ \sa handleType()
+*/
+
+/*!
+ \enum QAbstractVideoBuffer::MapMode
+
+ Enumerates how a video buffer's data is mapped to memory.
+
+ \value NotMapped The video buffer has is not mapped to memory.
+ \value ReadOnly The mapped memory is populated with data from the video buffer when mapped, but
+ the content of the mapped memory may be discarded when unmapped.
+ \value WriteOnly The mapped memory is uninitialized when mapped, and the content will be used to
+ populate the video buffer when unmapped.
+ \value ReadWrite The mapped memory is populated with data from the video buffer, and the
+ video buffer is repopulated with the content of the mapped memory.
+
+ \sa mapMode(), map()
+*/
+
+/*!
+ Constructs an abstract video buffer of the given \a type.
+*/
+QAbstractVideoBuffer::QAbstractVideoBuffer(HandleType type)
+ : d_ptr(new QAbstractVideoBufferPrivate)
+{
+ Q_D(QAbstractVideoBuffer);
+
+ d->handleType = type;
+}
+
+/*!
+ \internal
+*/
+QAbstractVideoBuffer::QAbstractVideoBuffer(QAbstractVideoBufferPrivate &dd, HandleType type)
+ : d_ptr(&dd)
+{
+ Q_D(QAbstractVideoBuffer);
+
+ d->handleType = type;
+}
+
+/*!
+ Destroys an abstract video buffer.
+*/
+QAbstractVideoBuffer::~QAbstractVideoBuffer()
+{
+ delete d_ptr;
+}
+
+/*!
+ Returns the type of a video buffer's handle.
+
+ \since 1.0
+ \sa handle()
+*/
+QAbstractVideoBuffer::HandleType QAbstractVideoBuffer::handleType() const
+{
+ return d_func()->handleType;
+}
+
+/*!
+ \fn QAbstractVideoBuffer::mapMode() const
+
+ Returns the mode a video buffer is mapped in.
+
+ \since 1.0
+ \sa map()
+*/
+
+/*!
+ \fn QAbstractVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
+
+ Maps the contents of a video buffer to memory.
+
+ The map \a mode indicates whether the contents of the mapped memory should be read from and/or
+ written to the buffer. If the map mode includes the QAbstractVideoBuffer::ReadOnly flag the
+ mapped memory will be populated with the content of the video buffer when mapped. If the map
+ mode includes the QAbstractVideoBuffer::WriteOnly flag the content of the mapped memory will be
+ persisted in the buffer when unmapped.
+
+ When access to the data is no longer needed be sure to call the unmap() function to release the
+ mapped memory.
+
+ Returns a pointer to the mapped memory region, or a null pointer if the mapping failed. The
+ size in bytes of the mapped memory region is returned in \a numBytes, and the line stride in \a
+ bytesPerLine.
+
+ When access to the data is no longer needed be sure to unmap() the buffer.
+
+ \note Writing to memory that is mapped as read-only is undefined, and may result in changes
+ to shared data.
+
+ \since 1.0
+ \sa unmap(), mapMode()
+*/
+
+/*!
+ \fn QAbstractVideoBuffer::unmap()
+
+ Releases the memory mapped by the map() function
+
+ If the \l {QAbstractVideoBuffer::MapMode}{MapMode} included the QAbstractVideoBuffer::WriteOnly
+ flag this will persist the current content of the mapped memory to the video frame.
+
+ \since 1.0
+ \sa map()
+*/
+
+/*!
+ Returns a type specific handle to the data buffer.
+
+ The type of the handle is given by handleType() function.
+
+ XXX put a table here too
+
+ \since 1.0
+ \sa handleType()
+*/
+QVariant QAbstractVideoBuffer::handle() const
+{
+ return QVariant();
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/multimediakit/video/qabstractvideobuffer.h b/src/multimediakit/video/qabstractvideobuffer.h
new file mode 100644
index 000000000..44f4247e7
--- /dev/null
+++ b/src/multimediakit/video/qabstractvideobuffer.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QABSTRACTVIDEOBUFFER_H
+#define QABSTRACTVIDEOBUFFER_H
+
+#include <qmobilityglobal.h>
+#include <qtmedianamespace.h>
+
+
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QVariant;
+
+class QAbstractVideoBufferPrivate;
+
+class Q_MULTIMEDIA_EXPORT QAbstractVideoBuffer
+{
+public:
+ enum HandleType
+ {
+ NoHandle,
+ GLTextureHandle,
+ XvShmImageHandle,
+ CoreImageHandle,
+ QPixmapHandle,
+ UserHandle = 1000
+ };
+
+ enum MapMode
+ {
+ NotMapped = 0x00,
+ ReadOnly = 0x01,
+ WriteOnly = 0x02,
+ ReadWrite = ReadOnly | WriteOnly
+ };
+
+ QAbstractVideoBuffer(HandleType type);
+ virtual ~QAbstractVideoBuffer();
+
+ HandleType handleType() const;
+
+ virtual MapMode mapMode() const = 0;
+
+ virtual uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) = 0;
+ virtual void unmap() = 0;
+
+ virtual QVariant handle() const;
+
+protected:
+ QAbstractVideoBuffer(QAbstractVideoBufferPrivate &dd, HandleType type);
+
+ QAbstractVideoBufferPrivate *d_ptr;
+
+private:
+ Q_DECLARE_PRIVATE(QAbstractVideoBuffer)
+ Q_DISABLE_COPY(QAbstractVideoBuffer)
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QAbstractVideoBuffer::HandleType)
+Q_DECLARE_METATYPE(QAbstractVideoBuffer::MapMode)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/multimediakit/video/qabstractvideobuffer_p.h b/src/multimediakit/video/qabstractvideobuffer_p.h
new file mode 100644
index 000000000..acfa1ee74
--- /dev/null
+++ b/src/multimediakit/video/qabstractvideobuffer_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QABSTRACTVIDEOBUFFER_P_H
+#define QABSTRACTVIDEOBUFFER_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/qshareddata.h>
+#include "qabstractvideobuffer.h"
+
+#include <qmobilityglobal.h>
+#include <qtmedianamespace.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractVideoBufferPrivate
+{
+public:
+ QAbstractVideoBufferPrivate()
+ : handleType(QAbstractVideoBuffer::NoHandle)
+ {}
+
+ virtual ~QAbstractVideoBufferPrivate()
+ {}
+
+ QAbstractVideoBuffer::HandleType handleType;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/video/qabstractvideosurface.cpp b/src/multimediakit/video/qabstractvideosurface.cpp
new file mode 100644
index 000000000..59c55c242
--- /dev/null
+++ b/src/multimediakit/video/qabstractvideosurface.cpp
@@ -0,0 +1,344 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include "qabstractvideosurface.h"
+
+#include "qvideosurfaceformat.h"
+
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_METATYPE(QVideoSurfaceFormat)
+Q_DECLARE_METATYPE(QAbstractVideoSurface::Error)
+
+/*!
+ \class QAbstractVideoSurface
+ \brief The QAbstractVideoSurface class is a base class for video presentation surfaces.
+ \since 1.0
+ \inmodule QtMultimediaKit
+
+ A video surface presents a continuous stream of identically formatted frames, where the format
+ of each frame is compatible with a stream format supplied when starting a presentation.
+
+ XXX Why do I carE?
+
+ The QAbstractVideoSurface class defines the standard interface that video producers use to
+ inter-operate with video presentation surfaces. It is not supposed to be instantiated directly.
+ Instead, you should subclass it to create new video surfaces.
+
+ A list of pixel formats a surface can present is given by the supportedPixelFormats() function,
+ and the isFormatSupported() function will test if a video surface format is supported. If a
+ format is not supported the nearestFormat() function may be able to suggest a similar format.
+ For example, if a surface supports fixed set of resolutions it may suggest the smallest
+ supported resolution that contains the proposed resolution.
+
+ The start() function takes a supported format and enables a video surface. Once started a
+ surface will begin displaying the frames it receives in the present() function. Surfaces may
+ hold a reference to the buffer of a presented video frame until a new frame is presented or
+ streaming is stopped. The stop() function will disable a surface and a release any video
+ buffers it holds references to.
+
+ XXX Example?
+*/
+
+/*!
+ \enum QAbstractVideoSurface::Error
+ This enum describes the errors that may be returned by the error() function.
+
+ \value NoError No error occurred.
+ \value UnsupportedFormatError A video format was not supported.
+ \value IncorrectFormatError A video frame was not compatible with the format of the surface.
+ \value StoppedError The surface has not been started.
+ \value ResourceError The surface could not allocate some resource.
+*/
+
+/*!
+ Constructs a video surface with the given \a parent.
+*/
+QAbstractVideoSurface::QAbstractVideoSurface(QObject *parent)
+ : QObject(parent)
+{
+ setProperty("_q_surfaceFormat", QVariant::fromValue(QVideoSurfaceFormat()));
+ setProperty("_q_active", false);
+ setProperty("_q_error", QVariant::fromValue(QAbstractVideoSurface::NoError));
+ setProperty("_q_nativeResolution", QSize());
+}
+
+// XXX Qt5
+/*!
+ \internal
+
+ This is deprecated.
+
+ Since we need to build without access to Qt's private headers we can't reliably inherit
+ from QObjectPrivate. Binary compatibility means we can't remove this constructor or
+ add a d pointer to QAbstractVideoSurface.
+*/
+QAbstractVideoSurface::QAbstractVideoSurface(QAbstractVideoSurfacePrivate &, QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys a video surface.
+*/
+QAbstractVideoSurface::~QAbstractVideoSurface()
+{
+}
+
+/*!
+ \fn QAbstractVideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const
+
+ Returns a list of pixel formats a video surface can present for a given handle \a type.
+
+ The pixel formats returned for the QAbstractVideoBuffer::NoHandle type are valid for any buffer
+ that can be mapped in read-only mode.
+
+ Types that are first in the list can be assumed to be faster to render.
+ \since 1.0
+*/
+
+/*!
+ Tests a video surface \a format to determine if a surface can accept it.
+
+ Returns true if the format is supported by the surface, and false otherwise.
+ \since 1.0
+*/
+bool QAbstractVideoSurface::isFormatSupported(const QVideoSurfaceFormat &format) const
+{
+ return supportedPixelFormats(format.handleType()).contains(format.pixelFormat());
+}
+
+/*!
+ Returns a supported video surface format that is similar to \a format.
+
+ A similar surface format is one that has the same \l {QVideoSurfaceFormat::pixelFormat()}{pixel
+ format} and \l {QVideoSurfaceFormat::handleType()}{handle type} but may differ in some of the other
+ properties. For example, if there are restrictions on the \l {QVideoSurfaceFormat::frameSize()}
+ {frame sizes} a video surface can accept it may suggest a format with a larger frame size and
+ a \l {QVideoSurfaceFormat::viewport()}{viewport} the size of the original frame size.
+
+ If the format is already supported it will be returned unchanged, or if there is no similar
+ supported format an invalid format will be returned.
+ \since 1.0
+*/
+QVideoSurfaceFormat QAbstractVideoSurface::nearestFormat(const QVideoSurfaceFormat &format) const
+{
+ return isFormatSupported(format)
+ ? format
+ : QVideoSurfaceFormat();
+}
+
+/*!
+ \fn QAbstractVideoSurface::supportedFormatsChanged()
+
+ Signals that the set of formats supported by a video surface has changed.
+
+ \since 1.0
+ \sa supportedPixelFormats(), isFormatSupported()
+*/
+
+/*!
+ Returns the format of a video surface.
+ \since 1.0
+*/
+QVideoSurfaceFormat QAbstractVideoSurface::surfaceFormat() const
+{
+ return property("_q_format").value<QVideoSurfaceFormat>();
+}
+
+/*!
+ \fn QAbstractVideoSurface::surfaceFormatChanged(const QVideoSurfaceFormat &format)
+
+ Signals that the configured \a format of a video surface has changed.
+
+ \since 1.0
+ \sa surfaceFormat(), start()
+*/
+
+/*!
+ Starts a video surface presenting \a format frames.
+
+ Returns true if the surface was started, and false if an error occurred.
+
+ \since 1.0
+ \sa isActive(), stop()
+*/
+bool QAbstractVideoSurface::start(const QVideoSurfaceFormat &format)
+{
+ bool wasActive = property("_q_active").toBool();
+
+ setProperty("_q_active", true);
+ setProperty("_q_format", QVariant::fromValue(format));
+ setProperty("_q_error", QVariant::fromValue(NoError));
+
+ emit surfaceFormatChanged(format);
+
+ if (!wasActive)
+ emit activeChanged(true);
+
+ return true;
+}
+
+/*!
+ Stops a video surface presenting frames and releases any resources acquired in start().
+
+ \since 1.0
+ \sa isActive(), start()
+*/
+void QAbstractVideoSurface::stop()
+{
+ if (property("_q_active").toBool()) {
+ setProperty("_q_format", QVariant::fromValue(QVideoSurfaceFormat()));
+ setProperty("_q_active", false);
+
+ emit activeChanged(false);
+ emit surfaceFormatChanged(surfaceFormat());
+ }
+}
+
+/*!
+ Indicates whether a video surface has been started.
+
+ Returns true if the surface has been started, and false otherwise.
+ \since 1.0
+*/
+bool QAbstractVideoSurface::isActive() const
+{
+ return property("_q_active").toBool();
+}
+
+/*!
+ \fn QAbstractVideoSurface::activeChanged(bool active)
+
+ Signals that the \a active state of a video surface has changed.
+
+ \since 1.0
+ \sa isActive(), start(), stop()
+*/
+
+/*!
+ \fn QAbstractVideoSurface::present(const QVideoFrame &frame)
+
+ Presents a video \a frame.
+
+ Returns true if the frame was presented, and false if an error occurred.
+
+ Not all surfaces will block until the presentation of a frame has completed. Calling present()
+ on a non-blocking surface may fail if called before the presentation of a previous frame has
+ completed. In such cases the surface may not return to a ready state until it has had an
+ opportunity to process events.
+
+ If present() fails for any other reason the surface will immediately enter the stopped state
+ and an error() value will be set.
+
+ A video surface must be in the started state for present() to succeed, and the format of the
+ video frame must be compatible with the current video surface format.
+
+ \since 1.0
+ \sa error()
+*/
+
+/*!
+ Returns the last error that occurred.
+
+ If a surface fails to start(), or stops unexpectedly this function can be called to discover
+ what error occurred.
+ \since 1.0
+*/
+
+QAbstractVideoSurface::Error QAbstractVideoSurface::error() const
+{
+ return property("_q_error").value<QAbstractVideoSurface::Error>();
+}
+
+/*!
+ Sets the value of error() to \a error.
+ \since 1.0
+*/
+void QAbstractVideoSurface::setError(Error error)
+{
+ setProperty("_q_error", QVariant::fromValue(error));
+}
+
+/*!
+ \property QAbstractVideoSurface::nativeResolution
+
+ The native resolution of video surface.
+ This is the resolution of video frames the surface
+ can render with optimal quality and/or performance.
+
+ The native resolution is not always known and can be changed during playback.
+ \since 1.1
+ */
+QSize QAbstractVideoSurface::nativeResolution() const
+{
+ return property("_q_nativeResolution").toSize();
+}
+
+/*!
+ Set the video surface native \a resolution.
+ \since 1.1
+ */
+void QAbstractVideoSurface::setNativeResolution(const QSize &resolution)
+{
+ const QSize nativeResolution = property("_q_nativeResolution").toSize();
+
+ if (nativeResolution != resolution) {
+ setProperty("_q_nativeResolution", resolution);
+
+ emit nativeResolutionChanged(resolution);
+ }
+}
+/*!
+ \fn QAbstractVideoSurface::nativeResolutionChanged(const QSize &resolution);
+
+ Signals the native \a resolution of video surface has changed.
+ \since 1.1
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qabstractvideosurface.cpp"
+
diff --git a/src/multimediakit/video/qabstractvideosurface.h b/src/multimediakit/video/qabstractvideosurface.h
new file mode 100644
index 000000000..a23b31698
--- /dev/null
+++ b/src/multimediakit/video/qabstractvideosurface.h
@@ -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$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTVIDEOSURFACE_H
+#define QABSTRACTVIDEOSURFACE_H
+
+#include <QtCore/qobject.h>
+#include <qvideoframe.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QRectF;
+class QVideoSurfaceFormat;
+
+class QAbstractVideoSurfacePrivate;
+
+class Q_MULTIMEDIA_EXPORT QAbstractVideoSurface : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QSize nativeResolution READ nativeResolution NOTIFY nativeResolutionChanged)
+public:
+ enum Error
+ {
+ NoError,
+ UnsupportedFormatError,
+ IncorrectFormatError,
+ StoppedError,
+ ResourceError
+ };
+
+ explicit QAbstractVideoSurface(QObject *parent = 0);
+ ~QAbstractVideoSurface();
+
+ virtual QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const = 0;
+ virtual bool isFormatSupported(const QVideoSurfaceFormat &format) const;
+ virtual QVideoSurfaceFormat nearestFormat(const QVideoSurfaceFormat &format) const;
+
+ QVideoSurfaceFormat surfaceFormat() const;
+
+ QSize nativeResolution() const;
+
+ virtual bool start(const QVideoSurfaceFormat &format);
+ virtual void stop();
+
+ bool isActive() const;
+
+ virtual bool present(const QVideoFrame &frame) = 0;
+
+ Error error() const;
+
+Q_SIGNALS:
+ void activeChanged(bool active);
+ void surfaceFormatChanged(const QVideoSurfaceFormat &format);
+ void supportedFormatsChanged();
+ void nativeResolutionChanged(const QSize &);
+
+protected:
+ QAbstractVideoSurface(QAbstractVideoSurfacePrivate &dd, QObject *parent);
+
+ void setError(Error error);
+ void setNativeResolution(const QSize &resolution);
+
+private:
+ Q_DECLARE_PRIVATE(QAbstractVideoSurface)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/multimediakit/video/qimagevideobuffer.cpp b/src/multimediakit/video/qimagevideobuffer.cpp
new file mode 100644
index 000000000..0c932ff90
--- /dev/null
+++ b/src/multimediakit/video/qimagevideobuffer.cpp
@@ -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$
+**
+****************************************************************************/
+
+#include "qimagevideobuffer_p.h"
+
+#include "qabstractvideobuffer_p.h"
+
+#include <qimage.h>
+#include <qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+class QImageVideoBufferPrivate : public QAbstractVideoBufferPrivate
+{
+public:
+ QImageVideoBufferPrivate()
+ : mapMode(QAbstractVideoBuffer::NotMapped)
+ {
+ }
+
+ QAbstractVideoBuffer::MapMode mapMode;
+ QImage image;
+};
+
+QImageVideoBuffer::QImageVideoBuffer(const QImage &image)
+ : QAbstractVideoBuffer(*new QImageVideoBufferPrivate, NoHandle)
+{
+ Q_D(QImageVideoBuffer);
+
+ d->image = image;
+}
+
+QImageVideoBuffer::~QImageVideoBuffer()
+{
+}
+
+QAbstractVideoBuffer::MapMode QImageVideoBuffer::mapMode() const
+{
+ return d_func()->mapMode;
+}
+
+uchar *QImageVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
+{
+ Q_D(QImageVideoBuffer);
+
+ if (d->mapMode == NotMapped && d->image.bits() && mode != NotMapped) {
+ d->mapMode = mode;
+
+ if (numBytes)
+ *numBytes = d->image.byteCount();
+
+ if (bytesPerLine)
+ *bytesPerLine = d->image.bytesPerLine();
+
+ return d->image.bits();
+ } else {
+ return 0;
+ }
+}
+
+void QImageVideoBuffer::unmap()
+{
+ Q_D(QImageVideoBuffer);
+
+ d->mapMode = NotMapped;
+}
+
+QT_END_NAMESPACE
diff --git a/src/multimediakit/video/qimagevideobuffer_p.h b/src/multimediakit/video/qimagevideobuffer_p.h
new file mode 100644
index 000000000..993ec57b4
--- /dev/null
+++ b/src/multimediakit/video/qimagevideobuffer_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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 QIMAGEVIDEOBUFFER_P_H
+#define QIMAGEVIDEOBUFFER_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 <qabstractvideobuffer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QImage;
+
+class QImageVideoBufferPrivate;
+
+class Q_MULTIMEDIA_EXPORT QImageVideoBuffer : public QAbstractVideoBuffer
+{
+ Q_DECLARE_PRIVATE(QImageVideoBuffer)
+public:
+ QImageVideoBuffer(const QImage &image);
+ ~QImageVideoBuffer();
+
+ MapMode mapMode() const;
+
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine);
+ void unmap();
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/multimediakit/video/qmemoryvideobuffer.cpp b/src/multimediakit/video/qmemoryvideobuffer.cpp
new file mode 100644
index 000000000..92d16a264
--- /dev/null
+++ b/src/multimediakit/video/qmemoryvideobuffer.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** 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 "qmemoryvideobuffer_p.h"
+
+#include "qabstractvideobuffer_p.h"
+#include <qbytearray.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMemoryVideoBufferPrivate : public QAbstractVideoBufferPrivate
+{
+public:
+ QMemoryVideoBufferPrivate()
+ : bytesPerLine(0)
+ , mapMode(QAbstractVideoBuffer::NotMapped)
+ {
+ }
+
+ int bytesPerLine;
+ QAbstractVideoBuffer::MapMode mapMode;
+ QByteArray data;
+};
+
+/*!
+ \class QMemoryVideoBuffer
+ \brief The QMemoryVideoBuffer class provides a system memory allocated video data buffer.
+ \internal
+ \since QtMobility 1.0
+
+ QMemoryVideoBuffer is the default video buffer for allocating system memory. It may be used to
+ allocate memory for a QVideoFrame without implementing your own QAbstractVideoBuffer.
+*/
+
+/*!
+ Constructs a video buffer with an image stride of \a bytesPerLine from a byte \a array.
+*/
+QMemoryVideoBuffer::QMemoryVideoBuffer(const QByteArray &array, int bytesPerLine)
+ : QAbstractVideoBuffer(*new QMemoryVideoBufferPrivate, NoHandle)
+{
+ Q_D(QMemoryVideoBuffer);
+
+ d->data = array;
+ d->bytesPerLine = bytesPerLine;
+}
+
+/*!
+ Destroys a system memory allocated video buffer.
+*/
+QMemoryVideoBuffer::~QMemoryVideoBuffer()
+{
+}
+
+/*!
+ \reimp
+ \since 1.1
+*/
+QAbstractVideoBuffer::MapMode QMemoryVideoBuffer::mapMode() const
+{
+ return d_func()->mapMode;
+}
+
+/*!
+ \reimp
+ \since 1.1
+*/
+uchar *QMemoryVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
+{
+ Q_D(QMemoryVideoBuffer);
+
+ if (d->mapMode == NotMapped && d->data.data() && mode != NotMapped) {
+ d->mapMode = mode;
+
+ if (numBytes)
+ *numBytes = d->data.size();
+
+ if (bytesPerLine)
+ *bytesPerLine = d->bytesPerLine;
+
+ return reinterpret_cast<uchar *>(d->data.data());
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ \reimp
+ \since 1.1
+*/
+void QMemoryVideoBuffer::unmap()
+{
+ d_func()->mapMode = NotMapped;
+}
+
+QT_END_NAMESPACE
diff --git a/src/multimediakit/video/qmemoryvideobuffer_p.h b/src/multimediakit/video/qmemoryvideobuffer_p.h
new file mode 100644
index 000000000..1889df0e2
--- /dev/null
+++ b/src/multimediakit/video/qmemoryvideobuffer_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 QMEMORYVIDEOBUFFER_P_H
+#define QMEMORYVIDEOBUFFER_P_H
+
+#include <qabstractvideobuffer.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.
+//
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QMemoryVideoBufferPrivate;
+
+class Q_MULTIMEDIA_EXPORT QMemoryVideoBuffer : public QAbstractVideoBuffer
+{
+ Q_DECLARE_PRIVATE(QMemoryVideoBuffer)
+public:
+ QMemoryVideoBuffer(const QByteArray &data, int bytesPerLine);
+ ~QMemoryVideoBuffer();
+
+ MapMode mapMode() const;
+
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine);
+ void unmap();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/multimediakit/video/qvideoframe.cpp b/src/multimediakit/video/qvideoframe.cpp
new file mode 100644
index 000000000..f974e3294
--- /dev/null
+++ b/src/multimediakit/video/qvideoframe.cpp
@@ -0,0 +1,793 @@
+/****************************************************************************
+**
+** 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 "qvideoframe.h"
+
+#include "qimagevideobuffer_p.h"
+#include "qmemoryvideobuffer_p.h"
+
+#include <qimage.h>
+#include <qpair.h>
+#include <qsize.h>
+#include <qvariant.h>
+#include <qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace
+{
+class QVideoFramePrivateRegisterMetaTypes
+{
+public:
+ QVideoFramePrivateRegisterMetaTypes()
+ {
+ qRegisterMetaType<QVideoFrame::PixelFormat>("QVideoFrame::PixelFormat");
+ }
+} _registerMetaTypes;
+}
+
+
+class QVideoFramePrivate : public QSharedData
+{
+public:
+ QVideoFramePrivate()
+ : startTime(-1)
+ , endTime(-1)
+ , data(0)
+ , mappedBytes(0)
+ , bytesPerLine(0)
+ , pixelFormat(QVideoFrame::Format_Invalid)
+ , fieldType(QVideoFrame::ProgressiveFrame)
+ , buffer(0)
+ {
+ }
+
+ QVideoFramePrivate(const QSize &size, QVideoFrame::PixelFormat format)
+ : size(size)
+ , startTime(-1)
+ , endTime(-1)
+ , data(0)
+ , mappedBytes(0)
+ , bytesPerLine(0)
+ , pixelFormat(format)
+ , fieldType(QVideoFrame::ProgressiveFrame)
+ , buffer(0)
+ {
+ }
+
+ ~QVideoFramePrivate()
+ {
+ delete buffer;
+ }
+
+ QSize size;
+ qint64 startTime;
+ qint64 endTime;
+ uchar *data;
+ int mappedBytes;
+ int bytesPerLine;
+ QVideoFrame::PixelFormat pixelFormat;
+ QVideoFrame::FieldType fieldType;
+ QAbstractVideoBuffer *buffer;
+
+private:
+ Q_DISABLE_COPY(QVideoFramePrivate)
+};
+
+/*!
+ \class QVideoFrame
+ \brief The QVideoFrame class provides a representation of a frame of video data.
+ \since 1.0
+ \inmodule QtMultimediaKit
+
+ A QVideoFrame encapsulates the data of a video frame, and information about the frame.
+
+ XXX why do I care
+
+ The contents of a video frame can be mapped to memory using the map() function. While
+ mapped, the video data can accessed using the bits() function, which returns a pointer to a
+ buffer. The total size of this buffer is given by the mappedBytes() function, and the size of each line is given
+ by bytesPerLine(). The return value of the handle() function may be used to access frame data
+ using the internal buffer's native APIs.
+
+ The video data in a QVideoFrame is encapsulated in a QAbstractVideoBuffer. A QVideoFrame
+ may be constructed from any buffer type by subclassing the QAbstractVideoBuffer class.
+
+ \note QVideoFrame is explicitly shared, any change made to video frame will also apply to any
+ copies.
+
+ XXX example
+*/
+
+/*!
+ \enum QVideoFrame::PixelFormat
+
+ Enumerates video data types.
+
+ \value Format_Invalid
+ The frame is invalid.
+
+ \value Format_ARGB32
+ The frame is stored using a 32-bit ARGB format (0xAARRGGBB). This is equivalent to
+ QImage::Format_ARGB32.
+
+ \value Format_ARGB32_Premultiplied
+ The frame stored using a premultiplied 32-bit ARGB format (0xAARRGGBB). This is equivalent
+ to QImage::Format_ARGB32_Premultiplied.
+
+ \value Format_RGB32
+ The frame stored using a 32-bit RGB format (0xffRRGGBB). This is equivalent to
+ QImage::Format_RGB32
+
+ \value Format_RGB24
+ The frame is stored using a 24-bit RGB format (8-8-8). This is equivalent to
+ QImage::Format_RGB888
+
+ \value Format_RGB565
+ The frame is stored using a 16-bit RGB format (5-6-5). This is equivalent to
+ QImage::Format_RGB16.
+
+ \value Format_RGB555
+ The frame is stored using a 16-bit RGB format (5-5-5). This is equivalent to
+ QImage::Format_RGB555.
+
+ \value Format_ARGB8565_Premultiplied
+ The frame is stored using a 24-bit premultiplied ARGB format (8-6-6-5).
+
+ \value Format_BGRA32
+ The frame is stored using a 32-bit ARGB format (0xBBGGRRAA).
+
+ \value Format_BGRA32_Premultiplied
+ The frame is stored using a premultiplied 32bit BGRA format.
+
+ \value Format_BGR32
+ The frame is stored using a 32-bit BGR format (0xBBGGRRff).
+
+ \value Format_BGR24
+ The frame is stored using a 24-bit BGR format (0xBBGGRR).
+
+ \value Format_BGR565
+ The frame is stored using a 16-bit BGR format (5-6-5).
+
+ \value Format_BGR555
+ The frame is stored using a 16-bit BGR format (5-5-5).
+
+ \value Format_BGRA5658_Premultiplied
+ The frame is stored using a 24-bit premultiplied BGRA format (5-6-5-8).
+
+ \value Format_AYUV444
+ The frame is stored using a packed 32-bit AYUV format (0xAAYYUUVV).
+
+ \value Format_AYUV444_Premultiplied
+ The frame is stored using a packed premultiplied 32-bit AYUV format (0xAAYYUUVV).
+
+ \value Format_YUV444
+ The frame is stored using a 24-bit packed YUV format (8-8-8).
+
+ \value Format_YUV420P
+ The frame is stored using an 8-bit per component planar YUV format with the U and V planes
+ horizontally and vertically sub-sampled, i.e. the height and width of the U and V planes are
+ half that of the Y plane.
+
+ \value Format_YV12
+ The frame is stored using an 8-bit per component planar YVU format with the V and U planes
+ horizontally and vertically sub-sampled, i.e. the height and width of the V and U planes are
+ half that of the Y plane.
+
+ \value Format_UYVY
+ The frame is stored using an 8-bit per component packed YUV format with the U and V planes
+ horizontally sub-sampled (U-Y-V-Y), i.e. two horizontally adjacent pixels are stored as a 32-bit
+ macropixel which has a Y value for each pixel and common U and V values.
+
+ \value Format_YUYV
+ The frame is stored using an 8-bit per component packed YUV format with the U and V planes
+ horizontally sub-sampled (Y-U-Y-V), i.e. two horizontally adjacent pixels are stored as a 32-bit
+ macropixel which has a Y value for each pixel and common U and V values.
+
+ \value Format_NV12
+ The frame is stored using an 8-bit per component semi-planar YUV format with a Y plane (Y)
+ followed by a horizontally and vertically sub-sampled, packed UV plane (U-V).
+
+ \value Format_NV21
+ The frame is stored using an 8-bit per component semi-planar YUV format with a Y plane (Y)
+ followed by a horizontally and vertically sub-sampled, packed VU plane (V-U).
+
+ \value Format_IMC1
+ The frame is stored using an 8-bit per component planar YUV format with the U and V planes
+ horizontally and vertically sub-sampled. This is similar to the Format_YUV420P type, except
+ that the bytes per line of the U and V planes are padded out to the same stride as the Y plane.
+
+ \value Format_IMC2
+ The frame is stored using an 8-bit per component planar YUV format with the U and V planes
+ horizontally and vertically sub-sampled. This is similar to the Format_YUV420P type, except
+ that the lines of the U and V planes are interleaved, i.e. each line of U data is followed by a
+ line of V data creating a single line of the same stride as the Y data.
+
+ \value Format_IMC3
+ The frame is stored using an 8-bit per component planar YVU format with the V and U planes
+ horizontally and vertically sub-sampled. This is similar to the Format_YV12 type, except that
+ the bytes per line of the V and U planes are padded out to the same stride as the Y plane.
+
+ \value Format_IMC4
+ The frame is stored using an 8-bit per component planar YVU format with the V and U planes
+ horizontally and vertically sub-sampled. This is similar to the Format_YV12 type, except that
+ the lines of the V and U planes are interleaved, i.e. each line of V data is followed by a line
+ of U data creating a single line of the same stride as the Y data.
+
+ \value Format_Y8
+ The frame is stored using an 8-bit greyscale format.
+
+ \value Format_Y16
+ The frame is stored using a 16-bit linear greyscale format. Little endian.
+
+ \value Format_Jpeg
+ The frame is stored in compressed Jpeg format.
+
+ \value Format_CameraRaw
+ The frame is stored using a device specific camera raw format.
+
+ \value Format_AdobeDng
+ The frame is stored using raw Adobe Digital Negative (DNG) format.
+
+ \value Format_User
+ Start value for user defined pixel formats.
+*/
+
+/*!
+ \enum QVideoFrame::FieldType
+
+ Specifies the field an interlaced video frame belongs to.
+
+ \value ProgressiveFrame The frame is not interlaced.
+ \value TopField The frame contains a top field.
+ \value BottomField The frame contains a bottom field.
+ \value InterlacedFrame The frame contains a merged top and bottom field.
+*/
+
+/*!
+ Constructs a null video frame.
+*/
+QVideoFrame::QVideoFrame()
+ : d(new QVideoFramePrivate)
+{
+}
+
+/*!
+ Constructs a video frame from a \a buffer with the given pixel \a format and \a size in pixels.
+
+ \note This doesn't increment the reference count of the video buffer.
+ \since 1.0
+*/
+QVideoFrame::QVideoFrame(
+ QAbstractVideoBuffer *buffer, const QSize &size, PixelFormat format)
+ : d(new QVideoFramePrivate(size, format))
+{
+ d->buffer = buffer;
+}
+
+/*!
+ Constructs a video frame of the given pixel \a format and \a size in pixels.
+
+ The \a bytesPerLine (stride) is the length of each scan line in bytes, and \a bytes is the total
+ number of bytes that must be allocated for the frame.
+ \since 1.0
+*/
+QVideoFrame::QVideoFrame(int bytes, const QSize &size, int bytesPerLine, PixelFormat format)
+ : d(new QVideoFramePrivate(size, format))
+{
+ if (bytes > 0) {
+ QByteArray data;
+ data.resize(bytes);
+
+ // Check the memory was successfully allocated.
+ if (!data.isEmpty())
+ d->buffer = new QMemoryVideoBuffer(data, bytesPerLine);
+ }
+}
+
+/*!
+ Constructs a video frame from an \a image.
+
+ \note This will construct an invalid video frame if there is no frame type equivalent to the
+ image format.
+
+ \since 1.0
+ \sa pixelFormatFromImageFormat()
+*/
+QVideoFrame::QVideoFrame(const QImage &image)
+ : d(new QVideoFramePrivate(
+ image.size(), pixelFormatFromImageFormat(image.format())))
+{
+ if (d->pixelFormat != Format_Invalid)
+ d->buffer = new QImageVideoBuffer(image);
+}
+
+/*!
+ Constructs a copy of \a other.
+
+ XXX reference count
+
+ \since 1.0
+*/
+QVideoFrame::QVideoFrame(const QVideoFrame &other)
+ : d(other.d)
+{
+}
+
+/*!
+ Assigns the contents of \a other to a video frame.
+ \since 1.0
+*/
+QVideoFrame &QVideoFrame::operator =(const QVideoFrame &other)
+{
+ d = other.d;
+
+ return *this;
+}
+
+/*!
+ Destroys a video frame.
+
+ XXX reference count
+*/
+QVideoFrame::~QVideoFrame()
+{
+}
+
+/*!
+ Identifies whether a video frame is valid.
+
+ An invalid frame has no video buffer associated with it.
+
+ Returns true if the frame is valid, and false if it is not.
+ \since 1.0
+*/
+bool QVideoFrame::isValid() const
+{
+ return d->buffer != 0;
+}
+
+/*!
+ Returns the color format of a video frame.
+ \since 1.0
+*/
+QVideoFrame::PixelFormat QVideoFrame::pixelFormat() const
+{
+ return d->pixelFormat;
+}
+
+/*!
+ Returns the type of a video frame's handle.
+
+ XXX What about it?
+
+ \since 1.0
+*/
+QAbstractVideoBuffer::HandleType QVideoFrame::handleType() const
+{
+ return d->buffer ? d->buffer->handleType() : QAbstractVideoBuffer::NoHandle;
+}
+
+/*!
+ Returns the dimensions of a video frame.
+ \since 1.0
+*/
+QSize QVideoFrame::size() const
+{
+ return d->size;
+}
+
+/*!
+ Returns the width of a video frame.
+ \since 1.0
+*/
+int QVideoFrame::width() const
+{
+ return d->size.width();
+}
+
+/*!
+ Returns the height of a video frame.
+ \since 1.0
+*/
+int QVideoFrame::height() const
+{
+ return d->size.height();
+}
+
+/*!
+ Returns the field an interlaced video frame belongs to.
+
+ If the video is not interlaced this will return WholeFrame.
+ \since 1.0
+*/
+QVideoFrame::FieldType QVideoFrame::fieldType() const
+{
+ return d->fieldType;
+}
+
+/*!
+ Sets the \a field an interlaced video frame belongs to.
+ \since 1.0
+*/
+void QVideoFrame::setFieldType(QVideoFrame::FieldType field)
+{
+ d->fieldType = field;
+}
+
+/*!
+ Identifies if a video frame's contents are currently mapped to system memory.
+
+ This is a convenience function which checks that the \l {QAbstractVideoBuffer::MapMode}{MapMode}
+ of the frame is not equal to QAbstractVideoBuffer::NotMapped.
+
+ Returns true if the contents of the video frame are mapped to system memory, and false
+ otherwise.
+
+ \since 1.0
+ \sa mapMode(), QAbstractVideoBuffer::MapMode
+*/
+
+bool QVideoFrame::isMapped() const
+{
+ return d->buffer != 0 && d->buffer->mapMode() != QAbstractVideoBuffer::NotMapped;
+}
+
+/*!
+ Identifies if the mapped contents of a video frame will be persisted when the frame is unmapped.
+
+ This is a convenience function which checks if the \l {QAbstractVideoBuffer::MapMode}{MapMode}
+ contains the QAbstractVideoBuffer::WriteOnly flag.
+
+ Returns true if the video frame will be updated when unmapped, and false otherwise.
+
+ \note The result of altering the data of a frame that is mapped in read-only mode is undefined.
+ Depending on the buffer implementation the changes may be persisted, or worse alter a shared
+ buffer.
+
+ \since 1.0
+ \sa mapMode(), QAbstractVideoBuffer::MapMode
+*/
+bool QVideoFrame::isWritable() const
+{
+ return d->buffer != 0 && (d->buffer->mapMode() & QAbstractVideoBuffer::WriteOnly);
+}
+
+/*!
+ Identifies if the mapped contents of a video frame were read from the frame when it was mapped.
+
+ This is a convenience function which checks if the \l {QAbstractVideoBuffer::MapMode}{MapMode}
+ contains the QAbstractVideoBuffer::WriteOnly flag.
+
+ Returns true if the contents of the mapped memory were read from the video frame, and false
+ otherwise.
+
+ \since 1.0
+ \sa mapMode(), QAbstractVideoBuffer::MapMode
+*/
+bool QVideoFrame::isReadable() const
+{
+ return d->buffer != 0 && (d->buffer->mapMode() & QAbstractVideoBuffer::ReadOnly);
+}
+
+/*!
+ Returns the mode a video frame was mapped to system memory in.
+
+ \since 1.0
+ \sa map(), QAbstractVideoBuffer::MapMode
+*/
+QAbstractVideoBuffer::MapMode QVideoFrame::mapMode() const
+{
+ return d->buffer != 0 ? d->buffer->mapMode() : QAbstractVideoBuffer::NotMapped;
+}
+
+/*!
+ Maps the contents of a video frame to memory.
+
+ The map \a mode indicates whether the contents of the mapped memory should be read from and/or
+ written to the frame. If the map mode includes the QAbstractVideoBuffer::ReadOnly flag the
+ mapped memory will be populated with the content of the video frame when mapped. If the map
+ mode inclues the QAbstractVideoBuffer::WriteOnly flag the content of the mapped memory will be
+ persisted in the frame when unmapped.
+
+ While mapped the contents of a video frame can be accessed directly through the pointer returned
+ by the bits() function.
+
+ When access to the data is no longer needed be sure to call the unmap() function to release the
+ mapped memory and possibly update the video frame contents.
+
+ Returns true if the buffer was mapped to memory in the given \a mode and false otherwise.
+
+ XXX examples and why do I care
+
+ \since 1.0
+ \sa unmap(), mapMode(), bits()
+*/
+bool QVideoFrame::map(QAbstractVideoBuffer::MapMode mode)
+{
+ if (d->buffer != 0 && d->data == 0) {
+ Q_ASSERT(d->bytesPerLine == 0);
+ Q_ASSERT(d->mappedBytes == 0);
+
+ d->data = d->buffer->map(mode, &d->mappedBytes, &d->bytesPerLine);
+
+ return d->data != 0;
+ }
+
+ return false;
+}
+
+/*!
+ Releases the memory mapped by the map() function.
+
+ If the \l {QAbstractVideoBuffer::MapMode}{MapMode} included the QAbstractVideoBuffer::WriteOnly
+ flag this will persist the current content of the mapped memory to the video frame.
+
+ \since 1.0
+ \sa map()
+*/
+void QVideoFrame::unmap()
+{
+ if (d->data != 0) {
+ d->mappedBytes = 0;
+ d->bytesPerLine = 0;
+ d->data = 0;
+
+ d->buffer->unmap();
+ }
+}
+
+/*!
+ Returns the number of bytes in a scan line.
+
+ \note This is the bytes per line of the first plane only. The bytes per line of subsequent
+ planes should be calculated as per the frame type.
+
+ XXX examples of these calculations
+
+ This value is only valid while the frame data is \l {map()}{mapped}.
+
+ \since 1.0
+ \sa bits(), map(), mappedBytes()
+*/
+int QVideoFrame::bytesPerLine() const
+{
+ return d->bytesPerLine;
+}
+
+/*!
+ Returns a pointer to the start of the frame data buffer.
+
+ This value is only valid while the frame data is \l {map()}{mapped}.
+
+ Changes made to data accessed via this pointer (when mapped with write access)
+ are only guaranteed to have been persisted when unmap() is called.
+
+ \since 1.0
+ \sa map(), mappedBytes(), bytesPerLine()
+*/
+uchar *QVideoFrame::bits()
+{
+ return d->data;
+}
+
+/*!
+ Returns a pointer to the start of the frame data buffer.
+
+ This value is only valid while the frame data is \l {map()}{mapped}.
+
+ If the buffer was not mapped with read access, the contents of this
+ buffer will initially be uninitialized.
+
+ \since 1.0
+ \sa map(), mappedBytes(), bytesPerLine()
+*/
+const uchar *QVideoFrame::bits() const
+{
+ return d->data;
+}
+
+/*!
+ Returns the number of bytes occupied by the mapped frame data.
+
+ This value is only valid while the frame data is \l {map()}{mapped}.
+
+ \since 1.0
+ \sa map()
+*/
+int QVideoFrame::mappedBytes() const
+{
+ return d->mappedBytes;
+}
+
+/*!
+ Returns a type specific handle to a video frame's buffer.
+
+ For an OpenGL texture this would be the texture ID.
+
+ XXX Perhaps a table with corresondence
+
+ \since 1.0
+ \sa QAbstractVideoBuffer::handle()
+*/
+QVariant QVideoFrame::handle() const
+{
+ return d->buffer != 0 ? d->buffer->handle() : QVariant();
+}
+
+/*!
+ Returns the presentation time when the frame should be displayed.
+ \since 1.0
+*/
+qint64 QVideoFrame::startTime() const
+{
+ return d->startTime;
+}
+
+/*!
+ Sets the presentation \a time when the frame should be displayed.
+ \since 1.0
+*/
+void QVideoFrame::setStartTime(qint64 time)
+{
+ d->startTime = time;
+}
+
+/*!
+ Returns the presentation time when a frame should stop being displayed.
+
+ XXX example? if start=end what happens?
+ \since 1.0
+*/
+qint64 QVideoFrame::endTime() const
+{
+ return d->endTime;
+}
+
+/*!
+ Sets the presentation \a time when a frame should stop being displayed.
+ \since 1.0
+*/
+void QVideoFrame::setEndTime(qint64 time)
+{
+ d->endTime = time;
+}
+
+/*!
+ Returns a video pixel format equivalent to an image \a format. If there is no equivalent
+ format QVideoFrame::InvalidType is returned instead.
+ \since 1.0
+*/
+QVideoFrame::PixelFormat QVideoFrame::pixelFormatFromImageFormat(QImage::Format format)
+{
+ switch (format) {
+ case QImage::Format_Invalid:
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ case QImage::Format_Indexed8:
+ return Format_Invalid;
+ case QImage::Format_RGB32:
+ return Format_RGB32;
+ case QImage::Format_ARGB32:
+ return Format_ARGB32;
+ case QImage::Format_ARGB32_Premultiplied:
+ return Format_ARGB32_Premultiplied;
+ case QImage::Format_RGB16:
+ return Format_RGB565;
+ case QImage::Format_ARGB8565_Premultiplied:
+ return Format_ARGB8565_Premultiplied;
+ case QImage::Format_RGB666:
+ case QImage::Format_ARGB6666_Premultiplied:
+ return Format_Invalid;
+ case QImage::Format_RGB555:
+ return Format_RGB555;
+ case QImage::Format_ARGB8555_Premultiplied:
+ return Format_Invalid;
+ case QImage::Format_RGB888:
+ return Format_RGB24;
+ case QImage::Format_RGB444:
+ case QImage::Format_ARGB4444_Premultiplied:
+ return Format_Invalid;
+ case QImage::NImageFormats:
+ return Format_Invalid;
+ }
+ return Format_Invalid;
+}
+
+/*!
+ Returns an image format equivalent to a video frame pixel \a format. If there is no equivalent
+ format QImage::Format_Invalid is returned instead.
+ \since 1.0
+*/
+QImage::Format QVideoFrame::imageFormatFromPixelFormat(PixelFormat format)
+{
+ switch (format) {
+ case Format_Invalid:
+ return QImage::Format_Invalid;
+ case Format_ARGB32:
+ return QImage::Format_ARGB32;
+ case Format_ARGB32_Premultiplied:
+ return QImage::Format_ARGB32_Premultiplied;
+ case Format_RGB32:
+ return QImage::Format_RGB32;
+ case Format_RGB24:
+ return QImage::Format_RGB888;
+ case Format_RGB565:
+ return QImage::Format_RGB16;
+ case Format_RGB555:
+ return QImage::Format_RGB555;
+ case Format_ARGB8565_Premultiplied:
+ return QImage::Format_ARGB8565_Premultiplied;
+ case Format_BGRA32:
+ case Format_BGRA32_Premultiplied:
+ case Format_BGR32:
+ case Format_BGR24:
+ return QImage::Format_Invalid;
+ case Format_BGR565:
+ case Format_BGR555:
+ case Format_BGRA5658_Premultiplied:
+ case Format_AYUV444:
+ case Format_AYUV444_Premultiplied:
+ case Format_YUV444:
+ case Format_YUV420P:
+ case Format_YV12:
+ case Format_UYVY:
+ case Format_YUYV:
+ case Format_NV12:
+ case Format_NV21:
+ case Format_IMC1:
+ case Format_IMC2:
+ case Format_IMC3:
+ case Format_IMC4:
+ case Format_Y8:
+ case Format_Y16:
+ case Format_Jpeg:
+ case Format_CameraRaw:
+ case Format_AdobeDng:
+ return QImage::Format_Invalid;
+ case Format_User:
+ return QImage::Format_Invalid;
+ }
+ return QImage::Format_Invalid;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/multimediakit/video/qvideoframe.h b/src/multimediakit/video/qvideoframe.h
new file mode 100644
index 000000000..8d90dbb96
--- /dev/null
+++ b/src/multimediakit/video/qvideoframe.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** 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 QVIDEOFRAME_H
+#define QVIDEOFRAME_H
+
+#include <QtCore/qmetatype.h>
+#include <QtCore/qshareddata.h>
+#include <QtGui/qimage.h>
+#include <qabstractvideobuffer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSize;
+class QVariant;
+
+class QVideoFramePrivate;
+
+class Q_MULTIMEDIA_EXPORT QVideoFrame
+{
+public:
+ enum FieldType
+ {
+ ProgressiveFrame,
+ TopField,
+ BottomField,
+ InterlacedFrame
+ };
+
+ enum PixelFormat
+ {
+ Format_Invalid,
+ Format_ARGB32,
+ Format_ARGB32_Premultiplied,
+ Format_RGB32,
+ Format_RGB24,
+ Format_RGB565,
+ Format_RGB555,
+ Format_ARGB8565_Premultiplied,
+ Format_BGRA32,
+ Format_BGRA32_Premultiplied,
+ Format_BGR32,
+ Format_BGR24,
+ Format_BGR565,
+ Format_BGR555,
+ Format_BGRA5658_Premultiplied,
+
+ Format_AYUV444,
+ Format_AYUV444_Premultiplied,
+ Format_YUV444,
+ Format_YUV420P,
+ Format_YV12,
+ Format_UYVY,
+ Format_YUYV,
+ Format_NV12,
+ Format_NV21,
+ Format_IMC1,
+ Format_IMC2,
+ Format_IMC3,
+ Format_IMC4,
+ Format_Y8,
+ Format_Y16,
+
+ Format_Jpeg,
+
+ Format_CameraRaw,
+ Format_AdobeDng,
+
+ Format_User = 1000
+ };
+
+ QVideoFrame();
+ QVideoFrame(QAbstractVideoBuffer *buffer, const QSize &size, PixelFormat format);
+ QVideoFrame(int bytes, const QSize &size, int bytesPerLine, PixelFormat format);
+ QVideoFrame(const QImage &image);
+ QVideoFrame(const QVideoFrame &other);
+ ~QVideoFrame();
+
+ QVideoFrame &operator =(const QVideoFrame &other);
+
+ bool isValid() const;
+
+ PixelFormat pixelFormat() const;
+
+ QAbstractVideoBuffer::HandleType handleType() const;
+
+ QSize size() const;
+ int width() const;
+ int height() const;
+
+ FieldType fieldType() const;
+ void setFieldType(FieldType);
+
+ bool isMapped() const;
+ bool isReadable() const;
+ bool isWritable() const;
+
+ QAbstractVideoBuffer::MapMode mapMode() const;
+
+ bool map(QAbstractVideoBuffer::MapMode mode);
+ void unmap();
+
+ int bytesPerLine() const;
+
+ uchar *bits();
+ const uchar *bits() const;
+ int mappedBytes() const;
+
+ QVariant handle() const;
+
+ qint64 startTime() const;
+ void setStartTime(qint64 time);
+
+ qint64 endTime() const;
+ void setEndTime(qint64 time);
+
+ static PixelFormat pixelFormatFromImageFormat(QImage::Format format);
+ static QImage::Format imageFormatFromPixelFormat(PixelFormat format);
+
+private:
+ QExplicitlySharedDataPointer<QVideoFramePrivate> d;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QVideoFrame::FieldType)
+Q_DECLARE_METATYPE(QVideoFrame::PixelFormat)
+
+QT_END_HEADER
+
+#endif
+
diff --git a/src/multimediakit/video/qvideosurfaceformat.cpp b/src/multimediakit/video/qvideosurfaceformat.cpp
new file mode 100644
index 000000000..58b2baa44
--- /dev/null
+++ b/src/multimediakit/video/qvideosurfaceformat.cpp
@@ -0,0 +1,709 @@
+/****************************************************************************
+**
+** 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 "qvideosurfaceformat.h"
+
+#include <qdebug.h>
+#include <qmetatype.h>
+#include <qpair.h>
+#include <qvariant.h>
+#include <qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+class QVideoSurfaceFormatPrivate : public QSharedData
+{
+public:
+ QVideoSurfaceFormatPrivate()
+ : pixelFormat(QVideoFrame::Format_Invalid)
+ , handleType(QAbstractVideoBuffer::NoHandle)
+ , scanLineDirection(QVideoSurfaceFormat::TopToBottom)
+ , pixelAspectRatio(1, 1)
+ , ycbcrColorSpace(QVideoSurfaceFormat::YCbCr_Undefined)
+ , frameRate(0.0)
+ {
+ }
+
+ QVideoSurfaceFormatPrivate(
+ const QSize &size,
+ QVideoFrame::PixelFormat format,
+ QAbstractVideoBuffer::HandleType type)
+ : pixelFormat(format)
+ , handleType(type)
+ , scanLineDirection(QVideoSurfaceFormat::TopToBottom)
+ , frameSize(size)
+ , pixelAspectRatio(1, 1)
+ , ycbcrColorSpace(QVideoSurfaceFormat::YCbCr_Undefined)
+ , viewport(QPoint(0, 0), size)
+ , frameRate(0.0)
+ {
+ }
+
+ QVideoSurfaceFormatPrivate(const QVideoSurfaceFormatPrivate &other)
+ : QSharedData(other)
+ , pixelFormat(other.pixelFormat)
+ , handleType(other.handleType)
+ , scanLineDirection(other.scanLineDirection)
+ , frameSize(other.frameSize)
+ , pixelAspectRatio(other.pixelAspectRatio)
+ , ycbcrColorSpace(other.ycbcrColorSpace)
+ , viewport(other.viewport)
+ , frameRate(other.frameRate)
+ , propertyNames(other.propertyNames)
+ , propertyValues(other.propertyValues)
+ {
+ }
+
+ bool operator ==(const QVideoSurfaceFormatPrivate &other) const
+ {
+ if (pixelFormat == other.pixelFormat
+ && handleType == other.handleType
+ && scanLineDirection == other.scanLineDirection
+ && frameSize == other.frameSize
+ && pixelAspectRatio == other.pixelAspectRatio
+ && viewport == other.viewport
+ && frameRatesEqual(frameRate, other.frameRate)
+ && ycbcrColorSpace == other.ycbcrColorSpace
+ && propertyNames.count() == other.propertyNames.count()) {
+ for (int i = 0; i < propertyNames.count(); ++i) {
+ int j = other.propertyNames.indexOf(propertyNames.at(i));
+
+ if (j == -1 || propertyValues.at(i) != other.propertyValues.at(j))
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ inline static bool frameRatesEqual(qreal r1, qreal r2)
+ {
+ return qAbs(r1 - r2) <= 0.00001 * qMin(qAbs(r1), qAbs(r2));
+ }
+
+ QVideoFrame::PixelFormat pixelFormat;
+ QAbstractVideoBuffer::HandleType handleType;
+ QVideoSurfaceFormat::Direction scanLineDirection;
+ QSize frameSize;
+ QSize pixelAspectRatio;
+ QVideoSurfaceFormat::YCbCrColorSpace ycbcrColorSpace;
+ QRect viewport;
+ qreal frameRate;
+ QList<QByteArray> propertyNames;
+ QList<QVariant> propertyValues;
+};
+
+/*!
+ \class QVideoSurfaceFormat
+ \brief The QVideoSurfaceFormat class specifies the stream format of a video presentation
+ surface.
+ \since 1.0
+ \inmodule QtMultimediaKit
+
+ A video surface presents a stream of video frames. The surface's format describes the type of
+ the frames and determines how they should be presented.
+
+ XXX Why do I care
+ XXX why isn't it videostreamformat then?
+
+ The core properties of a video stream required to setup a video surface are the pixel format
+ given by pixelFormat(), and the frame dimensions given by frameSize().
+
+ If the surface is to present frames using a frame's handle a surface format will also include
+ a handle type which is given by the handleType() function.
+
+ The region of a frame that is actually displayed on a video surface is given by the viewport().
+ A stream may have a viewport less than the entire region of a frame to allow for videos smaller
+ than the nearest optimal size of a video frame. For example the width of a frame may be
+ extended so that the start of each scan line is eight byte aligned.
+
+ Other common properties are the pixelAspectRatio(), scanLineDirection(), and frameRate().
+ Additionally a stream may have some additional type specific properties which are listed by the
+ dynamicPropertyNames() function and can be accessed using the property(), and setProperty()
+ functions.
+*/
+
+/*!
+ \enum QVideoSurfaceFormat::Direction
+
+ Enumerates the layout direction of video scan lines.
+
+ \value TopToBottom Scan lines are arranged from the top of the frame to the bottom.
+ \value BottomToTop Scan lines are arranged from the bottom of the frame to the top.
+*/
+
+/*!
+ \enum QVideoSurfaceFormat::YCbCrColorSpace
+
+ Enumerates the Y'CbCr color space of video frames.
+
+ \value YCbCr_Undefined
+ No color space is specified.
+
+ \value YCbCr_BT601
+ A Y'CbCr color space defined by ITU-R recommendation BT.601
+ with Y value range from 16 to 235, and Cb/Cr range from 16 to 240.
+ Used in standard definition video.
+
+ \value YCbCr_BT709
+ A Y'CbCr color space defined by ITU-R BT.709 with the same values range as YCbCr_BT601. Used
+ for HDTV.
+
+ \value YCbCr_xvYCC601
+ The BT.601 color space with the value range extended to 0 to 255.
+ It is backward compatibile with BT.601 and uses values outside BT.601 range to represent a
+ wider range of colors.
+
+ \value YCbCr_xvYCC709
+ The BT.709 color space with the value range extended to 0 to 255.
+
+ \value YCbCr_JPEG
+ The full range Y'CbCr color space used in JPEG files.
+*/
+
+/*!
+ Constructs a null video stream format.
+*/
+QVideoSurfaceFormat::QVideoSurfaceFormat()
+ : d(new QVideoSurfaceFormatPrivate)
+{
+}
+
+/*!
+ Contructs a description of stream which receives stream of \a type buffers with given frame
+ \a size and pixel \a format.
+ \since 1.0
+*/
+QVideoSurfaceFormat::QVideoSurfaceFormat(
+ const QSize& size, QVideoFrame::PixelFormat format, QAbstractVideoBuffer::HandleType type)
+ : d(new QVideoSurfaceFormatPrivate(size, format, type))
+{
+}
+
+/*!
+ Constructs a copy of \a other.
+ \since 1.0
+*/
+QVideoSurfaceFormat::QVideoSurfaceFormat(const QVideoSurfaceFormat &other)
+ : d(other.d)
+{
+}
+
+/*!
+ Assigns the values of \a other to this object.
+ \since 1.0
+*/
+QVideoSurfaceFormat &QVideoSurfaceFormat::operator =(const QVideoSurfaceFormat &other)
+{
+ d = other.d;
+
+ return *this;
+}
+
+/*!
+ Destroys a video stream description.
+*/
+QVideoSurfaceFormat::~QVideoSurfaceFormat()
+{
+}
+
+/*!
+ Identifies if a video surface format has a valid pixel format and frame size.
+
+ Returns true if the format is valid, and false otherwise.
+ \since 1.0
+*/
+bool QVideoSurfaceFormat::isValid() const
+{
+ return d->pixelFormat != QVideoFrame::Format_Invalid && d->frameSize.isValid();
+}
+
+/*!
+ Returns true if \a other is the same as this video format, and false if they are different.
+ \since 1.0
+*/
+bool QVideoSurfaceFormat::operator ==(const QVideoSurfaceFormat &other) const
+{
+ return d == other.d || *d == *other.d;
+}
+
+/*!
+ Returns true if \a other is different to a video format, and false if they are the same.
+ \since 1.0
+*/
+bool QVideoSurfaceFormat::operator !=(const QVideoSurfaceFormat &other) const
+{
+ return d != other.d && !(*d == *other.d);
+}
+
+/*!
+ Returns the pixel format of frames in a video stream.
+ \since 1.0
+*/
+QVideoFrame::PixelFormat QVideoSurfaceFormat::pixelFormat() const
+{
+ return d->pixelFormat;
+}
+
+/*!
+ Returns the type of handle the surface uses to present the frame data.
+
+ If the handle type is QAbstractVideoBuffer::NoHandle buffers with any handle type are valid
+ provided they can be \l {QAbstractVideoBuffer::map()}{mapped} with the
+ QAbstractVideoBuffer::ReadOnly flag. If the handleType() is not QAbstractVideoBuffer::NoHandle
+ then the handle type of the buffer must be the same as that of the surface format.
+ \since 1.0
+*/
+QAbstractVideoBuffer::HandleType QVideoSurfaceFormat::handleType() const
+{
+ return d->handleType;
+}
+
+/*!
+ Returns the dimensions of frames in a video stream.
+
+ \sa frameWidth(), frameHeight()
+ \since 1.0
+*/
+QSize QVideoSurfaceFormat::frameSize() const
+{
+ return d->frameSize;
+}
+
+/*!
+ Returns the width of frames in a video stream.
+
+ \sa frameSize(), frameHeight()
+ \since 1.0
+*/
+int QVideoSurfaceFormat::frameWidth() const
+{
+ return d->frameSize.width();
+}
+
+/*!
+ Returns the height of frame in a video stream.
+ \since 1.0
+*/
+int QVideoSurfaceFormat::frameHeight() const
+{
+ return d->frameSize.height();
+}
+
+/*!
+ Sets the size of frames in a video stream to \a size.
+
+ This will reset the viewport() to fill the entire frame.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setFrameSize(const QSize &size)
+{
+ d->frameSize = size;
+ d->viewport = QRect(QPoint(0, 0), size);
+}
+
+/*!
+ \overload
+
+ Sets the \a width and \a height of frames in a video stream.
+
+ This will reset the viewport() to fill the entire frame.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setFrameSize(int width, int height)
+{
+ d->frameSize = QSize(width, height);
+ d->viewport = QRect(0, 0, width, height);
+}
+
+/*!
+ Returns the viewport of a video stream.
+
+ The viewport is the region of a video frame that is actually displayed.
+
+ By default the viewport covers an entire frame.
+ \since 1.0
+*/
+QRect QVideoSurfaceFormat::viewport() const
+{
+ return d->viewport;
+}
+
+/*!
+ Sets the viewport of a video stream to \a viewport.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setViewport(const QRect &viewport)
+{
+ d->viewport = viewport;
+}
+
+/*!
+ Returns the direction of scan lines.
+ \since 1.0
+*/
+QVideoSurfaceFormat::Direction QVideoSurfaceFormat::scanLineDirection() const
+{
+ return d->scanLineDirection;
+}
+
+/*!
+ Sets the \a direction of scan lines.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setScanLineDirection(Direction direction)
+{
+ d->scanLineDirection = direction;
+}
+
+/*!
+ Returns the frame rate of a video stream in frames per second.
+ \since 1.0
+*/
+qreal QVideoSurfaceFormat::frameRate() const
+{
+ return d->frameRate;
+}
+
+/*!
+ Sets the frame \a rate of a video stream in frames per second.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setFrameRate(qreal rate)
+{
+ d->frameRate = rate;
+}
+
+/*!
+ Returns a video stream's pixel aspect ratio.
+ \since 1.0
+*/
+QSize QVideoSurfaceFormat::pixelAspectRatio() const
+{
+ return d->pixelAspectRatio;
+}
+
+/*!
+ Sets a video stream's pixel aspect \a ratio.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setPixelAspectRatio(const QSize &ratio)
+{
+ d->pixelAspectRatio = ratio;
+}
+
+/*!
+ \overload
+
+ Sets the \a horizontal and \a vertical elements of a video stream's pixel aspect ratio.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setPixelAspectRatio(int horizontal, int vertical)
+{
+ d->pixelAspectRatio = QSize(horizontal, vertical);
+}
+
+/*!
+ Returns the Y'CbCr color space of a video stream.
+ \since 1.0
+*/
+QVideoSurfaceFormat::YCbCrColorSpace QVideoSurfaceFormat::yCbCrColorSpace() const
+{
+ return d->ycbcrColorSpace;
+}
+
+/*!
+ Sets the Y'CbCr color \a space of a video stream.
+ It is only used with raw YUV frame types.
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setYCbCrColorSpace(QVideoSurfaceFormat::YCbCrColorSpace space)
+{
+ d->ycbcrColorSpace = space;
+}
+
+/*!
+ Returns a suggested size in pixels for the video stream.
+
+ This is the size of the viewport scaled according to the pixel aspect ratio.
+ \since 1.0
+*/
+QSize QVideoSurfaceFormat::sizeHint() const
+{
+ QSize size = d->viewport.size();
+
+ if (d->pixelAspectRatio.height() != 0)
+ size.setWidth(size.width() * d->pixelAspectRatio.width() / d->pixelAspectRatio.height());
+
+ return size;
+}
+
+/*!
+ Returns a list of video format dynamic property names.
+ \since 1.0
+*/
+QList<QByteArray> QVideoSurfaceFormat::propertyNames() const
+{
+ return (QList<QByteArray>()
+ << "handleType"
+ << "pixelFormat"
+ << "frameSize"
+ << "frameWidth"
+ << "viewport"
+ << "scanLineDirection"
+ << "frameRate"
+ << "pixelAspectRatio"
+ << "sizeHint"
+ << "yCbCrColorSpace")
+ + d->propertyNames;
+}
+
+/*!
+ Returns the value of the video format's \a name property.
+ \since 1.0
+*/
+QVariant QVideoSurfaceFormat::property(const char *name) const
+{
+ if (qstrcmp(name, "handleType") == 0) {
+ return qVariantFromValue(d->handleType);
+ } else if (qstrcmp(name, "pixelFormat") == 0) {
+ return qVariantFromValue(d->pixelFormat);
+ } else if (qstrcmp(name, "handleType") == 0) {
+ return qVariantFromValue(d->handleType);
+ } else if (qstrcmp(name, "frameSize") == 0) {
+ return d->frameSize;
+ } else if (qstrcmp(name, "frameWidth") == 0) {
+ return d->frameSize.width();
+ } else if (qstrcmp(name, "frameHeight") == 0) {
+ return d->frameSize.height();
+ } else if (qstrcmp(name, "viewport") == 0) {
+ return d->viewport;
+ } else if (qstrcmp(name, "scanLineDirection") == 0) {
+ return qVariantFromValue(d->scanLineDirection);
+ } else if (qstrcmp(name, "frameRate") == 0) {
+ return qVariantFromValue(d->frameRate);
+ } else if (qstrcmp(name, "pixelAspectRatio") == 0) {
+ return qVariantFromValue(d->pixelAspectRatio);
+ } else if (qstrcmp(name, "sizeHint") == 0) {
+ return sizeHint();
+ } else if (qstrcmp(name, "yCbCrColorSpace") == 0) {
+ return qVariantFromValue(d->ycbcrColorSpace);
+ } else {
+ int id = 0;
+ for (; id < d->propertyNames.count() && d->propertyNames.at(id) != name; ++id) {}
+
+ return id < d->propertyValues.count()
+ ? d->propertyValues.at(id)
+ : QVariant();
+ }
+}
+
+/*!
+ Sets the video format's \a name property to \a value.
+
+ Trying to set a read only property will be ignored.
+
+ \since 1.0
+*/
+void QVideoSurfaceFormat::setProperty(const char *name, const QVariant &value)
+{
+ if (qstrcmp(name, "handleType") == 0) {
+ // read only.
+ } else if (qstrcmp(name, "pixelFormat") == 0) {
+ // read only.
+ } else if (qstrcmp(name, "frameSize") == 0) {
+ if (qVariantCanConvert<QSize>(value)) {
+ d->frameSize = qvariant_cast<QSize>(value);
+ d->viewport = QRect(QPoint(0, 0), d->frameSize);
+ }
+ } else if (qstrcmp(name, "frameWidth") == 0) {
+ // read only.
+ } else if (qstrcmp(name, "frameHeight") == 0) {
+ // read only.
+ } else if (qstrcmp(name, "viewport") == 0) {
+ if (qVariantCanConvert<QRect>(value))
+ d->viewport = qvariant_cast<QRect>(value);
+ } else if (qstrcmp(name, "scanLineDirection") == 0) {
+ if (qVariantCanConvert<Direction>(value))
+ d->scanLineDirection = qvariant_cast<Direction>(value);
+ } else if (qstrcmp(name, "frameRate") == 0) {
+ if (qVariantCanConvert<qreal>(value))
+ d->frameRate = qvariant_cast<qreal>(value);
+ } else if (qstrcmp(name, "pixelAspectRatio") == 0) {
+ if (qVariantCanConvert<QSize>(value))
+ d->pixelAspectRatio = qvariant_cast<QSize>(value);
+ } else if (qstrcmp(name, "sizeHint") == 0) {
+ // read only.
+ } else if (qstrcmp(name, "yCbCrColorSpace") == 0) {
+ if (qVariantCanConvert<YCbCrColorSpace>(value))
+ d->ycbcrColorSpace = qvariant_cast<YCbCrColorSpace>(value);
+ } else {
+ int id = 0;
+ for (; id < d->propertyNames.count() && d->propertyNames.at(id) != name; ++id) {}
+
+ if (id < d->propertyValues.count()) {
+ if (value.isNull()) {
+ d->propertyNames.removeAt(id);
+ d->propertyValues.removeAt(id);
+ } else {
+ d->propertyValues[id] = value;
+ }
+ } else if (!value.isNull()) {
+ d->propertyNames.append(QByteArray(name));
+ d->propertyValues.append(value);
+ }
+ }
+}
+
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QVideoSurfaceFormat &f)
+{
+ QString typeName;
+ switch (f.pixelFormat()) {
+ case QVideoFrame::Format_Invalid:
+ typeName = QLatin1String("Format_Invalid");
+ break;
+ case QVideoFrame::Format_ARGB32:
+ typeName = QLatin1String("Format_ARGB32");
+ break;
+ case QVideoFrame::Format_ARGB32_Premultiplied:
+ typeName = QLatin1String("Format_ARGB32_Premultiplied");
+ break;
+ case QVideoFrame::Format_RGB32:
+ typeName = QLatin1String("Format_RGB32");
+ break;
+ case QVideoFrame::Format_RGB24:
+ typeName = QLatin1String("Format_RGB24");
+ break;
+ case QVideoFrame::Format_RGB565:
+ typeName = QLatin1String("Format_RGB565");
+ break;
+ case QVideoFrame::Format_RGB555:
+ typeName = QLatin1String("Format_RGB555");
+ break;
+ case QVideoFrame::Format_ARGB8565_Premultiplied:
+ typeName = QLatin1String("Format_ARGB8565_Premultiplied");
+ break;
+ case QVideoFrame::Format_BGRA32:
+ typeName = QLatin1String("Format_BGRA32");
+ break;
+ case QVideoFrame::Format_BGRA32_Premultiplied:
+ typeName = QLatin1String("Format_BGRA32_Premultiplied");
+ break;
+ case QVideoFrame::Format_BGR32:
+ typeName = QLatin1String("Format_BGR32");
+ break;
+ case QVideoFrame::Format_BGR24:
+ typeName = QLatin1String("Format_BGR24");
+ break;
+ case QVideoFrame::Format_BGR565:
+ typeName = QLatin1String("Format_BGR565");
+ break;
+ case QVideoFrame::Format_BGR555:
+ typeName = QLatin1String("Format_BGR555");
+ break;
+ case QVideoFrame::Format_BGRA5658_Premultiplied:
+ typeName = QLatin1String("Format_BGRA5658_Premultiplied");
+ break;
+ case QVideoFrame::Format_AYUV444:
+ typeName = QLatin1String("Format_AYUV444");
+ break;
+ case QVideoFrame::Format_AYUV444_Premultiplied:
+ typeName = QLatin1String("Format_AYUV444_Premultiplied");
+ break;
+ case QVideoFrame::Format_YUV444:
+ typeName = QLatin1String("Format_YUV444");
+ break;
+ case QVideoFrame::Format_YUV420P:
+ typeName = QLatin1String("Format_YUV420P");
+ break;
+ case QVideoFrame::Format_YV12:
+ typeName = QLatin1String("Format_YV12");
+ break;
+ case QVideoFrame::Format_UYVY:
+ typeName = QLatin1String("Format_UYVY");
+ break;
+ case QVideoFrame::Format_YUYV:
+ typeName = QLatin1String("Format_YUYV");
+ break;
+ case QVideoFrame::Format_NV12:
+ typeName = QLatin1String("Format_NV12");
+ break;
+ case QVideoFrame::Format_NV21:
+ typeName = QLatin1String("Format_NV21");
+ break;
+ case QVideoFrame::Format_IMC1:
+ typeName = QLatin1String("Format_IMC1");
+ break;
+ case QVideoFrame::Format_IMC2:
+ typeName = QLatin1String("Format_IMC2");
+ break;
+ case QVideoFrame::Format_IMC3:
+ typeName = QLatin1String("Format_IMC3");
+ break;
+ case QVideoFrame::Format_IMC4:
+ typeName = QLatin1String("Format_IMC4");
+ break;
+ case QVideoFrame::Format_Y8:
+ typeName = QLatin1String("Format_Y8");
+ break;
+ case QVideoFrame::Format_Y16:
+ typeName = QLatin1String("Format_Y16");
+ default:
+ typeName = QString(QLatin1String("UserType(%1)" )).arg(int(f.pixelFormat()));
+ }
+
+ dbg.nospace() << "QVideoSurfaceFormat(" << typeName;
+ dbg.nospace() << ", " << f.frameSize();
+ dbg.nospace() << ", viewport=" << f.viewport();
+ dbg.nospace() << ", pixelAspectRatio=" << f.pixelAspectRatio();
+ dbg.nospace() << ")";
+
+ foreach(const QByteArray& propertyName, f.propertyNames())
+ dbg << "\n " << propertyName.data() << " = " << f.property(propertyName.data());
+
+ return dbg.space();
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/multimediakit/video/qvideosurfaceformat.h b/src/multimediakit/video/qvideosurfaceformat.h
new file mode 100644
index 000000000..7baf18fd8
--- /dev/null
+++ b/src/multimediakit/video/qvideosurfaceformat.h
@@ -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$
+**
+****************************************************************************/
+
+#ifndef QVIDEOSURFACEFORMAT_H
+#define QVIDEOSURFACEFORMAT_H
+
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qsize.h>
+#include <QtGui/qimage.h>
+#include <qvideoframe.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDebug;
+
+class QVideoSurfaceFormatPrivate;
+
+class Q_MULTIMEDIA_EXPORT QVideoSurfaceFormat
+{
+public:
+ enum Direction
+ {
+ TopToBottom,
+ BottomToTop
+ };
+
+ enum YCbCrColorSpace
+ {
+ YCbCr_Undefined,
+ YCbCr_BT601,
+ YCbCr_BT709,
+ YCbCr_xvYCC601,
+ YCbCr_xvYCC709,
+ YCbCr_JPEG,
+#ifndef qdoc
+ YCbCr_CustomMatrix
+#endif
+ };
+
+ QVideoSurfaceFormat();
+ QVideoSurfaceFormat(
+ const QSize &size,
+ QVideoFrame::PixelFormat pixelFormat,
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle);
+ QVideoSurfaceFormat(const QVideoSurfaceFormat &format);
+ ~QVideoSurfaceFormat();
+
+ QVideoSurfaceFormat &operator =(const QVideoSurfaceFormat &format);
+
+ bool operator ==(const QVideoSurfaceFormat &format) const;
+ bool operator !=(const QVideoSurfaceFormat &format) const;
+
+ bool isValid() const;
+
+ QVideoFrame::PixelFormat pixelFormat() const;
+ QAbstractVideoBuffer::HandleType handleType() const;
+
+ QSize frameSize() const;
+ void setFrameSize(const QSize &size);
+ void setFrameSize(int width, int height);
+
+ int frameWidth() const;
+ int frameHeight() const;
+
+ QRect viewport() const;
+ void setViewport(const QRect &viewport);
+
+ Direction scanLineDirection() const;
+ void setScanLineDirection(Direction direction);
+
+ qreal frameRate() const;
+ void setFrameRate(qreal rate);
+
+ QSize pixelAspectRatio() const;
+ void setPixelAspectRatio(const QSize &ratio);
+ void setPixelAspectRatio(int width, int height);
+
+ YCbCrColorSpace yCbCrColorSpace() const;
+ void setYCbCrColorSpace(YCbCrColorSpace colorSpace);
+
+ QSize sizeHint() const;
+
+ QList<QByteArray> propertyNames() const;
+ QVariant property(const char *name) const;
+ void setProperty(const char *name, const QVariant &value);
+
+private:
+ QSharedDataPointer<QVideoSurfaceFormatPrivate> d;
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug, const QVideoSurfaceFormat &);
+#endif
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QVideoSurfaceFormat::Direction)
+Q_DECLARE_METATYPE(QVideoSurfaceFormat::YCbCrColorSpace)
+
+QT_END_HEADER
+
+#endif
+
diff --git a/src/multimediakit/video/video.pri b/src/multimediakit/video/video.pri
new file mode 100644
index 000000000..accaa3371
--- /dev/null
+++ b/src/multimediakit/video/video.pri
@@ -0,0 +1,22 @@
+
+INCLUDEPATH += video
+
+PUBLIC_HEADERS += \
+ video/qabstractvideobuffer.h \
+ video/qabstractvideosurface.h \
+ video/qvideoframe.h \
+ video/qvideosurfaceformat.h
+
+PRIVATE_HEADERS += \
+ video/qabstractvideobuffer_p.h \
+ video/qimagevideobuffer_p.h \
+ video/qmemoryvideobuffer_p.h
+
+SOURCES += \
+ video/qabstractvideobuffer.cpp \
+ video/qabstractvideosurface.cpp \
+ video/qimagevideobuffer.cpp \
+ video/qmemoryvideobuffer.cpp \
+ video/qvideoframe.cpp \
+ video/qvideosurfaceformat.cpp
+
diff --git a/src/plugins/audiocapture/audiocapture.pro b/src/plugins/audiocapture/audiocapture.pro
new file mode 100644
index 000000000..ceb554067
--- /dev/null
+++ b/src/plugins/audiocapture/audiocapture.pro
@@ -0,0 +1,25 @@
+load(qt_module)
+
+TARGET = qtmedia_audioengine
+QT += multimediakit-private
+PLUGIN_TYPE=mediaservice
+
+load(qt_plugin)
+DESTDIR = $$QT.multimediakit.plugins/$${PLUGIN_TYPE}
+
+# Input
+HEADERS += audioencodercontrol.h \
+ audiocontainercontrol.h \
+ audiomediarecordercontrol.h \
+ audioendpointselector.h \
+ audiocaptureservice.h \
+ audiocaptureserviceplugin.h \
+ audiocapturesession.h
+
+SOURCES += audioencodercontrol.cpp \
+ audiocontainercontrol.cpp \
+ audiomediarecordercontrol.cpp \
+ audioendpointselector.cpp \
+ audiocaptureservice.cpp \
+ audiocaptureserviceplugin.cpp \
+ audiocapturesession.cpp
diff --git a/src/plugins/audiocapture/audiocaptureservice.cpp b/src/plugins/audiocapture/audiocaptureservice.cpp
new file mode 100644
index 000000000..2859eb557
--- /dev/null
+++ b/src/plugins/audiocapture/audiocaptureservice.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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$
+** 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 "audiocaptureservice.h"
+#include "audiocapturesession.h"
+#include "audioendpointselector.h"
+#include "audioencodercontrol.h"
+#include "audiocontainercontrol.h"
+#include "audiomediarecordercontrol.h"
+
+AudioCaptureService::AudioCaptureService(QObject *parent):
+ QMediaService(parent)
+{
+ m_session = new AudioCaptureSession(this);
+ m_encoderControl = new AudioEncoderControl(m_session);
+ m_containerControl = new AudioContainerControl(m_session);
+ m_mediaControl = new AudioMediaRecorderControl(m_session);
+ m_endpointSelector = new AudioEndpointSelector(m_session);
+}
+
+AudioCaptureService::~AudioCaptureService()
+{
+ delete m_encoderControl;
+ delete m_containerControl;
+ delete m_endpointSelector;
+ delete m_mediaControl;
+ delete m_session;
+}
+
+QMediaControl *AudioCaptureService::requestControl(const char *name)
+{
+ if (qstrcmp(name,QMediaRecorderControl_iid) == 0)
+ return m_mediaControl;
+
+ if (qstrcmp(name,QAudioEncoderControl_iid) == 0)
+ return m_encoderControl;
+
+ if (qstrcmp(name,QAudioEndpointSelector_iid) == 0)
+ return m_endpointSelector;
+
+ if (qstrcmp(name,QMediaContainerControl_iid) == 0)
+ return m_containerControl;
+
+ return 0;
+}
+
+void AudioCaptureService::releaseControl(QMediaControl *control)
+{
+ Q_UNUSED(control)
+}
+
+
diff --git a/src/plugins/audiocapture/audiocaptureservice.h b/src/plugins/audiocapture/audiocaptureservice.h
new file mode 100644
index 000000000..22d70029d
--- /dev/null
+++ b/src/plugins/audiocapture/audiocaptureservice.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 AUDIOCAPTURESERVICE_H
+#define AUDIOCAPTURESERVICE_H
+
+#include <QtCore/qobject.h>
+
+#include "qmediaservice.h"
+
+class AudioCaptureSession;
+class AudioEncoderControl;
+class AudioContainerControl;
+class AudioMediaRecorderControl;
+class AudioEndpointSelector;
+
+QT_USE_NAMESPACE
+
+class AudioCaptureService : public QMediaService
+{
+ Q_OBJECT
+public:
+ AudioCaptureService(QObject *parent = 0);
+ ~AudioCaptureService();
+
+ QMediaControl *requestControl(const char *interface);
+ void releaseControl(QMediaControl *control);
+private:
+ AudioCaptureSession *m_session;
+ AudioEncoderControl *m_encoderControl;
+ AudioContainerControl *m_containerControl;
+ AudioEndpointSelector *m_endpointSelector;
+ AudioMediaRecorderControl *m_mediaControl;
+};
+
+#endif
diff --git a/src/plugins/audiocapture/audiocaptureserviceplugin.cpp b/src/plugins/audiocapture/audiocaptureserviceplugin.cpp
new file mode 100644
index 000000000..5ebaf12b9
--- /dev/null
+++ b/src/plugins/audiocapture/audiocaptureserviceplugin.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qstring.h>
+
+#include "audiocaptureserviceplugin.h"
+#include "audiocaptureservice.h"
+
+#include "qmediaserviceprovider.h"
+
+
+QStringList AudioCaptureServicePlugin::keys() const
+{
+ return QStringList() << QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE);
+}
+
+QMediaService* AudioCaptureServicePlugin::create(QString const& key)
+{
+ if (key == QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE))
+ return new AudioCaptureService;
+
+ return 0;
+}
+
+void AudioCaptureServicePlugin::release(QMediaService *service)
+{
+ delete service;
+}
+
+Q_EXPORT_PLUGIN2(qtmedia_audioengine, AudioCaptureServicePlugin);
+
diff --git a/src/plugins/audiocapture/audiocaptureserviceplugin.h b/src/plugins/audiocapture/audiocaptureserviceplugin.h
new file mode 100644
index 000000000..e244b9951
--- /dev/null
+++ b/src/plugins/audiocapture/audiocaptureserviceplugin.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** 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$
+** 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 AUDIOCAPTURESERVICEPLUGIN_H
+#define AUDIOCAPTURESERVICEPLUGIN_H
+
+#include "qmediaserviceproviderplugin.h"
+
+QT_USE_NAMESPACE
+
+class AudioCaptureServicePlugin : public QMediaServiceProviderPlugin
+{
+ Q_OBJECT
+
+public:
+ QStringList keys() const;
+ QMediaService* create(QString const& key);
+ void release(QMediaService *service);
+};
+
+#endif // AUDIOCAPTURESERVICEPLUGIN_H
diff --git a/src/plugins/audiocapture/audiocapturesession.cpp b/src/plugins/audiocapture/audiocapturesession.cpp
new file mode 100644
index 000000000..da6268adc
--- /dev/null
+++ b/src/plugins/audiocapture/audiocapturesession.cpp
@@ -0,0 +1,358 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qdebug.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qdir.h>
+#include <qaudiodeviceinfo.h>
+
+#include "qmediarecorder.h"
+
+#include "audiocapturesession.h"
+
+AudioCaptureSession::AudioCaptureSession(QObject *parent):
+ QObject(parent)
+{
+ m_deviceInfo = new QAudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice());
+ m_audioInput = 0;
+ m_position = 0;
+ m_state = QMediaRecorder::StoppedState;
+
+ m_format.setFrequency(8000);
+ m_format.setChannels(1);
+ m_format.setSampleSize(8);
+ m_format.setSampleType(QAudioFormat::UnSignedInt);
+ m_format.setCodec("audio/pcm");
+ wavFile = true;
+}
+
+AudioCaptureSession::~AudioCaptureSession()
+{
+ stop();
+
+ if(m_audioInput)
+ delete m_audioInput;
+}
+
+QAudioDeviceInfo* AudioCaptureSession::deviceInfo() const
+{
+ return m_deviceInfo;
+}
+
+QAudioFormat AudioCaptureSession::format() const
+{
+ return m_format;
+}
+
+bool AudioCaptureSession::isFormatSupported(const QAudioFormat &format) const
+{
+ if(m_deviceInfo) {
+ if(format.codec().contains(QLatin1String("audio/x-wav"))) {
+ QAudioFormat fmt = format;
+ fmt.setCodec("audio/pcm");
+ return m_deviceInfo->isFormatSupported(fmt);
+ } else
+ return m_deviceInfo->isFormatSupported(format);
+ }
+ return false;
+}
+
+bool AudioCaptureSession::setFormat(const QAudioFormat &format)
+{
+ if(m_deviceInfo) {
+
+ QAudioFormat fmt = format;
+
+ if(m_deviceInfo->isFormatSupported(fmt)) {
+ m_format = fmt;
+ if(m_audioInput) delete m_audioInput;
+ m_audioInput = 0;
+ QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
+ for(int i=0;i<devices.size();i++) {
+ if(qstrcmp(m_deviceInfo->deviceName().toLocal8Bit().constData(),
+ devices.at(i).deviceName().toLocal8Bit().constData()) == 0) {
+ m_audioInput = new QAudioInput(devices.at(i),m_format);
+ connect(m_audioInput,SIGNAL(stateChanged(QAudio::State)),this,SLOT(stateChanged(QAudio::State)));
+ connect(m_audioInput,SIGNAL(notify()),this,SLOT(notify()));
+ break;
+ }
+ }
+ } else {
+ m_format = m_deviceInfo->preferredFormat();
+ qWarning()<<"failed to setFormat using preferred...";
+ }
+ }
+ return false;
+}
+
+QStringList AudioCaptureSession::supportedContainers() const
+{
+ QStringList list;
+ if(m_deviceInfo) {
+ if (m_deviceInfo->supportedCodecs().size() > 0) {
+ list << "audio/x-wav";
+ list << "audio/pcm";
+ }
+ }
+ return list;
+}
+
+QString AudioCaptureSession::containerDescription(const QString &formatMimeType) const
+{
+ if(m_deviceInfo) {
+ if (formatMimeType.contains(QLatin1String("audio/pcm")))
+ return tr("RAW file format");
+ if (formatMimeType.contains(QLatin1String("audio/x-wav")))
+ return tr("WAV file format");
+ }
+ return QString();
+}
+
+void AudioCaptureSession::setContainerMimeType(const QString &formatMimeType)
+{
+ if (!formatMimeType.contains(QLatin1String("audio/x-wav")) &&
+ !formatMimeType.contains(QLatin1String("audio/pcm")) &&
+ !formatMimeType.isEmpty())
+ return;
+
+ if(m_deviceInfo) {
+ if (!m_deviceInfo->supportedCodecs().contains(QLatin1String("audio/pcm")))
+ return;
+
+ if (formatMimeType.isEmpty() || formatMimeType.contains(QLatin1String("audio/x-wav"))) {
+ wavFile = true;
+ m_format.setCodec("audio/pcm");
+ } else {
+ wavFile = false;
+ m_format.setCodec(formatMimeType);
+ }
+ }
+}
+
+QString AudioCaptureSession::containerMimeType() const
+{
+ if(wavFile)
+ return QString("audio/x-wav");
+
+ return QString("audio/pcm");
+}
+
+QUrl AudioCaptureSession::outputLocation() const
+{
+ return m_actualSink;
+}
+
+bool AudioCaptureSession::setOutputLocation(const QUrl& sink)
+{
+ m_sink = m_actualSink = sink;
+ return true;
+}
+
+qint64 AudioCaptureSession::position() const
+{
+ return m_position;
+}
+
+int AudioCaptureSession::state() const
+{
+ return int(m_state);
+}
+
+QDir AudioCaptureSession::defaultDir() const
+{
+ QStringList dirCandidates;
+
+#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
+ dirCandidates << QLatin1String("/home/user/MyDocs");
+#endif
+
+ dirCandidates << QDir::home().filePath("Documents");
+ dirCandidates << QDir::home().filePath("My Documents");
+ dirCandidates << QDir::homePath();
+ dirCandidates << QDir::currentPath();
+ dirCandidates << QDir::tempPath();
+
+ foreach (const QString &path, dirCandidates) {
+ QDir dir(path);
+ if (dir.exists() && QFileInfo(path).isWritable())
+ return dir;
+ }
+
+ return QDir();
+}
+
+QString AudioCaptureSession::generateFileName(const QDir &dir, const QString &ext) const
+{
+
+ int lastClip = 0;
+ foreach(QString fileName, dir.entryList(QStringList() << QString("clip_*.%1").arg(ext))) {
+ int imgNumber = fileName.mid(5, fileName.size()-6-ext.length()).toInt();
+ lastClip = qMax(lastClip, imgNumber);
+ }
+
+ QString name = QString("clip_%1.%2").arg(lastClip+1,
+ 4, //fieldWidth
+ 10,
+ QLatin1Char('0')).arg(ext);
+
+ return dir.absoluteFilePath(name);
+}
+
+void AudioCaptureSession::record()
+{
+ if(!m_audioInput) {
+ setFormat(m_format);
+ }
+
+ m_actualSink = m_sink;
+
+ if (m_actualSink.isEmpty()) {
+ QString ext = wavFile ? QLatin1String("wav") : QLatin1String("raw");
+ m_actualSink = generateFileName(defaultDir(), ext);
+ }
+
+ if(m_actualSink.toLocalFile().length() > 0)
+ file.setFileName(m_actualSink.toLocalFile());
+ else
+ file.setFileName(m_actualSink.toString());
+
+ if(m_audioInput) {
+ if(m_state == QMediaRecorder::StoppedState) {
+ if(file.open(QIODevice::WriteOnly)) {
+ memset(&header,0,sizeof(CombinedHeader));
+ memcpy(header.riff.descriptor.id,"RIFF",4);
+ header.riff.descriptor.size = 0xFFFFFFFF; // This should be updated on stop(), filesize-8
+ memcpy(header.riff.type,"WAVE",4);
+ memcpy(header.wave.descriptor.id,"fmt ",4);
+ header.wave.descriptor.size = 16;
+ header.wave.audioFormat = 1; // for PCM data
+ header.wave.numChannels = m_format.channels();
+ header.wave.sampleRate = m_format.frequency();
+ header.wave.byteRate = m_format.frequency()*m_format.channels()*m_format.sampleSize()/8;
+ header.wave.blockAlign = m_format.channels()*m_format.sampleSize()/8;
+ header.wave.bitsPerSample = m_format.sampleSize();
+ memcpy(header.data.descriptor.id,"data",4);
+ header.data.descriptor.size = 0xFFFFFFFF; // This should be updated on stop(),samples*channels*sampleSize/8
+ if (wavFile)
+ file.write((char*)&header,sizeof(CombinedHeader));
+
+ m_audioInput->start(qobject_cast<QIODevice*>(&file));
+ } else {
+ emit error(1,QString("can't open source, failed"));
+ m_state = QMediaRecorder::StoppedState;
+ emit stateChanged(m_state);
+ }
+ }
+ }
+
+ m_state = QMediaRecorder::RecordingState;
+}
+
+void AudioCaptureSession::pause()
+{
+ if(m_audioInput)
+ m_audioInput->stop();
+
+ m_state = QMediaRecorder::PausedState;
+}
+
+void AudioCaptureSession::stop()
+{
+ if(m_audioInput) {
+ m_audioInput->stop();
+ file.close();
+ if (wavFile) {
+ qint32 fileSize = file.size()-8;
+ file.open(QIODevice::ReadWrite | QIODevice::Unbuffered);
+ file.read((char*)&header,sizeof(CombinedHeader));
+ header.riff.descriptor.size = fileSize; // filesize-8
+ header.data.descriptor.size = fileSize-44; // samples*channels*sampleSize/8
+ file.seek(0);
+ file.write((char*)&header,sizeof(CombinedHeader));
+ file.close();
+ }
+ m_position = 0;
+ }
+ m_state = QMediaRecorder::StoppedState;
+}
+
+void AudioCaptureSession::stateChanged(QAudio::State state)
+{
+ switch(state) {
+ case QAudio::ActiveState:
+ emit stateChanged(QMediaRecorder::RecordingState);
+ break;
+ default:
+ if(!((m_state == QMediaRecorder::PausedState)||(m_state == QMediaRecorder::StoppedState)))
+ m_state = QMediaRecorder::StoppedState;
+
+ emit stateChanged(m_state);
+ break;
+ }
+}
+
+void AudioCaptureSession::notify()
+{
+ m_position += m_audioInput->notifyInterval();
+ emit positionChanged(m_position);
+}
+
+void AudioCaptureSession::setCaptureDevice(const QString &deviceName)
+{
+ m_captureDevice = deviceName;
+ if(m_deviceInfo)
+ delete m_deviceInfo;
+
+ m_deviceInfo = 0;
+
+ QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
+ for(int i = 0; i < devices.size(); i++) {
+ if(qstrcmp(m_captureDevice.toLocal8Bit().constData(),
+ devices.at(i).deviceName().toLocal8Bit().constData())==0){
+ m_deviceInfo = new QAudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice());
+ return;
+ }
+ }
+ m_deviceInfo = new QAudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice());
+}
+
+
+
diff --git a/src/plugins/audiocapture/audiocapturesession.h b/src/plugins/audiocapture/audiocapturesession.h
new file mode 100644
index 000000000..0ce139f9a
--- /dev/null
+++ b/src/plugins/audiocapture/audiocapturesession.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** 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$
+** 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 AUDIOCAPTURESESSION_H
+#define AUDIOCAPTURESESSION_H
+
+#include <QFile>
+#include <QUrl>
+#include <QDir>
+
+#include "audioencodercontrol.h"
+#include "audioendpointselector.h"
+#include "audiomediarecordercontrol.h"
+
+#include <qaudioformat.h>
+#include <qaudioinput.h>
+#include <qaudiodeviceinfo.h>
+
+QT_USE_NAMESPACE
+
+class AudioCaptureSession : public QObject
+{
+ Q_OBJECT
+
+public:
+ AudioCaptureSession(QObject *parent = 0);
+ ~AudioCaptureSession();
+
+ QAudioFormat format() const;
+ QAudioDeviceInfo* deviceInfo() const;
+ bool isFormatSupported(const QAudioFormat &format) const;
+ bool setFormat(const QAudioFormat &format);
+ QStringList supportedContainers() const;
+ QString containerMimeType() const;
+ void setContainerMimeType(const QString &formatMimeType);
+ QString containerDescription(const QString &formatMimeType) const;
+
+ QUrl outputLocation() const;
+ bool setOutputLocation(const QUrl& sink);
+ qint64 position() const;
+ int state() const;
+ void record();
+ void pause();
+ void stop();
+
+public slots:
+ void setCaptureDevice(const QString &deviceName);
+
+signals:
+ void stateChanged(QMediaRecorder::State state);
+ void positionChanged(qint64 position);
+ void error(int error, const QString &errorString);
+
+private slots:
+ void stateChanged(QAudio::State state);
+ void notify();
+
+private:
+ QDir defaultDir() const;
+ QString generateFileName(const QDir &dir, const QString &ext) const;
+
+ QFile file;
+ QString m_captureDevice;
+ QUrl m_sink;
+ QUrl m_actualSink;
+ QMediaRecorder::State m_state;
+ QAudioInput *m_audioInput;
+ QAudioDeviceInfo *m_deviceInfo;
+ QAudioFormat m_format;
+ qint64 m_position;
+ bool wavFile;
+
+ // WAV header stuff
+
+ struct chunk
+ {
+ char id[4];
+ quint32 size;
+ };
+
+ struct RIFFHeader
+ {
+ chunk descriptor;
+ char type[4];
+ };
+
+ struct WAVEHeader
+ {
+ chunk descriptor;
+ quint16 audioFormat; // PCM = 1
+ quint16 numChannels;
+ quint32 sampleRate;
+ quint32 byteRate;
+ quint16 blockAlign;
+ quint16 bitsPerSample;
+ };
+
+ struct DATAHeader
+ {
+ chunk descriptor;
+// quint8 data[];
+ };
+
+ struct CombinedHeader
+ {
+ RIFFHeader riff;
+ WAVEHeader wave;
+ DATAHeader data;
+ };
+
+ CombinedHeader header;
+};
+
+#endif
diff --git a/src/plugins/audiocapture/audiocontainercontrol.cpp b/src/plugins/audiocapture/audiocontainercontrol.cpp
new file mode 100644
index 000000000..454f43eda
--- /dev/null
+++ b/src/plugins/audiocapture/audiocontainercontrol.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "audiocontainercontrol.h"
+#include "audiocapturesession.h"
+
+AudioContainerControl::AudioContainerControl(QObject *parent)
+ :QMediaContainerControl(parent)
+{
+ m_session = qobject_cast<AudioCaptureSession*>(parent);
+}
+
+AudioContainerControl::~AudioContainerControl()
+{
+}
+
+QStringList AudioContainerControl::supportedContainers() const
+{
+ return m_session->supportedContainers();
+}
+
+QString AudioContainerControl::containerMimeType() const
+{
+ return m_session->containerMimeType();
+}
+
+void AudioContainerControl::setContainerMimeType(const QString &formatMimeType)
+{
+ m_session->setContainerMimeType(formatMimeType);
+}
+
+QString AudioContainerControl::containerDescription(const QString &formatMimeType) const
+{
+ return m_session->containerDescription(formatMimeType);
+}
+
diff --git a/src/plugins/audiocapture/audiocontainercontrol.h b/src/plugins/audiocapture/audiocontainercontrol.h
new file mode 100644
index 000000000..5c8d7b267
--- /dev/null
+++ b/src/plugins/audiocapture/audiocontainercontrol.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 AUDIOCONTAINERCONTROL_H
+#define AUDIOCONTAINERCONTROL_H
+
+#include "qmediacontainercontrol.h"
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+
+class AudioCaptureSession;
+
+QT_USE_NAMESPACE
+
+class AudioContainerControl : public QMediaContainerControl
+{
+ Q_OBJECT
+public:
+ AudioContainerControl(QObject *parent);
+ virtual ~AudioContainerControl();
+
+ QStringList supportedContainers() const;
+ QString containerMimeType() const;
+ void setContainerMimeType(const QString &formatMimeType);
+ QString containerDescription(const QString &formatMimeType) const;
+
+private:
+ AudioCaptureSession* m_session;
+};
+
+#endif
diff --git a/src/plugins/audiocapture/audioencodercontrol.cpp b/src/plugins/audiocapture/audioencodercontrol.cpp
new file mode 100644
index 000000000..888deac45
--- /dev/null
+++ b/src/plugins/audiocapture/audioencodercontrol.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** 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$
+** 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 "audioencodercontrol.h"
+#include "audiocapturesession.h"
+
+#include <qaudioformat.h>
+
+#include <QtCore/qdebug.h>
+
+AudioEncoderControl::AudioEncoderControl(QObject *parent)
+ :QAudioEncoderControl(parent)
+{
+ m_session = qobject_cast<AudioCaptureSession*>(parent);
+
+ QT_PREPEND_NAMESPACE(QAudioFormat) fmt;
+ fmt.setSampleSize(8);
+ fmt.setChannels(1);
+ fmt.setFrequency(8000);
+ fmt.setSampleType(QT_PREPEND_NAMESPACE(QAudioFormat)::SignedInt);
+ fmt.setCodec("audio/pcm");
+ fmt.setByteOrder(QAudioFormat::LittleEndian);
+ m_session->setFormat(fmt);
+
+ m_settings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding);
+ m_settings.setCodec("audio/pcm");
+ m_settings.setBitRate(8000);
+ m_settings.setChannelCount(1);
+ m_settings.setSampleRate(8000);
+ m_settings.setQuality(QtMultimediaKit::LowQuality);
+}
+
+AudioEncoderControl::~AudioEncoderControl()
+{
+}
+
+QStringList AudioEncoderControl::supportedAudioCodecs() const
+{
+ QStringList list;
+ if (m_session->supportedContainers().size() > 0)
+ list.append("audio/pcm");
+
+ return list;
+}
+
+QString AudioEncoderControl::codecDescription(const QString &codecName) const
+{
+ if (codecName.contains(QLatin1String("audio/pcm")))
+ return tr("PCM audio data");
+
+ return QString();
+}
+
+QStringList AudioEncoderControl::supportedEncodingOptions(const QString &codec) const
+{
+ Q_UNUSED(codec)
+
+ QStringList list;
+ return list;
+}
+
+QVariant AudioEncoderControl::encodingOption(const QString &codec, const QString &name) const
+{
+ Q_UNUSED(codec)
+ Q_UNUSED(name)
+
+ return QVariant();
+}
+
+void AudioEncoderControl::setEncodingOption(
+ const QString &codec, const QString &name, const QVariant &value)
+{
+ Q_UNUSED(value)
+ Q_UNUSED(codec)
+ Q_UNUSED(name)
+}
+
+QList<int> AudioEncoderControl::supportedSampleRates(const QAudioEncoderSettings &, bool *continuous) const
+{
+ if (continuous)
+ *continuous = false;
+
+ return m_session->deviceInfo()->supportedFrequencies();
+}
+
+QAudioEncoderSettings AudioEncoderControl::audioSettings() const
+{
+ return m_settings;
+}
+
+void AudioEncoderControl::setAudioSettings(const QAudioEncoderSettings &settings)
+{
+ QAudioFormat fmt = m_session->format();
+
+ if (settings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
+ if (settings.quality() == QtMultimediaKit::LowQuality) {
+ fmt.setSampleSize(8);
+ fmt.setChannels(1);
+ fmt.setFrequency(8000);
+ fmt.setSampleType(QAudioFormat::UnSignedInt);
+
+ } else if (settings.quality() == QtMultimediaKit::NormalQuality) {
+ fmt.setSampleSize(16);
+ fmt.setChannels(1);
+ fmt.setFrequency(22050);
+ fmt.setSampleType(QAudioFormat::SignedInt);
+
+ } else {
+ fmt.setSampleSize(16);
+ fmt.setChannels(1);
+ fmt.setFrequency(44100);
+ fmt.setSampleType(QAudioFormat::SignedInt);
+ }
+
+ } else {
+ fmt.setChannels(settings.channelCount());
+ fmt.setFrequency(settings.sampleRate());
+ if (settings.sampleRate() == 8000 && settings.bitRate() == 8000) {
+ fmt.setSampleType(QAudioFormat::UnSignedInt);
+ fmt.setSampleSize(8);
+ } else {
+ fmt.setSampleSize(16);
+ fmt.setSampleType(QAudioFormat::SignedInt);
+ }
+ }
+ fmt.setCodec("audio/pcm");
+
+ m_session->setFormat(fmt);
+ m_settings = settings;
+}
diff --git a/src/plugins/audiocapture/audioencodercontrol.h b/src/plugins/audiocapture/audioencodercontrol.h
new file mode 100644
index 000000000..09ac8b2b2
--- /dev/null
+++ b/src/plugins/audiocapture/audioencodercontrol.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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$
+** 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 AUDIOENCODERCONTROL_H
+#define AUDIOENCODERCONTROL_H
+
+#include "qaudioencodercontrol.h"
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+
+#include <qaudioformat.h>
+
+class AudioCaptureSession;
+
+QT_USE_NAMESPACE
+
+class AudioEncoderControl : public QAudioEncoderControl
+{
+ Q_OBJECT
+public:
+ AudioEncoderControl(QObject *parent);
+ virtual ~AudioEncoderControl();
+
+ QStringList supportedAudioCodecs() const;
+ QString codecDescription(const QString &codecName) const;
+ QList<int> supportedSampleRates(const QAudioEncoderSettings &, bool *continuous = 0) const;
+
+ QAudioEncoderSettings audioSettings() const;
+ void setAudioSettings(const QAudioEncoderSettings&);
+
+ QStringList supportedEncodingOptions(const QString &codec) const;
+ QVariant encodingOption(const QString &codec, const QString &name) const;
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
+
+private:
+ AudioCaptureSession* m_session;
+ QAudioEncoderSettings m_settings;
+};
+
+#endif
diff --git a/src/plugins/audiocapture/audioendpointselector.cpp b/src/plugins/audiocapture/audioendpointselector.cpp
new file mode 100644
index 000000000..dc7ca8e90
--- /dev/null
+++ b/src/plugins/audiocapture/audioendpointselector.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** 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$
+** 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 "audiocapturesession.h"
+#include "audioendpointselector.h"
+
+#include <qaudiodeviceinfo.h>
+
+
+AudioEndpointSelector::AudioEndpointSelector(QObject *parent)
+ :QAudioEndpointSelector(parent)
+{
+ m_session = qobject_cast<AudioCaptureSession*>(parent);
+
+ update();
+
+ m_audioInput = defaultEndpoint();
+}
+
+AudioEndpointSelector::~AudioEndpointSelector()
+{
+}
+
+QList<QString> AudioEndpointSelector::availableEndpoints() const
+{
+ return m_names;
+}
+
+QString AudioEndpointSelector::endpointDescription(const QString& name) const
+{
+ QString desc;
+
+ for(int i = 0; i < m_names.count(); i++) {
+ if (m_names.at(i).compare(name) == 0) {
+ desc = m_names.at(i);
+ break;
+ }
+ }
+ return desc;
+}
+
+QString AudioEndpointSelector::defaultEndpoint() const
+{
+ return QAudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice()).deviceName();
+}
+
+QString AudioEndpointSelector::activeEndpoint() const
+{
+ return m_audioInput;
+}
+
+void AudioEndpointSelector::setActiveEndpoint(const QString& name)
+{
+ if (m_audioInput.compare(name) != 0) {
+ m_audioInput = name;
+ m_session->setCaptureDevice(name);
+ emit activeEndpointChanged(name);
+ }
+}
+
+void AudioEndpointSelector::update()
+{
+ m_names.clear();
+ m_descriptions.clear();
+
+ QList<QAudioDeviceInfo> devices;
+ devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
+ for(int i = 0; i < devices.size(); ++i) {
+ m_names.append(devices.at(i).deviceName());
+ m_descriptions.append(devices.at(i).deviceName());
+ }
+}
diff --git a/src/plugins/audiocapture/audioendpointselector.h b/src/plugins/audiocapture/audioendpointselector.h
new file mode 100644
index 000000000..dda3c59c7
--- /dev/null
+++ b/src/plugins/audiocapture/audioendpointselector.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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$
+** 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 AUDIOENDPOINTSELECTOR_H
+#define AUDIOENDPOINTSELECTOR_H
+
+#include <QStringList>
+
+#include "qaudioendpointselector.h"
+
+class AudioCaptureSession;
+
+QT_USE_NAMESPACE
+
+class AudioEndpointSelector : public QAudioEndpointSelector
+{
+Q_OBJECT
+public:
+ AudioEndpointSelector(QObject *parent);
+ virtual ~AudioEndpointSelector();
+
+ QList<QString> availableEndpoints() const;
+ QString endpointDescription(const QString& name) const;
+ QString defaultEndpoint() const;
+ QString activeEndpoint() const;
+
+public Q_SLOTS:
+ void setActiveEndpoint(const QString& name);
+
+private:
+ void update();
+
+ QString m_audioInput;
+ QList<QString> m_names;
+ QList<QString> m_descriptions;
+ AudioCaptureSession* m_session;
+};
+
+#endif // AUDIOENDPOINTSELECTOR_H
diff --git a/src/plugins/audiocapture/audiomediarecordercontrol.cpp b/src/plugins/audiocapture/audiomediarecordercontrol.cpp
new file mode 100644
index 000000000..b1f550a04
--- /dev/null
+++ b/src/plugins/audiocapture/audiomediarecordercontrol.cpp
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** 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$
+** 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 "audiocapturesession.h"
+#include "audiomediarecordercontrol.h"
+
+#include <QtCore/qdebug.h>
+
+AudioMediaRecorderControl::AudioMediaRecorderControl(QObject *parent)
+ :QMediaRecorderControl(parent)
+{
+ m_session = qobject_cast<AudioCaptureSession*>(parent);
+ connect(m_session,SIGNAL(positionChanged(qint64)),this,SIGNAL(durationChanged(qint64)));
+ connect(m_session,SIGNAL(stateChanged(QMediaRecorder::State)),this,SIGNAL(stateChanged(QMediaRecorder::State)));
+ connect(m_session,SIGNAL(error(int,QString)),this,SIGNAL(error(int,QString)));
+}
+
+AudioMediaRecorderControl::~AudioMediaRecorderControl()
+{
+}
+
+QUrl AudioMediaRecorderControl::outputLocation() const
+{
+ return m_session->outputLocation();
+}
+
+bool AudioMediaRecorderControl::setOutputLocation(const QUrl& sink)
+{
+ return m_session->setOutputLocation(sink);
+}
+
+QMediaRecorder::State AudioMediaRecorderControl::state() const
+{
+ return (QMediaRecorder::State)m_session->state();
+}
+
+qint64 AudioMediaRecorderControl::duration() const
+{
+ return m_session->position();
+}
+
+void AudioMediaRecorderControl::record()
+{
+ m_session->record();
+}
+
+void AudioMediaRecorderControl::pause()
+{
+ m_session->stop();
+}
+
+void AudioMediaRecorderControl::stop()
+{
+ m_session->stop();
+}
+
+bool AudioMediaRecorderControl::isMuted() const
+{
+ return false;
+}
+
+void AudioMediaRecorderControl::setMuted(bool)
+{
+}
diff --git a/src/plugins/audiocapture/audiomediarecordercontrol.h b/src/plugins/audiocapture/audiomediarecordercontrol.h
new file mode 100644
index 000000000..a3528a875
--- /dev/null
+++ b/src/plugins/audiocapture/audiomediarecordercontrol.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** 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$
+** 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 AUDIOMEDIARECORDERCONTROL_H
+#define AUDIOMEDIARECORDERCONTROL_H
+
+#include <QtCore/qobject.h>
+
+#include "qmediarecorder.h"
+#include "qmediarecordercontrol.h"
+
+class AudioCaptureSession;
+
+QT_USE_NAMESPACE
+
+class AudioMediaRecorderControl : public QMediaRecorderControl
+{
+ Q_OBJECT
+public:
+ AudioMediaRecorderControl(QObject *parent = 0);
+ ~AudioMediaRecorderControl();
+
+ QUrl outputLocation() const;
+ bool setOutputLocation(const QUrl &sink);
+
+ QMediaRecorder::State state() const;
+
+ qint64 duration() const;
+
+ bool isMuted() const;
+
+ void applySettings() {}
+
+public slots:
+ void record();
+ void pause();
+ void stop();
+ void setMuted(bool);
+
+private:
+ AudioCaptureSession* m_session;
+};
+
+#endif
diff --git a/src/plugins/directshow/camera/camera.pri b/src/plugins/directshow/camera/camera.pri
new file mode 100644
index 000000000..42f5999a2
--- /dev/null
+++ b/src/plugins/directshow/camera/camera.pri
@@ -0,0 +1,31 @@
+INCLUDEPATH += $$PWD
+
+DEFINES += QMEDIA_DIRECTSHOW_CAMERA
+
+win32-g++: DEFINES += QT_NO_WMSDK
+
+win32: DEFINES += _CRT_SECURE_NO_WARNINGS
+
+HEADERS += \
+ $$PWD/dscameraservice.h \
+ $$PWD/dscameracontrol.h \
+ $$PWD/dsvideorenderer.h \
+ $$PWD/dsvideodevicecontrol.h \
+ $$PWD/dsimagecapturecontrol.h \
+ $$PWD/dscamerasession.h \
+ $$PWD/dsvideowidgetcontrol.h \
+ $$PWD/dscameraservice.h \
+ $$PWD/directshowglobal.h
+
+
+SOURCES += \
+ $$PWD/dscameraservice.cpp \
+ $$PWD/dscameracontrol.cpp \
+ $$PWD/dsvideorenderer.cpp \
+ $$PWD/dsvideodevicecontrol.cpp \
+ $$PWD/dsimagecapturecontrol.cpp \
+ $$PWD/dscamerasession.cpp \
+ $$PWD/dsvideowidgetcontrol.cpp
+
+INCLUDEPATH += $(DXSDK_DIR)/include
+LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32
diff --git a/src/plugins/directshow/camera/directshowglobal.h b/src/plugins/directshow/camera/directshowglobal.h
new file mode 100644
index 000000000..76c143798
--- /dev/null
+++ b/src/plugins/directshow/camera/directshowglobal.h
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** 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$
+** 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 DIRECTSHOWGLOBAL_H
+#define DIRECTSHOWGLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#include <dshow.h>
+
+DEFINE_GUID(MEDIASUBTYPE_I420,
+ 0x30323449,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71);
+
+extern const GUID MEDIASUBTYPE_RGB24;
+extern const GUID MEDIASUBTYPE_RGB32;
+extern const GUID MEDIASUBTYPE_YUY2;
+extern const GUID MEDIASUBTYPE_MJPG;
+extern const GUID MEDIASUBTYPE_RGB555;
+extern const GUID MEDIASUBTYPE_YVU9;
+extern const GUID MEDIASUBTYPE_UYVY;
+extern const GUID PIN_CATEGORY_CAPTURE;
+extern const GUID PIN_CATEGORY_PREVIEW;
+
+extern const IID IID_IPropertyBag;
+extern const IID IID_ISampleGrabber;
+extern const IID IID_ICaptureGraphBuilder2;
+extern const IID IID_IAMStreamConfig;
+
+
+extern const CLSID CLSID_CVidCapClassManager;
+extern const CLSID CLSID_VideoInputDeviceCategory;
+extern const CLSID CLSID_SampleGrabber;
+extern const CLSID CLSID_CaptureGraphBuilder2;
+
+#define SAFE_RELEASE(x) { if(x) x->Release(); x = NULL; }
+
+typedef struct IFileSinkFilter *LPFILESINKFILTER;
+typedef struct IAMCopyCaptureFileProgress *LPAMCOPYCAPTUREFILEPROGRESS;
+
+#ifndef __ICaptureGraphBuilder2_INTERFACE_DEFINED__
+#define __ICaptureGraphBuilder2_INTERFACE_DEFINED__
+struct ICaptureGraphBuilder2 : public IUnknown
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE SetFiltergraph(
+ /* [in] */ IGraphBuilder *pfg) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFiltergraph(
+ /* [out] */ IGraphBuilder **ppfg) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetOutputFileName(
+ /* [in] */ const GUID *pType,
+ /* [in] */ LPCOLESTR lpstrFile,
+ /* [out] */ IBaseFilter **ppf,
+ /* [out] */ IFileSinkFilter **ppSink) = 0;
+
+ virtual /* [local] */ HRESULT STDMETHODCALLTYPE FindInterface(
+ /* [in] */ const GUID *pCategory,
+ /* [in] */ const GUID *pType,
+ /* [in] */ IBaseFilter *pf,
+ /* [in] */ REFIID riid,
+ /* [out] */ void **ppint) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RenderStream(
+ /* [in] */ const GUID *pCategory,
+ /* [in] */ const GUID *pType,
+ /* [in] */ IUnknown *pSource,
+ /* [in] */ IBaseFilter *pfCompressor,
+ /* [in] */ IBaseFilter *pfRenderer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ControlStream(
+ /* [in] */ const GUID *pCategory,
+ /* [in] */ const GUID *pType,
+ /* [in] */ IBaseFilter *pFilter,
+ /* [in] */ REFERENCE_TIME *pstart,
+ /* [in] */ REFERENCE_TIME *pstop,
+ /* [in] */ WORD wStartCookie,
+ /* [in] */ WORD wStopCookie) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE AllocCapFile(
+ /* [in] */ LPCOLESTR lpstr,
+ /* [in] */ DWORDLONG dwlSize) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CopyCaptureFile(
+ /* [in] */ LPOLESTR lpwstrOld,
+ /* [in] */ LPOLESTR lpwstrNew,
+ /* [in] */ int fAllowEscAbort,
+ /* [in] */ IAMCopyCaptureFileProgress *pCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FindPin(
+ /* [in] */ IUnknown *pSource,
+ /* [in] */ PIN_DIRECTION pindir,
+ /* [in] */ const GUID *pCategory,
+ /* [in] */ const GUID *pType,
+ /* [in] */ BOOL fUnconnected,
+ /* [in] */ int num,
+ /* [out] */ IPin **ppPin) = 0;
+
+};
+#endif
+
+#ifndef __IAMStreamConfig_INTERFACE_DEFINED__
+#define __IAMStreamConfig_INTERFACE_DEFINED__
+struct IAMStreamConfig : public IUnknown
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE SetFormat(
+ /* [in] */ AM_MEDIA_TYPE *pmt) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFormat(
+ /* [out] */ AM_MEDIA_TYPE **ppmt) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(
+ /* [out] */ int *piCount,
+ /* [out] */ int *piSize) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetStreamCaps(
+ /* [in] */ int iIndex,
+ /* [out] */ AM_MEDIA_TYPE **ppmt,
+ /* [out] */ BYTE *pSCC) = 0;
+
+};
+#endif
+
+#ifndef __IErrorLog_INTERFACE_DEFINED__
+#define __IErrorLog_INTERFACE_DEFINED__
+struct IErrorLog : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE AddError(
+ /* [in] */ LPCOLESTR pszPropName,
+ /* [in] */ EXCEPINFO *pExcepInfo) = 0;
+
+ };
+#endif
+
+#ifndef __IPropertyBag_INTERFACE_DEFINED__
+#define __IPropertyBag_INTERFACE_DEFINED__
+struct IPropertyBag : public IUnknown
+{
+public:
+ virtual /* [local] */ HRESULT STDMETHODCALLTYPE Read(
+ /* [in] */ LPCOLESTR pszPropName,
+ /* [out][in] */ VARIANT *pVar,
+ /* [in] */ IErrorLog *pErrorLog) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Write(
+ /* [in] */ LPCOLESTR pszPropName,
+ /* [in] */ VARIANT *pVar) = 0;
+
+};
+#endif
+
+typedef struct IMediaSample *LPMEDIASAMPLE;
+
+EXTERN_C const IID IID_ISampleGrabberCB;
+
+#ifndef __ISampleGrabberCB_INTERFACE_DEFINED__
+#define __ISampleGrabberCB_INTERFACE_DEFINED__
+
+#undef INTERFACE
+#define INTERFACE ISampleGrabberCB
+DECLARE_INTERFACE_(ISampleGrabberCB, IUnknown)
+{
+// STDMETHOD(QueryInterface) (THIS_ const GUID *, void **) PURE;
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, void **) PURE;
+ STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG, Release) (THIS) PURE;
+ STDMETHOD_(HRESULT, SampleCB) (THIS_ double, LPMEDIASAMPLE) PURE;
+ STDMETHOD_(HRESULT, BufferCB) (THIS_ double, BYTE *, long) PURE;
+};
+#undef INTERFACE
+
+#endif
+
+
+#ifndef __ISampleGrabber_INTERFACE_DEFINED__
+#define __ISampleGrabber_INTERFACE_DEFINED__
+
+#define INTERFACE ISampleGrabber
+DECLARE_INTERFACE_(ISampleGrabber,IUnknown)
+{
+ STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ STDMETHOD(SetOneShot)(THIS_ BOOL) PURE;
+ STDMETHOD(SetMediaType)(THIS_ const AM_MEDIA_TYPE*) PURE;
+ STDMETHOD(GetConnectedMediaType)(THIS_ AM_MEDIA_TYPE*) PURE;
+ STDMETHOD(SetBufferSamples)(THIS_ BOOL) PURE;
+ STDMETHOD(GetCurrentBuffer)(THIS_ long*,long*) PURE;
+ STDMETHOD(GetCurrentSample)(THIS_ IMediaSample**) PURE;
+ STDMETHOD(SetCallback)(THIS_ ISampleGrabberCB *,long) PURE;
+};
+#undef INTERFACE
+#endif
+
+
+#endif
diff --git a/src/plugins/directshow/camera/dscameracontrol.cpp b/src/plugins/directshow/camera/dscameracontrol.cpp
new file mode 100644
index 000000000..b09064c2b
--- /dev/null
+++ b/src/plugins/directshow/camera/dscameracontrol.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <QtCore/qdebug.h>
+
+#include "dscameracontrol.h"
+#include "dscameraservice.h"
+#include "dscamerasession.h"
+
+QT_BEGIN_NAMESPACE
+
+DSCameraControl::DSCameraControl(QObject *parent)
+ :QCameraControl(parent), m_captureMode(QCamera::CaptureStillImage)
+{
+ m_session = qobject_cast<DSCameraSession*>(parent);
+ connect(m_session, SIGNAL(stateChanged(QCamera::State)),this, SIGNAL(stateChanged(QCamera::State)));
+}
+
+DSCameraControl::~DSCameraControl()
+{
+}
+
+void DSCameraControl::setState(QCamera::State state)
+{
+ switch (state) {
+ case QCamera::ActiveState:
+ start();
+ break;
+ case QCamera::UnloadedState: /* fall through */
+ case QCamera::LoadedState:
+ stop();
+ break;
+ }
+}
+
+bool DSCameraControl::isCaptureModeSupported(QCamera::CaptureMode mode) const
+{
+ bool bCaptureSupported = false;
+ switch (mode) {
+ case QCamera::CaptureStillImage:
+ bCaptureSupported = true;
+ break;
+ case QCamera::CaptureVideo:
+ bCaptureSupported = false;
+ break;
+ }
+ return bCaptureSupported;
+}
+
+void DSCameraControl::start()
+{
+ m_session->record();
+}
+
+void DSCameraControl::stop()
+{
+ m_session->stop();
+}
+
+QCamera::State DSCameraControl::state() const
+{
+ return (QCamera::State)m_session->state();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/directshow/camera/dscameracontrol.h b/src/plugins/directshow/camera/dscameracontrol.h
new file mode 100644
index 000000000..9b20563d2
--- /dev/null
+++ b/src/plugins/directshow/camera/dscameracontrol.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** 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 DSCAMERACONTROL_H
+#define DSCAMERACONTROL_H
+
+#include <QtCore/qobject.h>
+#include <qcameracontrol.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class DSCameraService;
+class DSCameraSession;
+
+
+class DSCameraControl : public QCameraControl
+{
+ Q_OBJECT
+public:
+ DSCameraControl(QObject *parent = 0);
+ ~DSCameraControl();
+
+ void start();
+ void stop();
+ QCamera::State state() const;
+
+ QCamera::CaptureMode captureMode() const { return m_captureMode; }
+ void setCaptureMode(QCamera::CaptureMode mode)
+ {
+ if (m_captureMode != mode) {
+ m_captureMode = mode;
+ emit captureModeChanged(mode);
+ }
+ }
+
+ void setState(QCamera::State state);
+
+ QCamera::Status status() const { return QCamera::UnavailableStatus; }
+ bool isCaptureModeSupported(QCamera::CaptureMode mode) const;
+ bool canChangeProperty(PropertyChangeType /* changeType */, QCamera::Status /* status */) const {return false; }
+
+private:
+ DSCameraSession *m_session;
+ DSCameraService *m_service;
+ QCamera::CaptureMode m_captureMode;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
+
+
diff --git a/src/plugins/directshow/camera/dscameraservice.cpp b/src/plugins/directshow/camera/dscameraservice.cpp
new file mode 100644
index 000000000..9d73da02c
--- /dev/null
+++ b/src/plugins/directshow/camera/dscameraservice.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** 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 <QtCore/qvariant.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/qwidget.h>
+#include <QVideoWidgetControl.h>
+
+
+#include "dscameraservice.h"
+#include "dscameracontrol.h"
+#include "dscamerasession.h"
+#include "dsvideorenderer.h"
+#include "dsvideodevicecontrol.h"
+#include "dsimagecapturecontrol.h"
+#include "dsvideowidgetcontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+DSCameraService::DSCameraService(QObject *parent):
+ QMediaService(parent)
+{
+ m_session = new DSCameraSession(this);
+
+ m_control = new DSCameraControl(m_session);
+
+ m_videoDevice = new DSVideoDeviceControl(m_session);
+
+ m_videoRenderer = new DSVideoRendererControl(m_session, this);
+
+ m_imageCapture = new DSImageCaptureControl(m_session);
+
+ m_viewFinderWidget = new DSVideoWidgetControl(m_session);
+
+ m_device = QByteArray("default");
+}
+
+DSCameraService::~DSCameraService()
+{
+ delete m_control;
+ delete m_videoDevice;
+ delete m_videoRenderer;
+ delete m_imageCapture;
+ delete m_viewFinderWidget;
+ delete m_session;
+}
+
+QMediaControl* DSCameraService::requestControl(const char *name)
+{
+ if(qstrcmp(name,QCameraControl_iid) == 0)
+ return m_control;
+
+ if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
+ return m_imageCapture;
+
+ if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
+ if (m_viewFinderWidget) {
+ return m_viewFinderWidget;
+ }
+ }
+
+ if(qstrcmp(name,QVideoRendererControl_iid) == 0)
+ return m_videoRenderer;
+
+ if(qstrcmp(name,QVideoDeviceControl_iid) == 0)
+ return m_videoDevice;
+
+ return 0;
+}
+
+void DSCameraService::releaseControl(QMediaControl *control)
+{
+ // Implemented as a singleton, so we do nothing.
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/directshow/camera/dscameraservice.h b/src/plugins/directshow/camera/dscameraservice.h
new file mode 100644
index 000000000..e8a9450fb
--- /dev/null
+++ b/src/plugins/directshow/camera/dscameraservice.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** 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 DSCAMERASERVICE_H
+#define DSCAMERASERVICE_H
+
+#include <QtCore/qobject.h>
+
+#include <qmediaservice.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class DSCameraControl;
+class DSCameraSession;
+class DSVideoOutputControl;
+class DSVideoDeviceControl;
+class DSVideoRendererControl;
+class DSImageCaptureControl;
+class DSVideoWidgetControl;
+
+
+class DSCameraService : public QMediaService
+{
+ Q_OBJECT
+
+public:
+ DSCameraService(QObject *parent = 0);
+ ~DSCameraService();
+
+ virtual QMediaControl* requestControl(const char *name);
+ virtual void releaseControl(QMediaControl *control);
+
+private:
+ DSCameraControl *m_control;
+ DSCameraSession *m_session;
+ DSVideoOutputControl *m_videoOutput;
+ DSVideoWidgetControl *m_viewFinderWidget;
+ DSVideoDeviceControl *m_videoDevice;
+ DSVideoRendererControl *m_videoRenderer;
+ DSImageCaptureControl *m_imageCapture;
+ QByteArray m_device;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp
new file mode 100644
index 000000000..a08fb318f
--- /dev/null
+++ b/src/plugins/directshow/camera/dscamerasession.cpp
@@ -0,0 +1,1160 @@
+/****************************************************************************
+**
+** 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 <QtCore/qdebug.h>
+#include <QWidget>
+#include <QFile>
+#include <QtMultimedia/qabstractvideobuffer.h>
+#include <QtMultimedia/qvideosurfaceformat.h>
+
+#include "dscamerasession.h"
+#include "dsvideorenderer.h"
+#include "directshowglobal.h"
+
+QT_BEGIN_NAMESPACE
+
+// If frames come in quicker than we display them, we allow the queue to build
+// up to this number before we start dropping them.
+const int LIMIT_FRAME = 5;
+
+namespace {
+// DirectShow helper implementation
+void _FreeMediaType(AM_MEDIA_TYPE& mt)
+{
+ if (mt.cbFormat != 0) {
+ CoTaskMemFree((PVOID)mt.pbFormat);
+ mt.cbFormat = 0;
+ mt.pbFormat = NULL;
+ }
+ if (mt.pUnk != NULL) {
+ // pUnk should not be used.
+ mt.pUnk->Release();
+ mt.pUnk = NULL;
+ }
+}
+
+} // end namespace
+
+class SampleGrabberCallbackPrivate : public ISampleGrabberCB
+{
+public:
+ STDMETHODIMP_(ULONG) AddRef() { return 1; }
+ STDMETHODIMP_(ULONG) Release() { return 2; }
+
+ STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject)
+ {
+ if (NULL == ppvObject)
+ return E_POINTER;
+ if (riid == IID_IUnknown /*__uuidof(IUnknown) */ ) {
+ *ppvObject = static_cast<IUnknown*>(this);
+ return S_OK;
+ }
+ if (riid == IID_ISampleGrabberCB /*__uuidof(ISampleGrabberCB)*/ ) {
+ *ppvObject = static_cast<ISampleGrabberCB*>(this);
+ return S_OK;
+ }
+ return E_NOTIMPL;
+ }
+
+ STDMETHODIMP SampleCB(double Time, IMediaSample *pSample)
+ {
+ return E_NOTIMPL;
+ }
+
+ STDMETHODIMP BufferCB(double Time, BYTE *pBuffer, long BufferLen)
+ {
+ if (!cs || active) {
+ return S_OK;
+ }
+
+ if ((cs->StillMediaType.majortype != MEDIATYPE_Video) ||
+ (cs->StillMediaType.formattype != FORMAT_VideoInfo) ||
+ (cs->StillMediaType.cbFormat < sizeof(VIDEOINFOHEADER))) {
+ return VFW_E_INVALIDMEDIATYPE;
+ }
+
+ active = true;
+
+ if(toggle == true) {
+ toggle = false;
+ }
+ else {
+ toggle = true;
+ }
+
+ if(toggle) {
+ active = false;
+ return S_OK;
+ }
+
+ bool check = false;
+ cs->mutex.lock();
+
+ if (cs->frames.size() > LIMIT_FRAME) {
+ check = true;
+ }
+
+ if (check) {
+ cs->mutex.unlock();
+ // Frames building up. We're going to drop some here
+ Sleep(100);
+ active = false;
+ return S_OK;
+ }
+ cs->mutex.unlock();
+
+ unsigned char* vidData = new unsigned char[BufferLen];
+ memcpy(vidData, pBuffer, BufferLen);
+
+ cs->mutex.lock();
+
+ video_buffer* buf = new video_buffer;
+ buf->buffer = vidData;
+ buf->length = BufferLen;
+ buf->time = (qint64)Time;
+
+ cs->frames.append(buf);
+
+ cs->mutex.unlock();
+
+ QMetaObject::invokeMethod(cs, "captureFrame", Qt::QueuedConnection);
+
+ active = false;
+
+ return S_OK;
+ }
+
+ DSCameraSession* cs;
+ bool active;
+ bool toggle;
+};
+
+
+DSCameraSession::DSCameraSession(QObject *parent)
+ : QObject(parent)
+ ,m_currentImageId(0)
+{
+ pBuild = NULL;
+ pGraph = NULL;
+ pCap = NULL;
+ pSG_Filter = NULL;
+ pSG = NULL;
+
+ opened = false;
+ available = false;
+ resolutions.clear();
+ m_state = QCamera::UnloadedState;
+ m_device = "default";
+
+ StillCapCB = new SampleGrabberCallbackPrivate;
+ StillCapCB->cs = this;
+ StillCapCB->active = false;
+ StillCapCB->toggle = false;
+
+ m_output = 0;
+ m_surface = 0;
+ m_windowSize = QSize(320,240);
+ pixelF = QVideoFrame::Format_RGB24;
+ actualFormat = QVideoSurfaceFormat(m_windowSize,pixelF);
+
+ graph = false;
+ active = false;
+
+ ::CoInitialize(NULL);
+}
+
+DSCameraSession::~DSCameraSession()
+{
+ if (opened) {
+ closeStream();
+ }
+
+ CoUninitialize();
+
+ SAFE_RELEASE(pCap);
+ SAFE_RELEASE(pSG_Filter);
+ SAFE_RELEASE(pGraph);
+ SAFE_RELEASE(pBuild);
+
+ if (StillCapCB) {
+ delete StillCapCB;
+ }
+}
+
+int DSCameraSession::captureImage(const QString &fileName)
+{
+ emit readyForCaptureChanged(false);
+
+ // We're going to do this in one big synchronous call
+ m_currentImageId++;
+ if (fileName.isEmpty()) {
+ m_snapshot = "img.jpg";
+ } else {
+ m_snapshot = fileName;
+ }
+
+ if (!active) {
+ startStream();
+ }
+
+ return m_currentImageId;
+}
+
+void DSCameraSession::setSurface(QAbstractVideoSurface* surface)
+{
+ m_surface = surface;
+}
+
+bool DSCameraSession::deviceReady()
+{
+ return available;
+}
+
+bool DSCameraSession::pictureInProgress()
+{
+ return m_snapshot.isEmpty();
+}
+
+int DSCameraSession::framerate() const
+{
+ return -1;
+}
+
+void DSCameraSession::setFrameRate(int rate)
+{
+ Q_UNUSED(rate)
+}
+
+int DSCameraSession::brightness() const
+{
+ return -1;
+}
+
+void DSCameraSession::setBrightness(int b)
+{
+ Q_UNUSED(b)
+}
+
+int DSCameraSession::contrast() const
+{
+ return -1;
+}
+
+void DSCameraSession::setContrast(int c)
+{
+ Q_UNUSED(c)
+}
+
+int DSCameraSession::saturation() const
+{
+ return -1;
+}
+
+void DSCameraSession::setSaturation(int s)
+{
+ Q_UNUSED(s)
+}
+
+int DSCameraSession::hue() const
+{
+ return -1;
+}
+
+void DSCameraSession::setHue(int h)
+{
+ Q_UNUSED(h)
+}
+
+int DSCameraSession::sharpness() const
+{
+ return -1;
+}
+
+void DSCameraSession::setSharpness(int s)
+{
+ Q_UNUSED(s)
+}
+
+int DSCameraSession::zoom() const
+{
+ return -1;
+}
+
+void DSCameraSession::setZoom(int z)
+{
+ Q_UNUSED(z)
+}
+
+bool DSCameraSession::backlightCompensation() const
+{
+ return false;
+}
+
+void DSCameraSession::setBacklightCompensation(bool b)
+{
+ Q_UNUSED(b)
+}
+
+int DSCameraSession::whitelevel() const
+{
+ return -1;
+}
+
+void DSCameraSession::setWhitelevel(int w)
+{
+ Q_UNUSED(w)
+}
+
+int DSCameraSession::rotation() const
+{
+ return 0;
+}
+
+void DSCameraSession::setRotation(int r)
+{
+ Q_UNUSED(r)
+}
+
+bool DSCameraSession::flash() const
+{
+ return false;
+}
+
+void DSCameraSession::setFlash(bool f)
+{
+ Q_UNUSED(f)
+}
+
+bool DSCameraSession::autofocus() const
+{
+ return false;
+}
+
+void DSCameraSession::setAutofocus(bool f)
+{
+ Q_UNUSED(f)
+}
+
+QSize DSCameraSession::frameSize() const
+{
+ return m_windowSize;
+}
+
+void DSCameraSession::setFrameSize(const QSize& s)
+{
+ if (supportedResolutions(pixelF).contains(s))
+ m_windowSize = s;
+ else
+ qWarning() << "frame size if not supported for current pixel format, no change";
+}
+
+void DSCameraSession::setDevice(const QString &device)
+{
+ if(opened)
+ stopStream();
+
+ if(graph) {
+ SAFE_RELEASE(pCap);
+ SAFE_RELEASE(pSG_Filter);
+ SAFE_RELEASE(pGraph);
+ SAFE_RELEASE(pBuild);
+ }
+
+ available = false;
+ m_state = QCamera::LoadedState;
+
+ 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));
+ if(SUCCEEDED(hr)) {
+ // Create the enumerator for the video capture category
+ hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
+ if (S_OK == hr) {
+ pEnum->Reset();
+ // go through and find all video capture devices
+ IMoniker* pMoniker = NULL;
+ while(pEnum->Next(1, &pMoniker, NULL) == S_OK) {
+ IPropertyBag *pPropBag;
+ hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
+ (void**)(&pPropBag));
+ if(FAILED(hr)) {
+ pMoniker->Release();
+ continue; // skip this one
+ }
+ // Find the description
+ WCHAR str[120];
+ VARIANT varName;
+ varName.vt = VT_BSTR;
+ hr = pPropBag->Read(L"Description", &varName, 0);
+ if(FAILED(hr))
+ hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+ if(SUCCEEDED(hr)) {
+ wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
+ QString temp(QString::fromUtf16((unsigned short*)str));
+ if(temp.contains(device)) {
+ available = true;
+ }
+ }
+ pPropBag->Release();
+ pMoniker->Release();
+ }
+ pEnum->Release();
+ }
+ pDevEnum->Release();
+ }
+ CoUninitialize();
+
+ if(available) {
+ m_device = QByteArray(device.toLocal8Bit().constData());
+ graph = createFilterGraph();
+ if(!graph)
+ available = false;
+ }
+}
+
+QList<QVideoFrame::PixelFormat> DSCameraSession::supportedPixelFormats()
+{
+ return types;
+}
+
+QVideoFrame::PixelFormat DSCameraSession::pixelFormat() const
+{
+ return pixelF;
+}
+
+void DSCameraSession::setPixelFormat(QVideoFrame::PixelFormat fmt)
+{
+ pixelF = fmt;
+}
+
+QList<QSize> DSCameraSession::supportedResolutions(QVideoFrame::PixelFormat format)
+{
+ if (!resolutions.contains(format))
+ return QList<QSize>();
+ return resolutions.value(format);
+}
+
+bool DSCameraSession::setOutputLocation(const QUrl &sink)
+{
+ m_sink = sink;
+
+ return true;
+}
+
+QUrl DSCameraSession::outputLocation() const
+{
+ return m_sink;
+}
+
+qint64 DSCameraSession::position() const
+{
+ return timeStamp.elapsed();
+}
+
+int DSCameraSession::state() const
+{
+ return int(m_state);
+}
+
+void DSCameraSession::record()
+{
+ if(opened) {
+ return;
+ }
+
+ if(m_surface) {
+ bool match = false;
+
+ if (!m_surface->isFormatSupported(actualFormat)) {
+ QList<QVideoFrame::PixelFormat> fmts;
+ foreach(QVideoFrame::PixelFormat f, types) {
+ if (fmts.contains(f)) {
+ match = true;
+ pixelF = f;
+ actualFormat = QVideoSurfaceFormat(m_windowSize,pixelF);
+ break;
+ }
+ }
+ }
+ if (!m_surface->isFormatSupported(actualFormat) && !match) {
+ // fallback
+ if (types.contains(QVideoFrame::Format_RGB24)) {
+ // get RGB24 from camera and convert to RGB32 for surface!
+ pixelF = QVideoFrame::Format_RGB32;
+ actualFormat = QVideoSurfaceFormat(m_windowSize,pixelF);
+ }
+ }
+
+ if (m_surface->isFormatSupported(actualFormat)) {
+ m_surface->start(actualFormat);
+ m_state = QCamera::ActiveState;
+ emit stateChanged(QCamera::ActiveState);
+ } else {
+ qWarning() << "surface doesn't support camera format, cant start";
+ m_state = QCamera::LoadedState;
+ emit stateChanged(QCamera::LoadedState);
+ return;
+ }
+ } else {
+ qWarning() << "no video surface, cant start";
+ m_state = QCamera::LoadedState;
+ emit stateChanged(QCamera::LoadedState);
+ return;
+ }
+
+ opened = startStream();
+
+ if (!opened) {
+ qWarning() << "Stream did not open";
+ m_state = QCamera::LoadedState;
+ emit stateChanged(QCamera::LoadedState);
+ }
+}
+
+void DSCameraSession::pause()
+{
+ suspendStream();
+}
+
+void DSCameraSession::stop()
+{
+ if(!opened) {
+ return;
+ }
+
+ stopStream();
+ opened = false;
+ m_state = QCamera::LoadedState;
+ emit stateChanged(QCamera::LoadedState);
+}
+
+void DSCameraSession::captureFrame()
+{
+ if(m_surface && frames.count() > 0) {
+
+ QImage image;
+
+ if(pixelF == QVideoFrame::Format_RGB24) {
+
+ mutex.lock();
+
+ image = QImage(frames.at(0)->buffer,m_windowSize.width(),m_windowSize.height(),
+ QImage::Format_RGB888).rgbSwapped().mirrored(true);
+
+ QVideoFrame frame(image);
+ frame.setStartTime(frames.at(0)->time);
+
+ mutex.unlock();
+
+ m_surface->present(frame);
+
+ } else if (pixelF == QVideoFrame::Format_RGB32) {
+
+ mutex.lock();
+
+ image = QImage(frames.at(0)->buffer,m_windowSize.width(),m_windowSize.height(),
+ QImage::Format_RGB888).rgbSwapped().mirrored(true);
+
+ QVideoFrame frame(image.convertToFormat(QImage::Format_RGB32));
+ frame.setStartTime(frames.at(0)->time);
+
+ mutex.unlock();
+
+ m_surface->present(frame);
+
+ } else {
+ qWarning() << "TODO:captureFrame() format =" << pixelF;
+ }
+
+ if (m_snapshot.length() > 0) {
+ emit imageCaptured(m_currentImageId, image);
+ image.save(m_snapshot,"JPG");
+ emit imageSaved(m_currentImageId, m_snapshot);
+ m_snapshot.clear();
+ emit readyForCaptureChanged(true);
+ }
+
+ mutex.lock();
+ if (frames.isEmpty()) {
+ qWarning() << "Frames over-run";
+ }
+
+ video_buffer* buf = frames.takeFirst();
+ delete buf->buffer;
+ delete buf;
+ mutex.unlock();
+ }
+}
+
+HRESULT DSCameraSession::getPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin)
+{
+ *ppPin = 0;
+ IEnumPins *pEnum = 0;
+ IPin *pPin = 0;
+
+ HRESULT hr = pFilter->EnumPins(&pEnum);
+ if(FAILED(hr)) {
+ return hr;
+ }
+
+ pEnum->Reset();
+ while(pEnum->Next(1, &pPin, NULL) == S_OK) {
+ PIN_DIRECTION ThisPinDir;
+ pPin->QueryDirection(&ThisPinDir);
+ if(ThisPinDir == PinDir) {
+ pEnum->Release();
+ *ppPin = pPin;
+ return S_OK;
+ }
+ pEnum->Release();
+ }
+ pEnum->Release();
+ return E_FAIL;
+}
+
+bool DSCameraSession::createFilterGraph()
+{
+ HRESULT hr;
+ IMoniker* pMoniker = NULL;
+ ICreateDevEnum* pDevEnum = NULL;
+ IEnumMoniker* pEnum = NULL;
+
+ CoInitialize(NULL);
+
+ // Create the filter graph
+ hr = CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC,
+ IID_IGraphBuilder, (void**)&pGraph);
+ if (FAILED(hr)) {
+ qWarning()<<"failed to create filter graph";
+ return false;
+ }
+
+ // Create the capture graph builder
+ hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,
+ IID_ICaptureGraphBuilder2, (void**)&pBuild);
+ if (FAILED(hr)) {
+ qWarning()<<"failed to create graph builder";
+ return false;
+ }
+
+ // Attach the filter graph to the capture graph
+ hr = pBuild->SetFiltergraph(pGraph);
+ if (FAILED(hr)) {
+ qWarning()<<"failed to connect capture graph and filter graph";
+ return false;
+ }
+
+ // Find the Capture device
+ hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
+ CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
+ reinterpret_cast<void**>(&pDevEnum));
+ if (SUCCEEDED(hr)) {
+ // Create an enumerator for the video capture category
+ hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
+ pDevEnum->Release();
+ if (S_OK == hr) {
+ pEnum->Reset();
+ //go through and find all video capture devices
+ while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
+ IPropertyBag *pPropBag;
+ hr = pMoniker->BindToStorage(0, 0,
+ IID_IPropertyBag, (void**)(&pPropBag));
+ if(FAILED(hr)) {
+ pMoniker->Release();
+ continue; // skip this one
+ }
+ // Find the description
+ WCHAR str[120];
+ VARIANT varName;
+ varName.vt = VT_BSTR;
+ hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+ if (SUCCEEDED(hr)) {
+ // check if it is the selected device
+ wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
+ QString output = QString::fromUtf16((unsigned short*)str);
+ if (m_device.contains(output.toLocal8Bit().constData())) {
+ hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
+ if (SUCCEEDED(hr)) {
+ pPropBag->Release();
+ pMoniker->Release();
+ break;
+ }
+ }
+ }
+ pPropBag->Release();
+ pMoniker->Release();
+ }
+ if (NULL == pCap)
+ {
+ if (m_device.contains("default"))
+ {
+ pEnum->Reset();
+ // still have to loop to discard bind to storage failure case
+ while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
+ IPropertyBag *pPropBag = 0;
+
+ hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
+ if (FAILED(hr)) {
+ pMoniker->Release();
+ continue; // Don't panic yet
+ }
+
+ // No need to get the description, just grab it
+
+ hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
+ pPropBag->Release();
+ pMoniker->Release();
+ if (SUCCEEDED(hr)) {
+ break; // done, stop looping through
+ }
+ else
+ {
+ qWarning() << "Object bind failed";
+ }
+ }
+ }
+ }
+ pEnum->Release();
+ }
+ }
+
+ // Sample grabber filter
+ hr = CoCreateInstance(CLSID_SampleGrabber, NULL,CLSCTX_INPROC,
+ IID_IBaseFilter, (void**)&pSG_Filter);
+ if (FAILED(hr)) {
+ qWarning() << "failed to create sample grabber";
+ return false;
+ }
+
+ pSG_Filter->QueryInterface(IID_ISampleGrabber, (void**)&pSG);
+ if (FAILED(hr)) {
+ qWarning() << "failed to get sample grabber";
+ return false;
+ }
+ pSG->SetOneShot(FALSE);
+ pSG->SetBufferSamples(TRUE);
+ pSG->SetCallback(StillCapCB, 1);
+
+ CoUninitialize();
+
+ return true;
+}
+
+void DSCameraSession::updateProperties()
+{
+ HRESULT hr;
+ AM_MEDIA_TYPE *pmt = NULL;
+ VIDEOINFOHEADER *pvi = NULL;
+ VIDEO_STREAM_CONFIG_CAPS scc;
+ IAMStreamConfig* pConfig = 0;
+
+ hr = pBuild->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,pCap,
+ IID_IAMStreamConfig, (void**)&pConfig);
+ if (FAILED(hr)) {
+ qWarning()<<"failed to get config on capture device";
+ return;
+ }
+
+ int iCount;
+ int iSize;
+ hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);
+ if (FAILED(hr)) {
+ qWarning()<<"failed to get capabilities";
+ return;
+ }
+
+ QList<QSize> sizes;
+ QVideoFrame::PixelFormat f = QVideoFrame::Format_Invalid;
+
+ types.clear();
+ resolutions.clear();
+
+ for (int iIndex = 0; iIndex < iCount; iIndex++) {
+ hr = pConfig->GetStreamCaps(iIndex, &pmt, reinterpret_cast<BYTE*>(&scc));
+ if (hr == S_OK) {
+ pvi = (VIDEOINFOHEADER*)pmt->pbFormat;
+ if ((pmt->majortype == MEDIATYPE_Video) &&
+ (pmt->formattype == FORMAT_VideoInfo)) {
+ // Add types
+ if (pmt->subtype == MEDIASUBTYPE_RGB24) {
+ if (!types.contains(QVideoFrame::Format_RGB24)) {
+ types.append(QVideoFrame::Format_RGB24);
+ f = QVideoFrame::Format_RGB24;
+ }
+ } else if (pmt->subtype == MEDIASUBTYPE_RGB32) {
+ if (!types.contains(QVideoFrame::Format_RGB32)) {
+ types.append(QVideoFrame::Format_RGB32);
+ f = QVideoFrame::Format_RGB32;
+ }
+ } else if (pmt->subtype == MEDIASUBTYPE_YUY2) {
+ if (!types.contains(QVideoFrame::Format_YUYV)) {
+ types.append(QVideoFrame::Format_YUYV);
+ f = QVideoFrame::Format_YUYV;
+ }
+ } else if (pmt->subtype == MEDIASUBTYPE_MJPG) {
+ } else if (pmt->subtype == MEDIASUBTYPE_I420) {
+ if (!types.contains(QVideoFrame::Format_YUV420P)) {
+ types.append(QVideoFrame::Format_YUV420P);
+ f = QVideoFrame::Format_YUV420P;
+ }
+ } else if (pmt->subtype == MEDIASUBTYPE_RGB555) {
+ if (!types.contains(QVideoFrame::Format_RGB555)) {
+ types.append(QVideoFrame::Format_RGB555);
+ f = QVideoFrame::Format_RGB555;
+ }
+ } else if (pmt->subtype == MEDIASUBTYPE_YVU9) {
+ } else if (pmt->subtype == MEDIASUBTYPE_UYVY) {
+ if (!types.contains(QVideoFrame::Format_UYVY)) {
+ types.append(QVideoFrame::Format_UYVY);
+ f = QVideoFrame::Format_UYVY;
+ }
+ } else {
+ qWarning() << "UNKNOWN FORMAT: " << pmt->subtype.Data1;
+ }
+ // Add resolutions
+ QSize res(pvi->bmiHeader.biWidth, pvi->bmiHeader.biHeight);
+ if (!resolutions.contains(f)) {
+ sizes.clear();
+ resolutions.insert(f,sizes);
+ }
+ resolutions[f].append(res);
+ }
+ }
+ }
+ pConfig->Release();
+}
+
+bool DSCameraSession::setProperties()
+{
+ CoInitialize(NULL);
+
+ HRESULT hr;
+ AM_MEDIA_TYPE am_media_type;
+ AM_MEDIA_TYPE *pmt = NULL;
+ VIDEOINFOHEADER *pvi = NULL;
+ VIDEO_STREAM_CONFIG_CAPS scc;
+
+ IAMStreamConfig* pConfig = 0;
+ hr = pBuild->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCap,
+ IID_IAMStreamConfig, (void**)&pConfig);
+ if(FAILED(hr)) {
+ qWarning()<<"failed to get config on capture device";
+ return false;
+ }
+
+ int iCount;
+ int iSize;
+ hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);
+ if(FAILED(hr)) {
+ qWarning()<<"failed to get capabilities";
+ return false;
+ }
+
+ bool setFormatOK = false;
+ for (int iIndex = 0; iIndex < iCount; iIndex++) {
+ hr = pConfig->GetStreamCaps(iIndex, &pmt, reinterpret_cast<BYTE*>(&scc));
+ if (hr == S_OK) {
+ pvi = (VIDEOINFOHEADER*)pmt->pbFormat;
+
+ if ((pmt->majortype == MEDIATYPE_Video) &&
+ (pmt->formattype == FORMAT_VideoInfo)) {
+ if ((actualFormat.frameWidth() == pvi->bmiHeader.biWidth) &&
+ (actualFormat.frameHeight() == pvi->bmiHeader.biHeight)) {
+ hr = pConfig->SetFormat(pmt);
+ _FreeMediaType(*pmt);
+ if(FAILED(hr)) {
+ qWarning()<<"failed to set format:" << hr;
+ qWarning()<<"but going to continue";
+ continue; // We going to continue
+ } else {
+ setFormatOK = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ pConfig->Release();
+
+ if (!setFormatOK) {
+ qWarning() << "unable to set any format for camera";
+ return false;
+ }
+
+ // Set Sample Grabber config to match capture
+ ZeroMemory(&am_media_type, sizeof(am_media_type));
+ am_media_type.majortype = MEDIATYPE_Video;
+
+ if (actualFormat.pixelFormat() == QVideoFrame::Format_RGB32)
+ am_media_type.subtype = MEDIASUBTYPE_RGB24;
+ else if (actualFormat.pixelFormat() == QVideoFrame::Format_RGB24)
+ am_media_type.subtype = MEDIASUBTYPE_RGB24;
+ else if (actualFormat.pixelFormat() == QVideoFrame::Format_YUYV)
+ am_media_type.subtype = MEDIASUBTYPE_YUY2;
+ else if (actualFormat.pixelFormat() == QVideoFrame::Format_YUV420P)
+ am_media_type.subtype = MEDIASUBTYPE_I420;
+ else if (actualFormat.pixelFormat() == QVideoFrame::Format_RGB555)
+ am_media_type.subtype = MEDIASUBTYPE_RGB555;
+ else if (actualFormat.pixelFormat() == QVideoFrame::Format_UYVY)
+ am_media_type.subtype = MEDIASUBTYPE_UYVY;
+ else {
+ qWarning()<<"unknown format? for SG";
+ return false;
+ }
+
+ am_media_type.formattype = FORMAT_VideoInfo;
+ hr = pSG->SetMediaType(&am_media_type);
+ if (FAILED(hr)) {
+ qWarning()<<"failed to set video format on grabber";
+ return false;
+ }
+
+ pSG->GetConnectedMediaType(&StillMediaType);
+
+ CoUninitialize();
+
+ return true;
+}
+
+bool DSCameraSession::openStream()
+{
+ //Opens the stream for reading and allocates any necessary resources needed
+ //Return true if success, false otherwise
+
+ if (opened) {
+ return true;
+ }
+
+ if (!graph) {
+ graph = createFilterGraph();
+ if(!graph) {
+ qWarning()<<"failed to create filter graph in openStream";
+ return false;
+ }
+ }
+
+ CoInitialize(NULL);
+
+ HRESULT hr;
+
+ hr = pGraph->AddFilter(pCap, L"Capture Filter");
+ if (FAILED(hr)) {
+ qWarning()<<"failed to create capture filter";
+ return false;
+ }
+
+ hr = pGraph->AddFilter(pSG_Filter, L"Sample Grabber");
+ if (FAILED(hr)) {
+ qWarning()<<"failed to add sample grabber";
+ return false;
+ }
+
+ hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
+ pCap, NULL, pSG_Filter);
+ if (FAILED(hr)) {
+ qWarning() << "failed to renderstream" << hr;
+ return false;
+ }
+ pSG->GetConnectedMediaType(&StillMediaType);
+ pSG_Filter->Release();
+
+ CoUninitialize();
+
+ return true;
+}
+
+void DSCameraSession::closeStream()
+{
+ // Closes the stream and internally frees any resources used
+ HRESULT hr;
+ IMediaControl* pControl = 0;
+
+ hr = pGraph->QueryInterface(IID_IMediaControl,(void**)&pControl);
+ if (FAILED(hr)) {
+ qWarning()<<"failed to get stream control";
+ return;
+ }
+
+ hr = pControl->StopWhenReady();
+ if (FAILED(hr)) {
+ qWarning()<<"failed to stop";
+ pControl->Release();
+ return;
+ }
+
+ pControl->Release();
+
+ opened = false;
+ IPin *pPin = 0;
+
+ if (pCap)
+ {
+ hr = getPin(pCap, PINDIR_OUTPUT, &pPin);
+ if(FAILED(hr)) {
+ qWarning()<<"failed to disconnect capture filter";
+ return;
+ }
+ }
+
+ pGraph->Disconnect(pPin);
+ if (FAILED(hr)) {
+ qWarning()<<"failed to disconnect grabber filter";
+ return;
+ }
+
+ hr = getPin(pSG_Filter,PINDIR_INPUT,&pPin);
+ pGraph->Disconnect(pPin);
+ pGraph->RemoveFilter(pSG_Filter);
+ pGraph->RemoveFilter(pCap);
+
+ SAFE_RELEASE(pCap);
+ SAFE_RELEASE(pSG_Filter);
+ SAFE_RELEASE(pGraph);
+ SAFE_RELEASE(pBuild);
+
+ graph = false;
+}
+
+bool DSCameraSession::startStream()
+{
+ // Starts the stream, by emitting either QVideoPackets
+ // or QvideoFrames, depending on Format chosen
+ if (!graph)
+ graph = createFilterGraph();
+
+ if (!setProperties()) {
+ qWarning() << "Couldn't set properties (retrying)";
+ closeStream();
+ if (!openStream()) {
+ qWarning() << "Retry to open strean failed";
+ return false;
+ }
+ }
+
+ if (!opened) {
+ opened = openStream();
+ if (!opened) {
+ qWarning() << "failed to openStream()";
+ return false;
+ }
+ }
+
+ HRESULT hr;
+ IMediaControl* pControl = 0;
+
+ hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
+ if (FAILED(hr)) {
+ qWarning() << "failed to get stream control";
+ return false;
+ }
+
+ hr = pControl->Run();
+ pControl->Release();
+
+ if (FAILED(hr)) {
+ qWarning() << "failed to start";
+ return false;
+ }
+ active = true;
+ return true;
+}
+
+void DSCameraSession::stopStream()
+{
+ // Stops the stream from emitting packets
+ HRESULT hr;
+
+ IMediaControl* pControl = 0;
+ hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
+ if (FAILED(hr)) {
+ qWarning() << "failed to get stream control";
+ return;
+ }
+
+ hr = pControl->Stop();
+ pControl->Release();
+ if (FAILED(hr)) {
+ qWarning() << "failed to stop";
+ return;
+ }
+ active = false;
+
+ if (opened) {
+ closeStream();
+ }
+}
+
+void DSCameraSession::suspendStream()
+{
+ // Pauses the stream
+ HRESULT hr;
+
+ IMediaControl* pControl = 0;
+ hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
+ if (FAILED(hr)) {
+ qWarning() << "failed to get stream control";
+ return;
+ }
+
+ hr = pControl->Pause();
+ pControl->Release();
+ if (FAILED(hr)) {
+ qWarning() << "failed to pause";
+ return;
+ }
+
+ active = false;
+}
+
+void DSCameraSession::resumeStream()
+{
+ // Resumes a paused stream
+ startStream();
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/directshow/camera/dscamerasession.h b/src/plugins/directshow/camera/dscamerasession.h
new file mode 100644
index 000000000..72a0e5077
--- /dev/null
+++ b/src/plugins/directshow/camera/dscamerasession.h
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 DSCAMERASESSION_H
+#define DSCAMERASESSION_H
+
+#include <QtCore/qobject.h>
+#include <QTime>
+#include <QUrl>
+#include <QMutex>
+
+#include <qcamera.h>
+#include <QtMultimedia/qvideoframe.h>
+#include <QtMultimedia/qabstractvideosurface.h>
+#include <QtMultimedia/qvideosurfaceformat.h>
+
+#include <tchar.h>
+#include <dshow.h>
+#include <objbase.h>
+#include <initguid.h>
+#pragma comment(lib, "strmiids.lib")
+#pragma comment(lib, "ole32.lib")
+#include <windows.h>
+
+#pragma include_alias("dxtrans.h","qedit.h")
+#define __IDxtCompositor_INTERFACE_DEFINED__
+#define __IDxtAlphaSetter_INTERFACE_DEFINED__
+#define __IDxtJpeg_INTERFACE_DEFINED__
+#define __IDxtKey_INTERFACE_DEFINED__
+#include <qedit.h>
+
+struct ICaptureGraphBuilder2;
+struct ISampleGrabber;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class DSVideoRenderer;
+class SampleGrabberCallbackPrivate;
+
+
+struct video_buffer {
+ unsigned char* buffer;
+ int length;
+ qint64 time;
+};
+
+typedef QMap<unsigned int, QList<QSize> > FormatResolutionMap;
+
+class DSCameraSession : public QObject
+{
+ Q_OBJECT
+public:
+ DSCameraSession(QObject *parent = 0);
+ ~DSCameraSession();
+
+ bool deviceReady();
+ bool pictureInProgress();
+
+ // camera controls
+
+ int framerate() const;
+ void setFrameRate(int rate);
+ int brightness() const;
+ void setBrightness(int b);
+ int contrast() const;
+ void setContrast(int c);
+ int saturation() const;
+ void setSaturation(int s);
+ int hue() const;
+ void setHue(int h);
+ int sharpness() const;
+ void setSharpness(int s);
+ int zoom() const;
+ void setZoom(int z);
+ bool backlightCompensation() const;
+ void setBacklightCompensation(bool);
+ int whitelevel() const;
+ void setWhitelevel(int w);
+ int rotation() const;
+ void setRotation(int r);
+ bool flash() const;
+ void setFlash(bool f);
+ bool autofocus() const;
+ void setAutofocus(bool f);
+
+ QSize frameSize() const;
+ void setFrameSize(const QSize& s);
+ void setDevice(const QString &device);
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats();
+ QVideoFrame::PixelFormat pixelFormat() const;
+ void setPixelFormat(QVideoFrame::PixelFormat fmt);
+ QList<QSize> supportedResolutions(QVideoFrame::PixelFormat format);
+
+ // media control
+
+ bool setOutputLocation(const QUrl &sink);
+ QUrl outputLocation() const;
+ qint64 position() const;
+ int state() const;
+ void record();
+ void pause();
+ void stop();
+
+ void setSurface(QAbstractVideoSurface* surface);
+
+ int captureImage(const QString &fileName);
+
+ AM_MEDIA_TYPE StillMediaType;
+ QList<video_buffer*> frames;
+ SampleGrabberCallbackPrivate* StillCapCB;
+
+ QMutex mutex;
+
+Q_SIGNALS:
+ void stateChanged(QCamera::State);
+ void imageCaptured(int id, const QImage &preview);
+ void imageSaved(int id, const QString &fileName);
+ void readyForCaptureChanged(bool);
+
+private Q_SLOTS:
+ void captureFrame();
+
+private:
+ QVideoSurfaceFormat actualFormat;
+ QList<QVideoFrame::PixelFormat> types;
+
+ QTime timeStamp;
+ bool graph;
+ bool active;
+ bool opened;
+ bool available;
+ QCamera::State m_state;
+ QByteArray m_device;
+ QUrl m_sink;
+ DSVideoRenderer* m_output;
+ QAbstractVideoSurface* m_surface;
+ QVideoFrame::PixelFormat pixelF;
+ QSize m_windowSize;
+ FormatResolutionMap resolutions;
+
+ ICaptureGraphBuilder2* pBuild;
+ IGraphBuilder* pGraph;
+ IBaseFilter* pCap;
+ IBaseFilter* pSG_Filter;
+ ISampleGrabber *pSG;
+
+
+ QString m_snapshot;
+ int m_currentImageId;
+protected:
+ HRESULT getPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin);
+ bool createFilterGraph();
+ void updateProperties();
+ bool setProperties();
+ bool openStream();
+ void closeStream();
+ bool startStream();
+ void stopStream();
+ void suspendStream();
+ void resumeStream();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif
diff --git a/src/plugins/directshow/camera/dsimagecapturecontrol.cpp b/src/plugins/directshow/camera/dsimagecapturecontrol.cpp
new file mode 100644
index 000000000..17654c4a5
--- /dev/null
+++ b/src/plugins/directshow/camera/dsimagecapturecontrol.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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 <QtCore/QDebug>
+
+#include "dsimagecapturecontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+DSImageCaptureControl::DSImageCaptureControl(DSCameraSession *session)
+ :QCameraImageCaptureControl(session), m_session(session), m_ready(false)
+{
+ connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
+ connect(m_session, SIGNAL(imageCaptured(const int, QImage)),
+ this, SIGNAL(imageCaptured(const int, QImage)));
+ connect(m_session, SIGNAL(imageSaved(const int, const QString &)),
+ this, SIGNAL(imageSaved(const int, const QString &)));
+ connect(m_session, SIGNAL(readyForCaptureChanged(bool)),
+ this, SIGNAL(readyForCaptureChanged(bool)));
+}
+
+DSImageCaptureControl::~DSImageCaptureControl()
+{
+}
+
+bool DSImageCaptureControl::isReadyForCapture() const
+{
+ return m_ready;
+}
+
+int DSImageCaptureControl::capture(const QString &fileName)
+{
+ return m_session->captureImage(fileName);
+}
+
+void DSImageCaptureControl::updateState()
+{
+ bool ready = (m_session->state() == QCamera::ActiveState) &&
+ !m_session->pictureInProgress();
+ if(m_ready != ready)
+ emit readyForCaptureChanged(m_ready = ready);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/directshow/camera/dsimagecapturecontrol.h b/src/plugins/directshow/camera/dsimagecapturecontrol.h
new file mode 100644
index 000000000..8eca7b4e7
--- /dev/null
+++ b/src/plugins/directshow/camera/dsimagecapturecontrol.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** 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 DSIMAGECAPTURECONTROL_H
+#define DSIMAGECAPTURECONTROL_H
+
+#include <qcameraimagecapturecontrol.h>
+#include "dscamerasession.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class DSImageCaptureControl : public QCameraImageCaptureControl
+{
+ Q_OBJECT
+public:
+ DSImageCaptureControl(DSCameraSession *session);
+ virtual ~DSImageCaptureControl();
+
+ bool isReadyForCapture() const;
+ int capture(const QString &fileName);
+
+ virtual QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; }
+ virtual void setDriveMode(QCameraImageCapture::DriveMode mode) { }
+
+ virtual void cancelCapture() {}
+
+private slots:
+ void updateState();
+
+
+private:
+ DSCameraSession *m_session;
+ bool m_ready;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // DSCAPTURECONTROL_H
diff --git a/src/plugins/directshow/camera/dsvideodevicecontrol.cpp b/src/plugins/directshow/camera/dsvideodevicecontrol.cpp
new file mode 100644
index 000000000..8c9b03000
--- /dev/null
+++ b/src/plugins/directshow/camera/dsvideodevicecontrol.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** 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 <QDebug>
+#include <QFile>
+#include <QtGui/QIcon>
+
+#include "dsvideodevicecontrol.h"
+#include "dscamerasession.h"
+
+#include <tchar.h>
+#include <dshow.h>
+#include <objbase.h>
+#include <initguid.h>
+#include <Ocidl.h>
+#include <string.h>
+
+extern const CLSID CLSID_VideoInputDeviceCategory;
+
+QT_BEGIN_NAMESPACE
+
+DSVideoDeviceControl::DSVideoDeviceControl(QObject *parent)
+ : QVideoDeviceControl(parent)
+{
+ m_session = qobject_cast<DSCameraSession*>(parent);
+
+ devices.clear();
+ descriptions.clear();
+
+ 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));
+ if(SUCCEEDED(hr)) {
+ // Create the enumerator for the video capture category
+ hr = pDevEnum->CreateClassEnumerator(
+ CLSID_VideoInputDeviceCategory, &pEnum, 0);
+ if (S_OK == hr) {
+ pEnum->Reset();
+ // go through and find all video capture devices
+ IMoniker* pMoniker = NULL;
+ while(pEnum->Next(1, &pMoniker, NULL) == S_OK) {
+ IPropertyBag *pPropBag;
+ hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
+ (void**)(&pPropBag));
+ if(FAILED(hr)) {
+ pMoniker->Release();
+ continue; // skip this one
+ }
+ // Find the description
+ WCHAR str[120];
+ VARIANT varName;
+ varName.vt = VT_BSTR;
+ hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+ if(SUCCEEDED(hr)) {
+ wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
+ QString temp(QString::fromUtf16((unsigned short*)str));
+ devices.append(QString("ds:%1").arg(temp).toLocal8Bit().constData());
+ hr = pPropBag->Read(L"Description", &varName, 0);
+ wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
+ QString temp2(QString::fromUtf16((unsigned short*)str));
+ descriptions.append(temp2.toLocal8Bit().constData());
+ }
+ pPropBag->Release();
+ pMoniker->Release();
+ }
+ pEnum->Release();
+ }
+ pDevEnum->Release();
+ }
+ CoUninitialize();
+
+ selected = 0;
+}
+
+int DSVideoDeviceControl::deviceCount() const
+{
+ return devices.count();
+}
+
+QString DSVideoDeviceControl::deviceName(int index) const
+{
+ if(index >= 0 && index <= devices.count())
+ return devices.at(index);
+
+ return QString();
+}
+
+QString DSVideoDeviceControl::deviceDescription(int index) const
+{
+ if(index >= 0 && index <= descriptions.count())
+ return descriptions.at(index);
+
+ return QString();
+}
+
+QIcon DSVideoDeviceControl::deviceIcon(int index) const
+{
+ Q_UNUSED(index)
+
+ return QIcon();
+}
+
+int DSVideoDeviceControl::defaultDevice() const
+{
+ return 0;
+}
+
+int DSVideoDeviceControl::selectedDevice() const
+{
+ return selected;
+}
+
+void DSVideoDeviceControl::setSelectedDevice(int index)
+{
+ if(index >= 0 && index <= devices.count()) {
+ if (m_session) {
+ QString device = devices.at(index);
+ if (device.startsWith("ds:"))
+ device.remove(0,3);
+ m_session->setDevice(device);
+ }
+ selected = index;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/directshow/camera/dsvideodevicecontrol.h b/src/plugins/directshow/camera/dsvideodevicecontrol.h
new file mode 100644
index 000000000..8391c4eda
--- /dev/null
+++ b/src/plugins/directshow/camera/dsvideodevicecontrol.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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 DSVIDEODEVICECONTROL_H
+#define DSVIDEODEVICECONTROL_H
+
+#include <qvideodevicecontrol.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+class DSCameraSession;
+
+//QTM_USE_NAMESPACE
+
+class DSVideoDeviceControl : public QVideoDeviceControl
+{
+ Q_OBJECT
+public:
+ DSVideoDeviceControl(QObject *parent = 0);
+
+ int deviceCount() const;
+ QString deviceName(int index) const;
+ QString deviceDescription(int index) const;
+ QIcon deviceIcon(int index) const;
+ int defaultDevice() const;
+ int selectedDevice() const;
+
+public Q_SLOTS:
+ void setSelectedDevice(int index);
+
+private:
+ DSCameraSession* m_session;
+
+ QList<QString> devices;
+ QList<QString> descriptions;
+
+ int selected;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/plugins/directshow/camera/dsvideorenderer.cpp b/src/plugins/directshow/camera/dsvideorenderer.cpp
new file mode 100644
index 000000000..0fbdb15b1
--- /dev/null
+++ b/src/plugins/directshow/camera/dsvideorenderer.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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 <QtCore/qdebug.h>
+
+#include "dsvideorenderer.h"
+
+QT_BEGIN_NAMESPACE
+
+DSVideoRendererControl::DSVideoRendererControl(DSCameraSession* session, QObject *parent)
+ :QVideoRendererControl(parent),
+ m_surface(0),
+ m_session(session)
+{
+}
+
+DSVideoRendererControl::~DSVideoRendererControl()
+{
+}
+
+QAbstractVideoSurface* DSVideoRendererControl::surface() const
+{
+ return m_surface;
+}
+
+void DSVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
+{
+ m_surface = surface;
+ if(m_session)
+ m_session->setSurface(m_surface);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/directshow/camera/dsvideorenderer.h b/src/plugins/directshow/camera/dsvideorenderer.h
new file mode 100644
index 000000000..b941504ac
--- /dev/null
+++ b/src/plugins/directshow/camera/dsvideorenderer.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 DSVIDEORENDERER_H
+#define DSVIDEORENDERER_H
+
+#include <qvideorenderercontrol.h>
+#include "dscamerasession.h"
+
+class CameraFormatConverter;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+
+class DSVideoRendererControl : public QVideoRendererControl
+{
+ Q_OBJECT
+public:
+ DSVideoRendererControl(DSCameraSession* session, QObject *parent = 0);
+ ~DSVideoRendererControl();
+
+ QAbstractVideoSurface *surface() const;
+ void setSurface(QAbstractVideoSurface *surface);
+
+ void setSession(DSCameraSession* session);
+
+private:
+ QAbstractVideoSurface* m_surface;
+ DSCameraSession* m_session;
+ CameraFormatConverter* converter;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // DSVIDEORENDERER_H
diff --git a/src/plugins/directshow/camera/dsvideowidgetcontrol.cpp b/src/plugins/directshow/camera/dsvideowidgetcontrol.cpp
new file mode 100644
index 000000000..8298c0275
--- /dev/null
+++ b/src/plugins/directshow/camera/dsvideowidgetcontrol.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qcoreevent.h>
+#include <QtCore/qtimer.h>
+
+#include "DSVideoWidgetControl.h"
+#include "dscamerasession.h"
+
+QT_BEGIN_NAMESPACE
+
+DSVideoWidgetSurface::DSVideoWidgetSurface(QLabel *pWidget, QObject *parent)
+{
+ widget = pWidget;
+ myPixmap = 0;
+}
+
+QList<QVideoFrame::PixelFormat> DSVideoWidgetSurface::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ if (handleType == QAbstractVideoBuffer::NoHandle) {
+ return QList<QVideoFrame::PixelFormat>()
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_RGB24;
+ } else {
+ return QList<QVideoFrame::PixelFormat>();
+ }
+}
+
+
+bool DSVideoWidgetSurface::present(const QVideoFrame &frame)
+{
+ QVideoFrame myFrame = frame;
+ myFrame.map(QAbstractVideoBuffer::ReadOnly);
+ QImage image(
+ frame.bits(),
+ frame.width(),
+ frame.height(),
+ frame.bytesPerLine(),
+ imageFormat);
+ if (image.isNull())
+ {
+ // Try to adapt
+ QImage image2(
+ frame.bits(),
+ frame.width(),
+ frame.height(),
+ frame.bytesPerLine(),
+ QImage::Format_RGB888);
+ image = image2;
+ }
+ myFrame.unmap();
+ delete myPixmap;
+ myPixmap = new QPixmap(QPixmap::fromImage(image).scaled(widget->size()));
+ widget->setPixmap(*myPixmap);
+ widget->repaint();
+ return true;
+}
+
+void DSVideoWidgetSurface::setImageFormat(QImage::Format fmt)
+{
+ imageFormat = fmt;
+}
+
+void DSVideoWidgetSurface::updateVideoRect()
+{
+}
+
+void DSVideoWidgetSurface::paint(QPainter *painter)
+{
+}
+
+
+DSVideoWidgetControl::DSVideoWidgetControl(DSCameraSession* session, QObject *parent) :
+ m_session(session), QVideoWidgetControl(parent),
+ m_widget(new QLabel()),
+ m_fullScreen(false)
+{
+ m_widget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+ m_widget->setAlignment(Qt::AlignCenter);
+ m_widget->setAttribute(Qt::WA_NoSystemBackground, true);
+
+ surface = new DSVideoWidgetSurface(m_widget);
+
+ QPalette palette;
+ palette.setColor(QPalette::Background, Qt::black);
+ m_widget->setPalette(palette);
+ m_widget->setAutoFillBackground( true );
+
+ // Request QEvents
+ m_widget->installEventFilter(this);
+ m_windowId = m_widget->effectiveWinId();
+
+ surface->setImageFormat(QImage::Format_RGB888);
+ session->setSurface(surface);
+}
+
+DSVideoWidgetControl::~DSVideoWidgetControl()
+{
+ delete m_widget;
+}
+
+bool DSVideoWidgetControl::eventFilter(QObject *object, QEvent *e)
+{
+ if (object == m_widget) {
+ switch (e->type()) {
+ case QEvent::ParentChange:
+ case QEvent::WinIdChange:
+ case QEvent::Show:
+ m_windowId = m_widget->effectiveWinId();
+ emit widgetUpdated();
+ break;
+ case QEvent::Resize:
+ emit widgetResized(m_widget->size());
+ break;
+ case QEvent::PolishRequest:
+ m_widget->ensurePolished();
+ break;
+
+ default:
+ // Do nothing
+ break;
+ }
+ }
+ return false;
+}
+
+QWidget *DSVideoWidgetControl::videoWidget()
+{
+ return m_widget;
+}
+
+Qt::AspectRatioMode DSVideoWidgetControl::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void DSVideoWidgetControl::setAspectRatioMode(Qt::AspectRatioMode ratio)
+{
+ if (m_aspectRatioMode==ratio) {
+ return;
+ }
+ m_aspectRatioMode = ratio;
+
+ if (m_aspectRatioMode == Qt::KeepAspectRatio)
+ m_widget->setScaledContents(false);
+ else {
+ m_widget->setScaledContents(true);
+ }
+}
+
+bool DSVideoWidgetControl::isFullScreen() const
+{
+ return m_fullScreen;
+}
+
+void DSVideoWidgetControl::setFullScreen(bool fullScreen)
+{
+ if (m_widget && !fullScreen && m_fullScreen) {
+ m_widget->showNormal();
+ m_fullScreen = false;
+ } else if (m_widget && fullScreen) {
+ m_widget->showFullScreen();
+ m_fullScreen = true;
+ }
+
+ emit fullScreenChanged(fullScreen);
+}
+
+int DSVideoWidgetControl::brightness() const
+{
+ return 0;
+}
+
+void DSVideoWidgetControl::setBrightness(int brightness)
+{
+ Q_UNUSED(brightness);
+}
+
+int DSVideoWidgetControl::contrast() const
+{
+ return 0;
+}
+
+void DSVideoWidgetControl::setContrast(int contrast)
+{
+ Q_UNUSED(contrast);
+}
+
+int DSVideoWidgetControl::hue() const
+{
+ return 0;
+}
+
+void DSVideoWidgetControl::setHue(int hue)
+{
+ Q_UNUSED(hue);
+}
+
+int DSVideoWidgetControl::saturation() const
+{
+ return 0;
+}
+
+void DSVideoWidgetControl::setSaturation(int saturation)
+{
+ Q_UNUSED(saturation);
+}
+
+QT_END_NAMESPACE
+
+// End of file
diff --git a/src/plugins/directshow/camera/dsvideowidgetcontrol.h b/src/plugins/directshow/camera/dsvideowidgetcontrol.h
new file mode 100644
index 000000000..e17827453
--- /dev/null
+++ b/src/plugins/directshow/camera/dsvideowidgetcontrol.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** 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$
+** 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 DSVIDEOWIDGETCONTROL_H
+#define DSVIDEOWIDGETCONTROL_H
+
+#include <QtCore/qobject.h>
+#include <QtGui>
+#include <QtMultimedia/qvideoframe.h>
+#include <QtMultimedia/qabstractvideosurface.h>
+#include <QtMultimedia/qvideosurfaceformat.h>
+
+#include <qvideowidgetcontrol.h>
+#include "DsCameraControl.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class DSVideoWidgetSurface : public QAbstractVideoSurface
+{
+ Q_OBJECT
+ public:
+ DSVideoWidgetSurface(QLabel *pWidget, QObject *parent = 0);
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
+
+ bool present(const QVideoFrame &frame);
+
+ QRect videoRect() const { return targetRect; }
+ void updateVideoRect();
+
+ void paint(QPainter *painter);
+ void setImageFormat(QImage::Format fmt);
+
+ private:
+ QLabel *widget;
+ QImage::Format imageFormat;
+ QRect targetRect;
+ QSize imageSize;
+ QRect sourceRect;
+ QPixmap* myPixmap;
+ };
+
+class DSVideoWidgetControl : public QVideoWidgetControl
+{
+ Q_OBJECT
+
+ DSVideoWidgetSurface* surface;
+public: // Constructor & Destructor
+
+ DSVideoWidgetControl(DSCameraSession* session, QObject *parent = 0);
+ virtual ~DSVideoWidgetControl();
+
+public: // QVideoWidgetControl
+
+ QWidget *videoWidget();
+
+ // Aspect Ratio
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode ratio);
+
+ // Full Screen
+ bool isFullScreen() const;
+ void setFullScreen(bool fullScreen);
+
+ // Brightness
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ // Contrast
+ int contrast() const;
+ void setContrast(int contrast);
+
+ // Hue
+ int hue() const;
+ void setHue(int hue);
+
+ // Saturation
+ int saturation() const;
+ void setSaturation(int saturation);
+
+public: // Internal
+
+ bool eventFilter(QObject *object, QEvent *event);
+
+/*
+Q_SIGNALS: // QVideoWidgetControl
+
+ void fullScreenChanged(bool fullScreen);
+ void brightnessChanged(int brightness);
+ void contrastChanged(int contrast);
+ void hueChanged(int hue);
+ void saturationChanged(int saturation);
+*/
+
+Q_SIGNALS: // Internal Signals
+
+ void widgetResized(QSize size);
+ void widgetUpdated();
+
+private: // Data
+
+ DSCameraSession* m_session;
+ QLabel *m_widget;
+ WId m_windowId;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ bool m_fullScreen;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // DSVideoWidgetControl_H
diff --git a/src/plugins/directshow/directshow.pro b/src/plugins/directshow/directshow.pro
new file mode 100644
index 000000000..58e98c385
--- /dev/null
+++ b/src/plugins/directshow/directshow.pro
@@ -0,0 +1,23 @@
+TEMPLATE = lib
+
+CONFIG += plugin
+TARGET = $$qtLibraryTarget(dsengine)
+
+PLUGIN_TYPE=mediaservice
+
+include (../../../common.pri)
+INCLUDEPATH+=../../multimediakit \
+ ../../multimediakit/audio \
+ ../../multimediakit/video
+
+qtAddLibrary(QtMultimediaKit)
+
+DEPENDPATH += .
+
+HEADERS += dsserviceplugin.h
+SOURCES += dsserviceplugin.cpp
+
+!contains(wmsdk_enabled, yes): DEFINES += QT_NO_WMSDK
+
+include (player/player.pri)
+include (camera/camera.pri)
diff --git a/src/plugins/directshow/dsserviceplugin.cpp b/src/plugins/directshow/dsserviceplugin.cpp
new file mode 100644
index 000000000..9c0a21449
--- /dev/null
+++ b/src/plugins/directshow/dsserviceplugin.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qstring.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/QFile>
+
+#include "dsserviceplugin.h"
+
+
+#ifdef QMEDIA_DIRECTSHOW_CAMERA
+#include "dscameraservice.h"
+#endif
+
+#ifdef QMEDIA_DIRECTSHOW_PLAYER
+#include "directshowplayerservice.h"
+#endif
+
+#include <qmediaserviceprovider.h>
+
+
+#ifdef QMEDIA_DIRECTSHOW_CAMERA
+
+extern const CLSID CLSID_VideoInputDeviceCategory;
+
+
+#ifndef _STRSAFE_H_INCLUDED_
+#include <tchar.h>
+#endif
+#include <dshow.h>
+#include <objbase.h>
+#include <initguid.h>
+#pragma comment(lib, "strmiids.lib")
+#pragma comment(lib, "ole32.lib")
+#include <windows.h>
+#include <ocidl.h>
+#endif
+
+QT_USE_NAMESPACE
+
+QStringList DSServicePlugin::keys() const
+{
+ return QStringList()
+#ifdef QMEDIA_DIRECTSHOW_CAMERA
+ << QLatin1String(Q_MEDIASERVICE_CAMERA)
+#endif
+#ifdef QMEDIA_DIRECTSHOW_PLAYER
+ << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)
+#endif
+ ;
+}
+
+QMediaService* DSServicePlugin::create(QString const& key)
+{
+#ifdef QMEDIA_DIRECTSHOW_CAMERA
+ if (key == QLatin1String(Q_MEDIASERVICE_CAMERA))
+ return new DSCameraService;
+#endif
+#ifdef QMEDIA_DIRECTSHOW_PLAYER
+ if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER))
+ return new DirectShowPlayerService;
+#endif
+
+ qDebug() << "unsupported key:" << key;
+ return 0;
+}
+
+void DSServicePlugin::release(QMediaService *service)
+{
+ delete service;
+}
+
+QMediaServiceProviderHint::Features DSServicePlugin::supportedFeatures(
+ const QByteArray &service) const
+{
+ if (service == Q_MEDIASERVICE_MEDIAPLAYER)
+ return QMediaServiceProviderHint::StreamPlayback | QMediaServiceProviderHint::VideoSurface;
+ else
+ return QMediaServiceProviderHint::Features();
+}
+
+QList<QByteArray> DSServicePlugin::devices(const QByteArray &service) const
+{
+#ifdef QMEDIA_DIRECTSHOW_CAMERA
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ if (m_cameraDevices.isEmpty())
+ updateDevices();
+
+ return m_cameraDevices;
+ }
+#endif
+
+ return QList<QByteArray>();
+}
+
+QString DSServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
+{
+#ifdef QMEDIA_DIRECTSHOW_CAMERA
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ if (m_cameraDevices.isEmpty())
+ updateDevices();
+
+ for (int i=0; i<m_cameraDevices.count(); i++)
+ if (m_cameraDevices[i] == device)
+ return m_cameraDescriptions[i];
+ }
+#endif
+ return QString();
+}
+
+#ifdef QMEDIA_DIRECTSHOW_CAMERA
+
+void DSServicePlugin::updateDevices() const
+{
+ m_cameraDevices.clear();
+ m_cameraDescriptions.clear();
+ BOOL bFound = TRUE;
+ 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));
+ if(SUCCEEDED(hr)) {
+ // Create the enumerator for the video capture category
+ hr = pDevEnum->CreateClassEnumerator(
+ CLSID_VideoInputDeviceCategory, &pEnum, 0);
+ if (S_OK == hr) {
+ pEnum->Reset();
+ // go through and find all video capture devices
+ IMoniker* pMoniker = NULL;
+ while(pEnum->Next(1, &pMoniker, NULL) == S_OK) {
+ IPropertyBag *pPropBag;
+ hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag,
+ (void**)(&pPropBag));
+ if(FAILED(hr)) {
+ pMoniker->Release();
+ continue; // skip this one
+ }
+ bFound = TRUE;
+ // Find the description
+ WCHAR str[120];
+ VARIANT varName;
+ varName.vt = VT_BSTR;
+ hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+ if(SUCCEEDED(hr)) {
+ wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
+ QString temp(QString::fromUtf16((unsigned short*)str));
+ m_cameraDevices.append(QString("ds:%1").arg(temp).toLocal8Bit().constData());
+ hr = pPropBag->Read(L"Description", &varName, 0);
+ wcsncpy(str, varName.bstrVal, sizeof(str)/sizeof(str[0]));
+ QString temp2(QString::fromUtf16((unsigned short*)str));
+ m_cameraDescriptions.append(temp2);
+ } else {
+ qWarning() << "No friendly name";
+ }
+ pPropBag->Release();
+ pMoniker->Release();
+ }
+ pEnum->Release();
+ }
+ pDevEnum->Release();
+ }
+ CoUninitialize();
+ if (!bFound) {
+ qWarning() << "No camera devices found";
+ }
+}
+#endif
+
+Q_EXPORT_PLUGIN2(qtmedia_dsengine, DSServicePlugin);
+
diff --git a/src/plugins/directshow/dsserviceplugin.h b/src/plugins/directshow/dsserviceplugin.h
new file mode 100644
index 000000000..336da0a3f
--- /dev/null
+++ b/src/plugins/directshow/dsserviceplugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** 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$
+** 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 DSSERVICEPLUGIN_H
+#define DSSERVICEPLUGIN_H
+
+#include "qmediaserviceproviderplugin.h"
+
+QT_USE_NAMESPACE
+
+class DSServicePlugin
+ : public QMediaServiceProviderPlugin
+ , public QMediaServiceSupportedDevicesInterface
+ , public QMediaServiceFeaturesInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
+ Q_INTERFACES(QMediaServiceFeaturesInterface)
+public:
+ QStringList keys() const;
+ QMediaService* create(QString const& key);
+ void release(QMediaService *service);
+
+ QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const;
+
+ QList<QByteArray> devices(const QByteArray &service) const;
+ QString deviceDescription(const QByteArray &service, const QByteArray &device);
+
+private:
+#ifdef QMEDIA_DIRECTSHOW_CAMERA
+ void updateDevices() const;
+
+ mutable QList<QByteArray> m_cameraDevices;
+ mutable QStringList m_cameraDescriptions;
+#endif
+};
+
+#endif // DSSERVICEPLUGIN_H
diff --git a/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp b/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp
new file mode 100644
index 000000000..01c879732
--- /dev/null
+++ b/src/plugins/directshow/player/directshowaudioendpointcontrol.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** 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$
+** 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 "directshowaudioendpointcontrol.h"
+
+#include "directshowglobal.h"
+#include "directshowplayerservice.h"
+
+DirectShowAudioEndpointControl::DirectShowAudioEndpointControl(
+ DirectShowPlayerService *service, QObject *parent)
+ : QAudioEndpointSelector(parent)
+ , m_service(service)
+ , m_bindContext(0)
+ , m_deviceEnumerator(0)
+{
+ if (CreateBindCtx(0, &m_bindContext) == S_OK) {
+ m_deviceEnumerator = com_new<ICreateDevEnum>(CLSID_SystemDeviceEnum, IID_ICreateDevEnum);
+
+ updateEndpoints();
+
+ setActiveEndpoint(m_defaultEndpoint);
+ }
+}
+
+DirectShowAudioEndpointControl::~DirectShowAudioEndpointControl()
+{
+ foreach (IMoniker *moniker, m_devices)
+ moniker->Release();
+
+ if (m_bindContext)
+ m_bindContext->Release();
+
+ if (m_deviceEnumerator)
+ m_deviceEnumerator->Release();
+}
+
+QList<QString> DirectShowAudioEndpointControl::availableEndpoints() const
+{
+ return m_devices.keys();
+}
+
+QString DirectShowAudioEndpointControl::endpointDescription(const QString &name) const
+{
+#ifdef __IPropertyBag_INTERFACE_DEFINED__
+ QString description;
+
+ if (IMoniker *moniker = m_devices.value(name, 0)) {
+ IPropertyBag *propertyBag = 0;
+ if (SUCCEEDED(moniker->BindToStorage(
+ 0, 0, IID_IPropertyBag, reinterpret_cast<void **>(&propertyBag)))) {
+ VARIANT name;
+ VariantInit(&name);
+ if (SUCCEEDED(propertyBag->Read(L"FriendlyName", &name, 0)))
+ description = QString::fromWCharArray(name.bstrVal);
+ VariantClear(&name);
+ propertyBag->Release();
+ }
+ }
+
+ return description;
+#else
+ return name.section(QLatin1Char('\\'), -1);
+#endif
+}
+
+QString DirectShowAudioEndpointControl::defaultEndpoint() const
+{
+ return m_defaultEndpoint;
+}
+
+QString DirectShowAudioEndpointControl::activeEndpoint() const
+{
+ return m_activeEndpoint;
+}
+
+void DirectShowAudioEndpointControl::setActiveEndpoint(const QString &name)
+{
+ if (m_activeEndpoint == name)
+ return;
+
+ if (IMoniker *moniker = m_devices.value(name, 0)) {
+ IBaseFilter *filter = 0;
+
+ if (moniker->BindToObject(
+ m_bindContext,
+ 0,
+ IID_IBaseFilter,
+ reinterpret_cast<void **>(&filter)) == S_OK) {
+ m_service->setAudioOutput(filter);
+
+ filter->Release();
+ }
+ }
+}
+
+void DirectShowAudioEndpointControl::updateEndpoints()
+{
+ IMalloc *oleMalloc = 0;
+ if (m_deviceEnumerator && CoGetMalloc(1, &oleMalloc) == S_OK) {
+ IEnumMoniker *monikers = 0;
+
+ if (m_deviceEnumerator->CreateClassEnumerator(
+ CLSID_AudioRendererCategory, &monikers, 0) == S_OK) {
+ for (IMoniker *moniker = 0; monikers->Next(1, &moniker, 0) == S_OK; moniker->Release()) {
+ OLECHAR *string = 0;
+ if (moniker->GetDisplayName(m_bindContext, 0, &string) == S_OK) {
+ QString deviceId = QString::fromWCharArray(string);
+ oleMalloc->Free(string);
+
+ moniker->AddRef();
+ m_devices.insert(deviceId, moniker);
+
+ if (m_defaultEndpoint.isEmpty()
+ || deviceId.endsWith(QLatin1String("Default DirectSound Device"))) {
+ m_defaultEndpoint = deviceId;
+ }
+ }
+ }
+ monikers->Release();
+ }
+ oleMalloc->Release();
+ }
+}
diff --git a/src/plugins/directshow/player/directshowaudioendpointcontrol.h b/src/plugins/directshow/player/directshowaudioendpointcontrol.h
new file mode 100644
index 000000000..62a0bd47f
--- /dev/null
+++ b/src/plugins/directshow/player/directshowaudioendpointcontrol.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** 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$
+** 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 DIRECTSHOWAUDIOENDPOINTCONTROL_H
+#define DIRECTSHOWAUDIOENDPOINTCONTROL_H
+
+#include "qaudioendpointselector.h"
+
+#include <dshow.h>
+
+class DirectShowPlayerService;
+
+QT_USE_NAMESPACE
+
+class DirectShowAudioEndpointControl : public QAudioEndpointSelector
+{
+ Q_OBJECT
+public:
+ DirectShowAudioEndpointControl(DirectShowPlayerService *service, QObject *parent = 0);
+ ~DirectShowAudioEndpointControl();
+
+ QList<QString> availableEndpoints() const;
+
+ QString endpointDescription(const QString &name) const;
+
+ QString defaultEndpoint() const;
+ QString activeEndpoint() const;
+
+ void setActiveEndpoint(const QString& name);
+
+private:
+ void updateEndpoints();
+
+ DirectShowPlayerService *m_service;
+ IBindCtx *m_bindContext;
+ ICreateDevEnum *m_deviceEnumerator;
+
+ QMap<QString, IMoniker *> m_devices;
+ QString m_defaultEndpoint;
+ QString m_activeEndpoint;
+};
+
+#endif
+
diff --git a/src/plugins/directshow/player/directshoweventloop.cpp b/src/plugins/directshow/player/directshoweventloop.cpp
new file mode 100644
index 000000000..f863aa835
--- /dev/null
+++ b/src/plugins/directshow/player/directshoweventloop.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** 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$
+** 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 <directshoweventloop.h>
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qcoreevent.h>
+
+class DirectShowPostedEvent
+{
+public:
+ DirectShowPostedEvent(QObject *receiver, QEvent *event)
+ : receiver(receiver)
+ , event(event)
+ , next(0)
+ {
+ }
+
+ ~DirectShowPostedEvent()
+ {
+ delete event;
+ }
+
+ QObject *receiver;
+ QEvent *event;
+ DirectShowPostedEvent *next;
+};
+
+DirectShowEventLoop::DirectShowEventLoop(QObject *parent)
+ : QObject(parent)
+ , m_postsHead(0)
+ , m_postsTail(0)
+ , m_eventHandle(::CreateEvent(0, 0, 0, 0))
+ , m_waitHandle(::CreateEvent(0, 0, 0, 0))
+{
+}
+
+DirectShowEventLoop::~DirectShowEventLoop()
+{
+ ::CloseHandle(m_eventHandle);
+ ::CloseHandle(m_waitHandle);
+
+ for (DirectShowPostedEvent *post = m_postsHead; post; post = m_postsHead) {
+ m_postsHead = m_postsHead->next;
+
+ delete post;
+ }
+}
+
+void DirectShowEventLoop::wait(QMutex *mutex)
+{
+ ::ResetEvent(m_waitHandle);
+
+ mutex->unlock();
+
+ HANDLE handles[] = { m_eventHandle, m_waitHandle };
+ while (::WaitForMultipleObjects(2, handles, false, INFINITE) == WAIT_OBJECT_0)
+ processEvents();
+
+ mutex->lock();
+}
+
+void DirectShowEventLoop::wake()
+{
+ ::SetEvent(m_waitHandle);
+}
+
+void DirectShowEventLoop::postEvent(QObject *receiver, QEvent *event)
+{
+ QMutexLocker locker(&m_mutex);
+
+ DirectShowPostedEvent *post = new DirectShowPostedEvent(receiver, event);
+
+ if (m_postsTail)
+ m_postsTail->next = post;
+ else
+ m_postsHead = post;
+
+ m_postsTail = post;
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ ::SetEvent(m_eventHandle);
+}
+
+void DirectShowEventLoop::customEvent(QEvent *event)
+{
+ if (event->type() == QEvent::User) {
+ processEvents();
+ } else {
+ QObject::customEvent(event);
+ }
+}
+
+void DirectShowEventLoop::processEvents()
+{
+ QMutexLocker locker(&m_mutex);
+
+ ::ResetEvent(m_eventHandle);
+
+ while(m_postsHead) {
+ DirectShowPostedEvent *post = m_postsHead;
+ m_postsHead = m_postsHead->next;
+
+ if (!m_postsHead)
+ m_postsTail = 0;
+
+ locker.unlock();
+ QCoreApplication::sendEvent(post->receiver, post->event);
+ delete post;
+ locker.relock();
+ }
+}
diff --git a/src/plugins/directshow/player/directshoweventloop.h b/src/plugins/directshow/player/directshoweventloop.h
new file mode 100644
index 000000000..6f1a51cd5
--- /dev/null
+++ b/src/plugins/directshow/player/directshoweventloop.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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$
+** 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 DIRECTSHOWEVENTLOOP_H
+#define DIRECTSHOWEVENTLOOP_H
+
+#include <QtCore/qmutex.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qwaitcondition.h>
+
+#include <windows.h>
+
+class DirectShowPostedEvent;
+
+class DirectShowEventLoop : public QObject
+{
+ Q_OBJECT
+public:
+ DirectShowEventLoop(QObject *parent = 0);
+ ~DirectShowEventLoop();
+
+ void wait(QMutex *mutex);
+ void wake();
+
+ void postEvent(QObject *object, QEvent *event);
+
+protected:
+ void customEvent(QEvent *event);
+
+private:
+ void processEvents();
+
+ DirectShowPostedEvent *m_postsHead;
+ DirectShowPostedEvent *m_postsTail;
+ HANDLE m_eventHandle;
+ HANDLE m_waitHandle;
+ QMutex m_mutex;
+};
+
+#endif
diff --git a/src/plugins/directshow/player/directshowglobal.h b/src/plugins/directshow/player/directshowglobal.h
new file mode 100644
index 000000000..d14c117ec
--- /dev/null
+++ b/src/plugins/directshow/player/directshowglobal.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** 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$
+** 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 DIRECTSHOWGLOBAL_H
+#define DIRECTSHOWGLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#include <dshow.h>
+
+template <typename T> T *com_cast(IUnknown *unknown, const IID &iid)
+{
+ T *iface = 0;
+ return unknown && unknown->QueryInterface(iid, reinterpret_cast<void **>(&iface)) == S_OK
+ ? iface
+ : 0;
+}
+
+template <typename T> T *com_new(const IID &clsid, const IID &iid)
+{
+ T *object = 0;
+ return CoCreateInstance(
+ clsid,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ iid,
+ reinterpret_cast<void **>(&object)) == S_OK
+ ? object
+ : 0;
+}
+
+#ifndef __IFilterGraph2_INTERFACE_DEFINED__
+#define __IFilterGraph2_INTERFACE_DEFINED__
+#define INTERFACE IFilterGraph2
+DECLARE_INTERFACE_(IFilterGraph2 ,IGraphBuilder)
+{
+ STDMETHOD(AddSourceFilterForMoniker)(THIS_ IMoniker *, IBindCtx *, LPCWSTR,IBaseFilter **) PURE;
+ STDMETHOD(ReconnectEx)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE;
+ STDMETHOD(RenderEx)(IPin *, DWORD, DWORD *) PURE;
+};
+#undef INTERFACE
+#endif
+
+#ifndef __IAMFilterMiscFlags_INTERFACE_DEFINED__
+#define __IAMFilterMiscFlags_INTERFACE_DEFINED__
+#define INTERFACE IAMFilterMiscFlags
+DECLARE_INTERFACE_(IAMFilterMiscFlags ,IUnknown)
+{
+ STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ STDMETHOD_(ULONG,GetMiscFlags)(THIS) PURE;
+};
+#undef INTERFACE
+#endif
+
+#ifndef __IFileSourceFilter_INTERFACE_DEFINED__
+#define __IFileSourceFilter_INTERFACE_DEFINED__
+#define INTERFACE IFileSourceFilter
+DECLARE_INTERFACE_(IFileSourceFilter ,IUnknown)
+{
+ STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ STDMETHOD(Load)(THIS_ LPCOLESTR, const AM_MEDIA_TYPE *) PURE;
+ STDMETHOD(GetCurFile)(THIS_ LPOLESTR *ppszFileName, AM_MEDIA_TYPE *) PURE;
+};
+#undef INTERFACE
+#endif
+
+#ifndef __IAMOpenProgress_INTERFACE_DEFINED__
+#define __IAMOpenProgress_INTERFACE_DEFINED__
+#define INTERFACE IAMOpenProgress
+DECLARE_INTERFACE_(IAMOpenProgress ,IUnknown)
+{
+ STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ STDMETHOD(QueryProgress)(THIS_ LONGLONG *, LONGLONG *) PURE;
+ STDMETHOD(AbortOperation)(THIS) PURE;
+};
+#undef INTERFACE
+#endif
+
+#ifndef __IFilterChain_INTERFACE_DEFINED__
+#define __IFilterChain_INTERFACE_DEFINED__
+#define INTERFACE IFilterChain
+DECLARE_INTERFACE_(IFilterChain ,IUnknown)
+{
+ STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ STDMETHOD(StartChain)(IBaseFilter *, IBaseFilter *) PURE;
+ STDMETHOD(PauseChain)(IBaseFilter *, IBaseFilter *) PURE;
+ STDMETHOD(StopChain)(IBaseFilter *, IBaseFilter *) PURE;
+ STDMETHOD(RemoveChain)(IBaseFilter *, IBaseFilter *) PURE;
+};
+#undef INTERFACE
+#endif
+
+#endif
diff --git a/src/plugins/directshow/player/directshowioreader.cpp b/src/plugins/directshow/player/directshowioreader.cpp
new file mode 100644
index 000000000..5442f30d9
--- /dev/null
+++ b/src/plugins/directshow/player/directshowioreader.cpp
@@ -0,0 +1,496 @@
+/****************************************************************************
+**
+** 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$
+** 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 "directshowioreader.h"
+
+#include "directshoweventloop.h"
+#include "directshowglobal.h"
+#include "directshowiosource.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qthread.h>
+
+class DirectShowSampleRequest
+{
+public:
+ DirectShowSampleRequest(
+ IMediaSample *sample, DWORD_PTR userData, LONGLONG position, LONG length, BYTE *buffer)
+ : next(0)
+ , sample(sample)
+ , userData(userData)
+ , position(position)
+ , length(length)
+ , buffer(buffer)
+ , result(S_FALSE)
+ {
+ }
+
+ DirectShowSampleRequest *remove() { DirectShowSampleRequest *n = next; delete this; return n; }
+
+ DirectShowSampleRequest *next;
+ IMediaSample *sample;
+ DWORD_PTR userData;
+ LONGLONG position;
+ LONG length;
+ BYTE *buffer;
+ HRESULT result;
+};
+
+DirectShowIOReader::DirectShowIOReader(
+ QIODevice *device, DirectShowIOSource *source, DirectShowEventLoop *loop)
+ : m_source(source)
+ , m_device(device)
+ , m_loop(loop)
+ , m_pendingHead(0)
+ , m_pendingTail(0)
+ , m_readyHead(0)
+ , m_readyTail(0)
+ , m_synchronousPosition(0)
+ , m_synchronousLength(0)
+ , m_synchronousBytesRead(0)
+ , m_synchronousBuffer(0)
+ , m_synchronousResult(S_OK)
+ , m_totalLength(0)
+ , m_availableLength(0)
+ , m_flushing(false)
+{
+ moveToThread(device->thread());
+
+ connect(device, SIGNAL(readyRead()), this, SLOT(readyRead()));
+}
+
+DirectShowIOReader::~DirectShowIOReader()
+{
+ flushRequests();
+}
+
+HRESULT DirectShowIOReader::QueryInterface(REFIID riid, void **ppvObject)
+{
+ return m_source->QueryInterface(riid, ppvObject);
+}
+
+ULONG DirectShowIOReader::AddRef()
+{
+ return m_source->AddRef();
+}
+
+ULONG DirectShowIOReader::Release()
+{
+ return m_source->Release();
+}
+
+// IAsyncReader
+HRESULT DirectShowIOReader::RequestAllocator(
+ IMemAllocator *pPreferred, ALLOCATOR_PROPERTIES *pProps, IMemAllocator **ppActual)
+{
+ if (!ppActual || !pProps) {
+ return E_POINTER;
+ } else {
+ ALLOCATOR_PROPERTIES actualProperties;
+
+ if (pProps->cbAlign == 0)
+ pProps->cbAlign = 1;
+
+ if (pPreferred && pPreferred->SetProperties(pProps, &actualProperties) == S_OK) {
+ pPreferred->AddRef();
+
+ *ppActual = pPreferred;
+
+ m_source->setAllocator(*ppActual);
+
+ return S_OK;
+ } else {
+ *ppActual = com_new<IMemAllocator>(CLSID_MemoryAllocator, IID_IMemAllocator);
+
+ if (*ppActual) {
+ if ((*ppActual)->SetProperties(pProps, &actualProperties) != S_OK) {
+ (*ppActual)->Release();
+ } else {
+ m_source->setAllocator(*ppActual);
+
+ return S_OK;
+ }
+ }
+ }
+ ppActual = 0;
+
+ return E_FAIL;
+ }
+}
+
+HRESULT DirectShowIOReader::Request(IMediaSample *pSample, DWORD_PTR dwUser)
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (!pSample) {
+ return E_POINTER;
+ } else if (m_flushing) {
+ return VFW_E_WRONG_STATE;
+ } else {
+ REFERENCE_TIME startTime = 0;
+ REFERENCE_TIME endTime = 0;
+ BYTE *buffer;
+
+ if (pSample->GetTime(&startTime, &endTime) != S_OK
+ || pSample->GetPointer(&buffer) != S_OK) {
+ return VFW_E_SAMPLE_TIME_NOT_SET;
+ } else {
+ LONGLONG position = startTime / 10000000;
+ LONG length = (endTime - startTime) / 10000000;
+
+ DirectShowSampleRequest *request = new DirectShowSampleRequest(
+ pSample, dwUser, position, length, buffer);
+
+ if (m_pendingTail) {
+ m_pendingTail->next = request;
+ } else {
+ m_pendingHead = request;
+
+ m_loop->postEvent(this, new QEvent(QEvent::User));
+ }
+ m_pendingTail = request;
+
+ return S_OK;
+ }
+ }
+}
+
+HRESULT DirectShowIOReader::WaitForNext(
+ DWORD dwTimeout, IMediaSample **ppSample, DWORD_PTR *pdwUser)
+{
+ if (!ppSample || !pdwUser)
+ return E_POINTER;
+
+ QMutexLocker locker(&m_mutex);
+
+ do {
+ if (m_readyHead) {
+ DirectShowSampleRequest *request = m_readyHead;
+
+ *ppSample = request->sample;
+ *pdwUser = request->userData;
+
+ HRESULT hr = request->result;
+
+ m_readyHead = request->next;
+
+ if (!m_readyHead)
+ m_readyTail = 0;
+
+ delete request;
+
+ return hr;
+ } else if (m_flushing) {
+ *ppSample = 0;
+ *pdwUser = 0;
+
+ return VFW_E_WRONG_STATE;
+ }
+ } while (m_wait.wait(&m_mutex, dwTimeout));
+
+ *ppSample = 0;
+ *pdwUser = 0;
+
+ return VFW_E_TIMEOUT;
+}
+
+HRESULT DirectShowIOReader::SyncReadAligned(IMediaSample *pSample)
+{
+ if (!pSample) {
+ return E_POINTER;
+ } else {
+ REFERENCE_TIME startTime = 0;
+ REFERENCE_TIME endTime = 0;
+ BYTE *buffer;
+
+ if (pSample->GetTime(&startTime, &endTime) != S_OK
+ || pSample->GetPointer(&buffer) != S_OK) {
+ return VFW_E_SAMPLE_TIME_NOT_SET;
+ } else {
+ LONGLONG position = startTime / 10000000;
+ LONG length = (endTime - startTime) / 10000000;
+
+ QMutexLocker locker(&m_mutex);
+
+ if (thread() == QThread::currentThread()) {
+ qint64 bytesRead = 0;
+
+ HRESULT hr = blockingRead(position, length, buffer, &bytesRead);
+
+ if (SUCCEEDED(hr))
+ pSample->SetActualDataLength(bytesRead);
+
+ return hr;
+ } else {
+ m_synchronousPosition = position;
+ m_synchronousLength = length;
+ m_synchronousBuffer = buffer;
+
+ m_loop->postEvent(this, new QEvent(QEvent::User));
+
+ m_wait.wait(&m_mutex);
+
+ m_synchronousBuffer = 0;
+
+ if (SUCCEEDED(m_synchronousResult))
+ pSample->SetActualDataLength(m_synchronousBytesRead);
+
+ return m_synchronousResult;
+ }
+ }
+ }
+}
+
+HRESULT DirectShowIOReader::SyncRead(LONGLONG llPosition, LONG lLength, BYTE *pBuffer)
+{
+ if (!pBuffer) {
+ return E_POINTER;
+ } else {
+ if (thread() == QThread::currentThread()) {
+ qint64 bytesRead;
+
+ return blockingRead(llPosition, lLength, pBuffer, &bytesRead);
+ } else {
+ QMutexLocker locker(&m_mutex);
+
+ m_synchronousPosition = llPosition;
+ m_synchronousLength = lLength;
+ m_synchronousBuffer = pBuffer;
+
+ m_loop->postEvent(this, new QEvent(QEvent::User));
+
+ m_wait.wait(&m_mutex);
+
+ m_synchronousBuffer = 0;
+
+ return m_synchronousResult;
+ }
+ }
+}
+
+HRESULT DirectShowIOReader::Length(LONGLONG *pTotal, LONGLONG *pAvailable)
+{
+ if (!pTotal || !pAvailable) {
+ return E_POINTER;
+ } else {
+ QMutexLocker locker(&m_mutex);
+
+ *pTotal = m_totalLength;
+ *pAvailable = m_availableLength;
+
+ return S_OK;
+ }
+}
+
+
+HRESULT DirectShowIOReader::BeginFlush()
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (m_flushing)
+ return S_FALSE;
+
+ m_flushing = true;
+
+ flushRequests();
+
+ m_wait.wakeAll();
+
+ return S_OK;
+}
+
+HRESULT DirectShowIOReader::EndFlush()
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (!m_flushing)
+ return S_FALSE;
+
+ m_flushing = false;
+
+ return S_OK;
+}
+
+void DirectShowIOReader::customEvent(QEvent *event)
+{
+ if (event->type() == QEvent::User) {
+ readyRead();
+ } else {
+ QObject::customEvent(event);
+ }
+}
+
+void DirectShowIOReader::readyRead()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_availableLength = m_device->bytesAvailable() + m_device->pos();
+ m_totalLength = m_device->size();
+
+ if (m_synchronousBuffer) {
+ if (nonBlockingRead(
+ m_synchronousPosition,
+ m_synchronousLength,
+ m_synchronousBuffer,
+ &m_synchronousBytesRead,
+ &m_synchronousResult)) {
+ m_wait.wakeAll();
+ }
+ } else {
+ qint64 bytesRead = 0;
+
+ while (m_pendingHead && nonBlockingRead(
+ m_pendingHead->position,
+ m_pendingHead->length,
+ m_pendingHead->buffer,
+ &bytesRead,
+ &m_pendingHead->result)) {
+ m_pendingHead->sample->SetActualDataLength(bytesRead);
+
+ if (m_readyTail)
+ m_readyTail->next = m_pendingHead;
+ m_readyTail = m_pendingHead;
+
+ m_pendingHead = m_pendingHead->next;
+
+ m_readyTail->next = 0;
+
+ if (!m_pendingHead)
+ m_pendingTail = 0;
+
+ if (!m_readyHead)
+ m_readyHead = m_readyTail;
+
+ m_wait.wakeAll();
+ }
+ }
+}
+
+HRESULT DirectShowIOReader::blockingRead(
+ LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead)
+{
+ *bytesRead = 0;
+
+ if (qint64(position) > m_device->size())
+ return S_FALSE;
+
+ const qint64 maxSize = qMin<qint64>(m_device->size(), position + length);
+
+ while (m_device->bytesAvailable() + m_device->pos() < maxSize) {
+ if (!m_device->waitForReadyRead(-1))
+ return S_FALSE;
+ }
+
+ if (m_device->pos() != position && !m_device->seek(position))
+ return S_FALSE;
+
+ const qint64 maxBytes = qMin<qint64>(length, m_device->bytesAvailable());
+
+ *bytesRead = m_device->read(reinterpret_cast<char *>(buffer), maxBytes);
+
+ if (*bytesRead != length) {
+ qMemSet(buffer + *bytesRead, 0, length - *bytesRead);
+
+ return S_FALSE;
+ } else {
+ return S_OK;
+ }
+}
+
+bool DirectShowIOReader::nonBlockingRead(
+ LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead, HRESULT *result)
+{
+ const qint64 maxSize = qMin<qint64>(m_device->size(), position + length);
+
+ if (position > m_device->size()) {
+ *bytesRead = 0;
+ *result = S_FALSE;
+
+ return true;
+ } else if (m_device->bytesAvailable() + m_device->pos() >= maxSize) {
+ if (m_device->pos() != position && !m_device->seek(position)) {
+ *bytesRead = 0;
+ *result = S_FALSE;
+
+ return true;
+ } else {
+ const qint64 maxBytes = qMin<qint64>(length, m_device->bytesAvailable());
+
+ *bytesRead = m_device->read(reinterpret_cast<char *>(buffer), maxBytes);
+
+ if (*bytesRead != length) {
+ qMemSet(buffer + *bytesRead, 0, length - *bytesRead);
+
+ *result = S_FALSE;
+ } else {
+ *result = S_OK;
+ }
+
+ return true;
+ }
+ } else {
+ return false;
+ }
+}
+
+void DirectShowIOReader::flushRequests()
+{
+ while (m_pendingHead) {
+ m_pendingHead->result = VFW_E_WRONG_STATE;
+
+ if (m_readyTail)
+ m_readyTail->next = m_pendingHead;
+
+ m_readyTail = m_pendingHead;
+
+ m_pendingHead = m_pendingHead->next;
+
+ m_readyTail->next = 0;
+
+ if (!m_pendingHead)
+ m_pendingTail = 0;
+
+ if (!m_readyHead)
+ m_readyHead = m_readyTail;
+ }
+}
diff --git a/src/plugins/directshow/player/directshowioreader.h b/src/plugins/directshow/player/directshowioreader.h
new file mode 100644
index 000000000..ca398f12e
--- /dev/null
+++ b/src/plugins/directshow/player/directshowioreader.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 DIRECTSHOWIOREADER_H
+#define DIRECTSHOWIOREADER_H
+
+#include <QtCore/qmutex.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qwaitcondition.h>
+
+#include <dshow.h>
+
+QT_BEGIN_NAMESPACE
+class QIODevice;
+QT_END_NAMESPACE
+
+class DirectShowEventLoop;
+class DirectShowIOSource;
+class DirectShowSampleRequest;
+
+class DirectShowIOReader : public QObject, public IAsyncReader
+{
+ Q_OBJECT
+public:
+ DirectShowIOReader(QIODevice *device, DirectShowIOSource *source, DirectShowEventLoop *loop);
+ ~DirectShowIOReader();
+
+ // IUnknown
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ // IAsyncReader
+ HRESULT STDMETHODCALLTYPE RequestAllocator(
+ IMemAllocator *pPreferred, ALLOCATOR_PROPERTIES *pProps, IMemAllocator **ppActual);
+
+ HRESULT STDMETHODCALLTYPE Request(IMediaSample *pSample, DWORD_PTR dwUser);
+
+ HRESULT STDMETHODCALLTYPE WaitForNext(
+ DWORD dwTimeout, IMediaSample **ppSample, DWORD_PTR *pdwUser);
+
+ HRESULT STDMETHODCALLTYPE SyncReadAligned(IMediaSample *pSample);
+
+ HRESULT STDMETHODCALLTYPE SyncRead(LONGLONG llPosition, LONG lLength, BYTE *pBuffer);
+
+ HRESULT STDMETHODCALLTYPE Length(LONGLONG *pTotal, LONGLONG *pAvailable);
+
+ HRESULT STDMETHODCALLTYPE BeginFlush();
+ HRESULT STDMETHODCALLTYPE EndFlush();
+
+protected:
+ void customEvent(QEvent *event);
+
+private Q_SLOTS:
+ void readyRead();
+
+private:
+ HRESULT blockingRead(LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead);
+ bool nonBlockingRead(
+ LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead, HRESULT *result);
+ void flushRequests();
+
+ DirectShowIOSource *m_source;
+ QIODevice *m_device;
+ DirectShowEventLoop *m_loop;
+ DirectShowSampleRequest *m_pendingHead;
+ DirectShowSampleRequest *m_pendingTail;
+ DirectShowSampleRequest *m_readyHead;
+ DirectShowSampleRequest *m_readyTail;
+ LONGLONG m_synchronousPosition;
+ LONG m_synchronousLength;
+ qint64 m_synchronousBytesRead;
+ BYTE *m_synchronousBuffer;
+ HRESULT m_synchronousResult;
+ LONGLONG m_totalLength;
+ LONGLONG m_availableLength;
+ bool m_flushing;
+ QMutex m_mutex;
+ QWaitCondition m_wait;
+};
+
+#endif
diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp
new file mode 100644
index 000000000..c8f3e6a97
--- /dev/null
+++ b/src/plugins/directshow/player/directshowiosource.cpp
@@ -0,0 +1,639 @@
+/****************************************************************************
+**
+** 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$
+** 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 "directshowiosource.h"
+
+#include "directshowglobal.h"
+#include "directshowmediatype.h"
+#include "directshowpinenum.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qurl.h>
+
+static const GUID directshow_subtypes[] =
+{
+ MEDIASUBTYPE_Avi,
+ MEDIASUBTYPE_WAVE,
+ MEDIASUBTYPE_NULL
+};
+
+DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop)
+ : m_ref(1)
+ , m_state(State_Stopped)
+ , m_reader(0)
+ , m_loop(loop)
+ , m_graph(0)
+ , m_clock(0)
+ , m_allocator(0)
+ , m_peerPin(0)
+ , m_pinId(QLatin1String("Data"))
+{
+ QVector<AM_MEDIA_TYPE> mediaTypes;
+
+ AM_MEDIA_TYPE type =
+ {
+ MEDIATYPE_Stream, // majortype
+ MEDIASUBTYPE_NULL, // subtype
+ TRUE, // bFixedSizeSamples
+ FALSE, // bTemporalCompression
+ 1, // lSampleSize
+ GUID_NULL, // formattype
+ 0, // pUnk
+ 0, // cbFormat
+ 0, // pbFormat
+ };
+
+ static const int count = sizeof(directshow_subtypes) / sizeof(GUID);
+
+ for (int i = 0; i < count; ++i) {
+ type.subtype = directshow_subtypes[i];
+ mediaTypes.append(type);
+ }
+
+ setMediaTypes(mediaTypes);
+}
+
+DirectShowIOSource::~DirectShowIOSource()
+{
+ Q_ASSERT(m_ref == 0);
+
+ delete m_reader;
+}
+
+void DirectShowIOSource::setDevice(QIODevice *device)
+{
+ Q_ASSERT(!m_reader);
+
+ m_reader = new DirectShowIOReader(device, this, m_loop);
+}
+
+void DirectShowIOSource::setAllocator(IMemAllocator *allocator)
+{
+ if (m_allocator)
+ m_allocator->Release();
+
+ m_allocator = allocator;
+
+ if (m_allocator)
+ m_allocator->AddRef();
+}
+
+// IUnknown
+HRESULT DirectShowIOSource::QueryInterface(REFIID riid, void **ppvObject)
+{
+ // 2dd74950-a890-11d1-abe8-00a0c905f375
+ static const GUID iid_IAmFilterMiscFlags = {
+ 0x2dd74950, 0xa890, 0x11d1, {0xab, 0xe8, 0x00, 0xa0, 0xc9, 0x05, 0xf3, 0x75}};
+
+ if (!ppvObject) {
+ return E_POINTER;
+ } else if (riid == IID_IUnknown
+ || riid == IID_IPersist
+ || riid == IID_IMediaFilter
+ || riid == IID_IBaseFilter) {
+ *ppvObject = static_cast<IBaseFilter *>(this);
+ } else if (riid == iid_IAmFilterMiscFlags) {
+ *ppvObject = static_cast<IAMFilterMiscFlags *>(this);
+ } else if (riid == IID_IPin) {
+ *ppvObject = static_cast<IPin *>(this);
+ } else if (riid == IID_IAsyncReader) {
+ *ppvObject = static_cast<IAsyncReader *>(m_reader);
+ } else {
+ *ppvObject = 0;
+
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+
+ return S_OK;
+}
+
+ULONG DirectShowIOSource::AddRef()
+{
+ return InterlockedIncrement(&m_ref);
+}
+
+ULONG DirectShowIOSource::Release()
+{
+ ULONG ref = InterlockedDecrement(&m_ref);
+
+ if (ref == 0) {
+ delete this;
+ }
+
+ return ref;
+}
+
+// IPersist
+HRESULT DirectShowIOSource::GetClassID(CLSID *pClassID)
+{
+ *pClassID = CLSID_NULL;
+
+ return S_OK;
+}
+
+// IMediaFilter
+HRESULT DirectShowIOSource::Run(REFERENCE_TIME tStart)
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_state = State_Running;
+
+ return S_OK;
+}
+
+HRESULT DirectShowIOSource::Pause()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_state = State_Paused;
+
+ return S_OK;
+}
+
+HRESULT DirectShowIOSource::Stop()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_state = State_Stopped;
+
+ return S_OK;
+}
+
+HRESULT DirectShowIOSource::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
+{
+ Q_UNUSED(dwMilliSecsTimeout);
+
+ if (!pState) {
+ return E_POINTER;
+ } else {
+ QMutexLocker locker(&m_mutex);
+
+ *pState = m_state;
+
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowIOSource::SetSyncSource(IReferenceClock *pClock)
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (m_clock)
+ m_clock->Release();
+
+ m_clock = pClock;
+
+ if (m_clock)
+ m_clock->AddRef();
+
+ return S_OK;
+}
+
+HRESULT DirectShowIOSource::GetSyncSource(IReferenceClock **ppClock)
+{
+ if (!ppClock) {
+ return E_POINTER;
+ } else {
+ if (!m_clock) {
+ *ppClock = 0;
+
+ return S_FALSE;
+ } else {
+ m_clock->AddRef();
+
+ *ppClock = m_clock;
+
+ return S_OK;
+ }
+ }
+}
+
+// IBaseFilter
+HRESULT DirectShowIOSource::EnumPins(IEnumPins **ppEnum)
+{
+ if (!ppEnum) {
+ return E_POINTER;
+ } else {
+ *ppEnum = new DirectShowPinEnum(QList<IPin *>() << this);
+
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowIOSource::FindPin(LPCWSTR Id, IPin **ppPin)
+{
+ if (!ppPin || !Id) {
+ return E_POINTER;
+ } else {
+ QMutexLocker locker(&m_mutex);
+ if (QString::fromWCharArray(Id) == m_pinId) {
+ AddRef();
+
+ *ppPin = this;
+
+ return S_OK;
+ } else {
+ *ppPin = 0;
+
+ return VFW_E_NOT_FOUND;
+ }
+ }
+}
+
+HRESULT DirectShowIOSource::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName)
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_graph = pGraph;
+ m_filterName = QString::fromWCharArray(pName);
+
+ return S_OK;
+}
+
+HRESULT DirectShowIOSource::QueryFilterInfo(FILTER_INFO *pInfo)
+{
+ if (!pInfo) {
+ return E_POINTER;
+ } else {
+ QString name = m_filterName;
+
+ if (name.length() >= MAX_FILTER_NAME)
+ name.truncate(MAX_FILTER_NAME - 1);
+
+ int length = name.toWCharArray(pInfo->achName);
+ pInfo->achName[length] = '\0';
+
+ if (m_graph)
+ m_graph->AddRef();
+
+ pInfo->pGraph = m_graph;
+
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowIOSource::QueryVendorInfo(LPWSTR *pVendorInfo)
+{
+ Q_UNUSED(pVendorInfo);
+
+ return E_NOTIMPL;
+}
+
+// IAMFilterMiscFlags
+ULONG DirectShowIOSource::GetMiscFlags()
+{
+ return AM_FILTER_MISC_FLAGS_IS_SOURCE;
+}
+
+// IPin
+HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
+{
+ QMutexLocker locker(&m_mutex);
+ if (!pReceivePin) {
+ return E_POINTER;
+ } else if (m_state != State_Stopped) {
+ return VFW_E_NOT_STOPPED;
+ } else if (m_peerPin) {
+ return VFW_E_ALREADY_CONNECTED;
+ } else {
+ HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED;
+
+ m_peerPin = pReceivePin;
+ m_peerPin->AddRef();
+
+ if (!pmt) {
+ IEnumMediaTypes *mediaTypes = 0;
+ if (pReceivePin->EnumMediaTypes(&mediaTypes) == S_OK) {
+ for (AM_MEDIA_TYPE *type = 0;
+ mediaTypes->Next(1, &type, 0) == S_OK;
+ DirectShowMediaType::deleteType(type)) {
+ switch (tryConnect(pReceivePin, type)) {
+ case S_OK:
+ DirectShowMediaType::freeData(type);
+ mediaTypes->Release();
+ return S_OK;
+ case VFW_E_NO_TRANSPORT:
+ hr = VFW_E_NO_TRANSPORT;
+ break;
+ default:
+ break;
+ }
+ }
+ mediaTypes->Release();
+ }
+ AM_MEDIA_TYPE type =
+ {
+ MEDIATYPE_Stream, // majortype
+ MEDIASUBTYPE_NULL, // subtype
+ TRUE, // bFixedSizeSamples
+ FALSE, // bTemporalCompression
+ 1, // lSampleSize
+ GUID_NULL, // formattype
+ 0, // pUnk
+ 0, // cbFormat
+ 0, // pbFormat
+ };
+
+ static const int count = sizeof(directshow_subtypes) / sizeof(GUID);
+
+ for (int i = 0; i < count; ++i) {
+ type.subtype = directshow_subtypes[i];
+
+ switch (tryConnect(pReceivePin, &type)) {
+ case S_OK:
+ return S_OK;
+ case VFW_E_NO_TRANSPORT:
+ hr = VFW_E_NO_TRANSPORT;
+ break;
+ default:
+ break;
+ }
+ }
+ } else if (pmt->majortype == MEDIATYPE_Stream && (hr = tryConnect(pReceivePin, pmt))) {
+ return S_OK;
+ }
+
+ m_peerPin->Release();
+ m_peerPin = 0;
+
+ m_mediaType.clear();
+
+ return hr;
+ }
+}
+
+HRESULT DirectShowIOSource::tryConnect(IPin *pin, const AM_MEDIA_TYPE *type)
+{
+ m_mediaType = *type;
+
+ HRESULT hr = pin->ReceiveConnection(this, type);
+
+ if (!SUCCEEDED(hr)) {
+ if (m_allocator) {
+ m_allocator->Release();
+ m_allocator = 0;
+ }
+ } else if (!m_allocator) {
+ hr = VFW_E_NO_TRANSPORT;
+
+ if (IMemInputPin *memPin = com_cast<IMemInputPin>(pin, IID_IMemInputPin)) {
+ if ((m_allocator = com_new<IMemAllocator>(CLSID_MemoryAllocator, IID_IMemAllocator))) {
+ ALLOCATOR_PROPERTIES properties;
+ if (memPin->GetAllocatorRequirements(&properties) == S_OK
+ || m_allocator->GetProperties(&properties) == S_OK) {
+ if (properties.cbAlign == 0)
+ properties.cbAlign = 1;
+
+ ALLOCATOR_PROPERTIES actualProperties;
+ if (SUCCEEDED(hr = m_allocator->SetProperties(&properties, &actualProperties)))
+ hr = memPin->NotifyAllocator(m_allocator, TRUE);
+ }
+ if (!SUCCEEDED(hr)) {
+ m_allocator->Release();
+ m_allocator = 0;
+ }
+ }
+ memPin->Release();
+ }
+ if (!SUCCEEDED(hr))
+ pin->Disconnect();
+ }
+ return hr;
+}
+
+HRESULT DirectShowIOSource::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
+{
+ Q_UNUSED(pConnector);
+ Q_UNUSED(pmt);
+ // Output pin.
+ return E_NOTIMPL;
+}
+
+HRESULT DirectShowIOSource::Disconnect()
+{
+ if (!m_peerPin) {
+ return S_FALSE;
+ } else if (m_state != State_Stopped) {
+ return VFW_E_NOT_STOPPED;
+ } else {
+ HRESULT hr = m_peerPin->Disconnect();
+
+ if (!SUCCEEDED(hr))
+ return hr;
+
+ if (m_allocator) {
+ m_allocator->Release();
+ m_allocator = 0;
+ }
+
+ m_peerPin->Release();
+ m_peerPin = 0;
+
+ m_mediaType.clear();
+
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowIOSource::ConnectedTo(IPin **ppPin)
+{
+ if (!ppPin) {
+ return E_POINTER;
+ } else {
+ QMutexLocker locker(&m_mutex);
+
+ if (!m_peerPin) {
+ *ppPin = 0;
+
+ return VFW_E_NOT_CONNECTED;
+ } else {
+ m_peerPin->AddRef();
+
+ *ppPin = m_peerPin;
+
+ return S_OK;
+ }
+ }
+}
+
+HRESULT DirectShowIOSource::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
+{
+ if (!pmt) {
+ return E_POINTER;
+ } else {
+ QMutexLocker locker(&m_mutex);
+
+ if (!m_peerPin) {
+ pmt = 0;
+
+ return VFW_E_NOT_CONNECTED;
+ } else {
+ DirectShowMediaType::copy(pmt, m_mediaType);
+
+ return S_OK;
+ }
+ }
+}
+
+HRESULT DirectShowIOSource::QueryPinInfo(PIN_INFO *pInfo)
+{
+ if (!pInfo) {
+ return E_POINTER;
+ } else {
+ AddRef();
+
+ pInfo->pFilter = this;
+ pInfo->dir = PINDIR_OUTPUT;
+
+ const int bytes = qMin(MAX_FILTER_NAME, (m_pinId.length() + 1) * 2);
+
+ qMemCopy(pInfo->achName, m_pinId.utf16(), bytes);
+
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowIOSource::QueryId(LPWSTR *Id)
+{
+ if (!Id) {
+ return E_POINTER;
+ } else {
+ const int bytes = (m_pinId.length() + 1) * 2;
+
+ *Id = static_cast<LPWSTR>(::CoTaskMemAlloc(bytes));
+
+ qMemCopy(*Id, m_pinId.utf16(), bytes);
+
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowIOSource::QueryAccept(const AM_MEDIA_TYPE *pmt)
+{
+ if (!pmt) {
+ return E_POINTER;
+ } else if (pmt->majortype == MEDIATYPE_Stream) {
+ return S_OK;
+ } else {
+ return S_FALSE;
+ }
+}
+
+HRESULT DirectShowIOSource::EnumMediaTypes(IEnumMediaTypes **ppEnum)
+{
+ if (!ppEnum) {
+ return E_POINTER;
+ } else {
+ *ppEnum = createMediaTypeEnum();
+
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowIOSource::QueryInternalConnections(IPin **apPin, ULONG *nPin)
+{
+ Q_UNUSED(apPin);
+ Q_UNUSED(nPin);
+
+ return E_NOTIMPL;
+}
+
+HRESULT DirectShowIOSource::EndOfStream()
+{
+ return S_OK;
+}
+
+HRESULT DirectShowIOSource::BeginFlush()
+{
+ return m_reader->BeginFlush();
+}
+
+HRESULT DirectShowIOSource::EndFlush()
+{
+ return m_reader->EndFlush();
+}
+
+HRESULT DirectShowIOSource::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
+{
+ Q_UNUSED(tStart);
+ Q_UNUSED(tStop);
+ Q_UNUSED(dRate);
+
+ return S_OK;
+}
+
+HRESULT DirectShowIOSource::QueryDirection(PIN_DIRECTION *pPinDir)
+{
+ if (!pPinDir) {
+ return E_POINTER;
+ } else {
+ *pPinDir = PINDIR_OUTPUT;
+
+ return S_OK;
+ }
+}
+
+DirectShowRcSource::DirectShowRcSource(DirectShowEventLoop *loop)
+ : DirectShowIOSource(loop)
+{
+}
+
+bool DirectShowRcSource::open(const QUrl &url)
+{
+ m_file.moveToThread(QCoreApplication::instance()->thread());
+
+ m_file.setFileName(QLatin1Char(':') + url.path());
+
+ qDebug("qrc file %s", qPrintable(m_file.fileName()));
+
+ if (m_file.open(QIODevice::ReadOnly)) {
+ qDebug("Size %d", m_file.size());
+ qDebug("Sequential %d", int(m_file.isSequential()));
+
+ setDevice(&m_file);
+
+ return true;
+ } else {
+ return false;
+ }
+}
diff --git a/src/plugins/directshow/player/directshowiosource.h b/src/plugins/directshow/player/directshowiosource.h
new file mode 100644
index 000000000..3019bdbe9
--- /dev/null
+++ b/src/plugins/directshow/player/directshowiosource.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** 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$
+** 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 DIRECTSHOWIOSOURCE_H
+#define DIRECTSHOWIOSOURCE_H
+
+#include "directshowglobal.h"
+#include "directshowioreader.h"
+#include "directshowmediatype.h"
+#include "directshowmediatypelist.h"
+
+#include <QtCore/qfile.h>
+
+class DirectShowIOSource
+ : public DirectShowMediaTypeList
+ , public IBaseFilter
+ , public IAMFilterMiscFlags
+ , public IPin
+{
+public:
+ DirectShowIOSource(DirectShowEventLoop *loop);
+ ~DirectShowIOSource();
+
+ void setDevice(QIODevice *device);
+ void setAllocator(IMemAllocator *allocator);
+
+ // IUnknown
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ // IPersist
+ HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
+
+ // IMediaFilter
+ HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
+ HRESULT STDMETHODCALLTYPE Pause();
+ HRESULT STDMETHODCALLTYPE Stop();
+
+ HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState);
+
+ HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
+ HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **ppClock);
+
+ // IBaseFilter
+ HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
+ HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
+
+ HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
+
+ HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
+ HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
+
+ // IAMFilterMiscFlags
+ ULONG STDMETHODCALLTYPE GetMiscFlags();
+
+ // IPin
+ HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
+ HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
+ HRESULT STDMETHODCALLTYPE Disconnect();
+ HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **ppPin);
+
+ HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
+
+ HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
+ HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
+
+ HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
+
+ HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
+
+ HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
+
+ HRESULT STDMETHODCALLTYPE EndOfStream();
+
+ HRESULT STDMETHODCALLTYPE BeginFlush();
+ HRESULT STDMETHODCALLTYPE EndFlush();
+
+ HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
+
+ HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
+
+private:
+ HRESULT tryConnect(IPin *pin, const AM_MEDIA_TYPE *type);
+
+ volatile LONG m_ref;
+ FILTER_STATE m_state;
+ DirectShowIOReader *m_reader;
+ DirectShowEventLoop *m_loop;
+ IFilterGraph *m_graph;
+ IReferenceClock *m_clock;
+ IMemAllocator *m_allocator;
+ IPin *m_peerPin;
+ DirectShowMediaType m_mediaType;
+ QString m_filterName;
+ const QString m_pinId;
+ QMutex m_mutex;
+};
+
+class DirectShowRcSource : public DirectShowIOSource
+{
+public:
+ DirectShowRcSource(DirectShowEventLoop *loop);
+
+ bool open(const QUrl &url);
+
+private:
+ QFile m_file;
+};
+
+#endif
diff --git a/src/plugins/directshow/player/directshowmediatype.cpp b/src/plugins/directshow/player/directshowmediatype.cpp
new file mode 100644
index 000000000..667d9491e
--- /dev/null
+++ b/src/plugins/directshow/player/directshowmediatype.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** 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$
+** 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 "directshowmediatype.h"
+
+namespace
+{
+ struct TypeLookup
+ {
+ QVideoFrame::PixelFormat pixelFormat;
+ GUID mediaType;
+ };
+
+ static const TypeLookup qt_typeLookup[] =
+ {
+ { QVideoFrame::Format_RGB32, /*MEDIASUBTYPE_RGB32*/ {0xe436eb7e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
+ { QVideoFrame::Format_BGR24, /*MEDIASUBTYPE_RGB24*/ {0xe436eb7d, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
+ { QVideoFrame::Format_RGB565, /*MEDIASUBTYPE_RGB565*/ {0xe436eb7b, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
+ { QVideoFrame::Format_RGB555, /*MEDIASUBTYPE_RGB555*/ {0xe436eb7c, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} },
+ { QVideoFrame::Format_AYUV444, /*MEDIASUBTYPE_AYUV*/ {0x56555941, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
+ { QVideoFrame::Format_YUYV, /*MEDIASUBTYPE_YUY2*/ {0x32595559, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
+ { QVideoFrame::Format_UYVY, /*MEDIASUBTYPE_UYVY*/ {0x59565955, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
+ { QVideoFrame::Format_IMC1, /*MEDIASUBTYPE_IMC1*/ {0x31434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
+ { QVideoFrame::Format_IMC2, /*MEDIASUBTYPE_IMC2*/ {0x32434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
+ { QVideoFrame::Format_IMC3, /*MEDIASUBTYPE_IMC3*/ {0x33434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
+ { QVideoFrame::Format_IMC4, /*MEDIASUBTYPE_IMC4*/ {0x34434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
+ { QVideoFrame::Format_YV12, /*MEDIASUBTYPE_YV12*/ {0x32315659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
+ { QVideoFrame::Format_NV12, /*MEDIASUBTYPE_NV12*/ {0x3231564E, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} },
+ { QVideoFrame::Format_YUV420P, /*MEDIASUBTYPE_IYUV*/ {0x56555949, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }
+ };
+}
+
+void DirectShowMediaType::copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source)
+{
+ *target = source;
+
+ if (source.cbFormat > 0) {
+ target->pbFormat = reinterpret_cast<PBYTE>(CoTaskMemAlloc(source.cbFormat));
+ memcpy(target->pbFormat, source.pbFormat, source.cbFormat);
+ }
+ if (target->pUnk)
+ target->pUnk->AddRef();
+}
+
+void DirectShowMediaType::deleteType(AM_MEDIA_TYPE *type)
+{
+ freeData(type);
+
+ CoTaskMemFree(type);
+}
+
+void DirectShowMediaType::freeData(AM_MEDIA_TYPE *type)
+{
+ if (type->cbFormat > 0)
+ CoTaskMemFree(type->pbFormat);
+
+ if (type->pUnk)
+ type->pUnk->Release();
+}
+
+
+GUID DirectShowMediaType::convertPixelFormat(QVideoFrame::PixelFormat format)
+{
+ // MEDIASUBTYPE_None;
+ static const GUID none = {
+ 0xe436eb8e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} };
+
+ const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup);
+
+ for (int i = 0; i < count; ++i)
+ if (qt_typeLookup[i].pixelFormat == format)
+ return qt_typeLookup[i].mediaType;
+ return none;
+}
+
+QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &type)
+{
+ const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup);
+
+ for (int i = 0; i < count; ++i) {
+ if (IsEqualGUID(qt_typeLookup[i].mediaType, type.subtype) && type.cbFormat > 0) {
+ if (IsEqualGUID(type.formattype, FORMAT_VideoInfo)) {
+ VIDEOINFOHEADER *header = reinterpret_cast<VIDEOINFOHEADER *>(type.pbFormat);
+
+ QVideoSurfaceFormat format(
+ QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)),
+ qt_typeLookup[i].pixelFormat);
+
+ if (header->AvgTimePerFrame > 0)
+ format.setFrameRate(10000 /header->AvgTimePerFrame);
+
+ format.setScanLineDirection(header->bmiHeader.biHeight < 0
+ ? QVideoSurfaceFormat::TopToBottom
+ : QVideoSurfaceFormat::BottomToTop);
+
+ return format;
+ } else if (IsEqualGUID(type.formattype, FORMAT_VideoInfo2)) {
+ VIDEOINFOHEADER2 *header = reinterpret_cast<VIDEOINFOHEADER2 *>(type.pbFormat);
+
+ QVideoSurfaceFormat format(
+ QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)),
+ qt_typeLookup[i].pixelFormat);
+
+ if (header->AvgTimePerFrame > 0)
+ format.setFrameRate(10000 / header->AvgTimePerFrame);
+
+ format.setScanLineDirection(header->bmiHeader.biHeight < 0
+ ? QVideoSurfaceFormat::TopToBottom
+ : QVideoSurfaceFormat::BottomToTop);
+
+ return format;
+ }
+ }
+ }
+ return QVideoSurfaceFormat();
+}
+
+int DirectShowMediaType::bytesPerLine(const QVideoSurfaceFormat &format)
+{
+ switch (format.pixelFormat()) {
+ // 32 bpp packed formats.
+ case QVideoFrame::Format_RGB32:
+ case QVideoFrame::Format_AYUV444:
+ return format.frameWidth() * 4;
+ // 24 bpp packed formats.
+ case QVideoFrame::Format_RGB24:
+ return format.frameWidth() * 3 + 3 - format.frameWidth() % 4;
+ // 16 bpp packed formats.
+ case QVideoFrame::Format_RGB565:
+ case QVideoFrame::Format_RGB555:
+ case QVideoFrame::Format_YUYV:
+ case QVideoFrame::Format_UYVY:
+ return format.frameWidth() * 2 + 3 - format.frameWidth() % 4;
+ // Planar formats.
+ case QVideoFrame::Format_IMC1:
+ case QVideoFrame::Format_IMC2:
+ case QVideoFrame::Format_IMC3:
+ case QVideoFrame::Format_IMC4:
+ case QVideoFrame::Format_YV12:
+ case QVideoFrame::Format_NV12:
+ case QVideoFrame::Format_YUV420P:
+ return format.frameWidth() + 3 - format.frameWidth() % 4;
+ default:
+ return 0;
+ }
+}
diff --git a/src/plugins/directshow/player/directshowmediatype.h b/src/plugins/directshow/player/directshowmediatype.h
new file mode 100644
index 000000000..7d37a5c29
--- /dev/null
+++ b/src/plugins/directshow/player/directshowmediatype.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 DIRECTSHOWMEDIATYPE_H
+#define DIRECTSHOWMEDIATYPE_H
+
+#include <qvideosurfaceformat.h>
+
+#include <dshow.h>
+#include <dvdmedia.h>
+
+class DirectShowMediaType : public AM_MEDIA_TYPE
+{
+public:
+ DirectShowMediaType() { memset(this, 0, sizeof(DirectShowMediaType)); }
+ DirectShowMediaType(const AM_MEDIA_TYPE &type) { copy(this, type); }
+ DirectShowMediaType(const DirectShowMediaType &other) { copy(this, other); }
+ DirectShowMediaType &operator =(const AM_MEDIA_TYPE &type) {
+ freeData(this); copy(this, type); return *this; }
+ DirectShowMediaType &operator =(const DirectShowMediaType &other) {
+ freeData(this); copy(this, other); return *this; }
+ ~DirectShowMediaType() { freeData(this); }
+
+ void clear() { freeData(this); memset(this, 0, sizeof(DirectShowMediaType)); }
+
+ static void copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source);
+ static void freeData(AM_MEDIA_TYPE *type);
+ static void deleteType(AM_MEDIA_TYPE *type);
+
+ static GUID convertPixelFormat(QVideoFrame::PixelFormat format);
+ static QVideoSurfaceFormat formatFromType(const AM_MEDIA_TYPE &type);
+
+ static int bytesPerLine(const QVideoSurfaceFormat &format);
+};
+
+#endif
diff --git a/src/plugins/directshow/player/directshowmediatypelist.cpp b/src/plugins/directshow/player/directshowmediatypelist.cpp
new file mode 100644
index 000000000..3060975fc
--- /dev/null
+++ b/src/plugins/directshow/player/directshowmediatypelist.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** 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$
+** 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 "directshowmediatypelist.h"
+
+#include "directshowmediatype.h"
+#include "videosurfacefilter.h"
+
+
+class DirectShowMediaTypeEnum : public IEnumMediaTypes
+{
+public:
+ DirectShowMediaTypeEnum(DirectShowMediaTypeList *list, int token, int index = 0);
+ ~DirectShowMediaTypeEnum();
+
+ // IUnknown
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ // IEnumMediaTypes
+ HRESULT STDMETHODCALLTYPE Next(
+ ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched);
+ HRESULT STDMETHODCALLTYPE Skip(ULONG cMediaTypes);
+ HRESULT STDMETHODCALLTYPE Reset();
+
+ HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes **ppEnum);
+
+private:
+ LONG m_ref;
+ DirectShowMediaTypeList *m_list;
+ int m_mediaTypeToken;
+ int m_index;
+};
+
+
+DirectShowMediaTypeEnum::DirectShowMediaTypeEnum(
+ DirectShowMediaTypeList *list, int token, int index)
+ : m_ref(1)
+ , m_list(list)
+ , m_mediaTypeToken(token)
+ , m_index(index)
+{
+ m_list->AddRef();
+}
+
+DirectShowMediaTypeEnum::~DirectShowMediaTypeEnum()
+{
+ m_list->Release();
+}
+
+HRESULT DirectShowMediaTypeEnum::QueryInterface(REFIID riid, void **ppvObject)
+{
+ if (!ppvObject) {
+ return E_POINTER;
+ } else if (riid == IID_IUnknown
+ || riid == IID_IEnumMediaTypes) {
+ *ppvObject = static_cast<IEnumMediaTypes *>(this);
+ } else {
+ *ppvObject = 0;
+
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+
+ return S_OK;
+}
+
+ULONG DirectShowMediaTypeEnum::AddRef()
+{
+ return InterlockedIncrement(&m_ref);
+}
+
+ULONG DirectShowMediaTypeEnum::Release()
+{
+ ULONG ref = InterlockedDecrement(&m_ref);
+
+ if (ref == 0) {
+ delete this;
+ }
+
+ return ref;
+}
+
+HRESULT DirectShowMediaTypeEnum::Next(
+ ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched)
+{
+ return m_list->nextMediaType(m_mediaTypeToken, &m_index, cMediaTypes, ppMediaTypes, pcFetched);
+}
+
+HRESULT DirectShowMediaTypeEnum::Skip(ULONG cMediaTypes)
+{
+ return m_list->skipMediaType(m_mediaTypeToken, &m_index, cMediaTypes);
+}
+
+HRESULT DirectShowMediaTypeEnum::Reset()
+{
+ m_mediaTypeToken = m_list->currentMediaTypeToken();
+ m_index = 0;
+
+ return S_OK;
+}
+
+HRESULT DirectShowMediaTypeEnum::Clone(IEnumMediaTypes **ppEnum)
+{
+ return m_list->cloneMediaType(m_mediaTypeToken, m_index, ppEnum);
+}
+
+
+DirectShowMediaTypeList::DirectShowMediaTypeList()
+ : m_mediaTypeToken(0)
+{
+}
+
+IEnumMediaTypes *DirectShowMediaTypeList::createMediaTypeEnum()
+{
+ return new DirectShowMediaTypeEnum(this, m_mediaTypeToken, 0);
+}
+
+
+void DirectShowMediaTypeList::setMediaTypes(const QVector<AM_MEDIA_TYPE> &types)
+{
+ ++m_mediaTypeToken;
+
+ m_mediaTypes = types;
+}
+
+
+int DirectShowMediaTypeList::currentMediaTypeToken()
+{
+ return m_mediaTypeToken;
+}
+
+HRESULT DirectShowMediaTypeList::nextMediaType(
+ int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount)
+{
+ if (!types || (count != 1 && !fetchedCount)) {
+ return E_POINTER;
+ } else if (m_mediaTypeToken != token) {
+ return VFW_E_ENUM_OUT_OF_SYNC;
+ } else {
+ int boundedCount = qBound<int>(0, count, m_mediaTypes.count() - *index);
+
+ for (int i = 0; i < boundedCount; ++i, ++(*index)) {
+ types[i] = reinterpret_cast<AM_MEDIA_TYPE *>(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)));
+
+ if (types[i]) {
+ DirectShowMediaType::copy(types[i], m_mediaTypes.at(*index));
+ } else {
+ for (--i; i >= 0; --i)
+ CoTaskMemFree(types[i]);
+
+ if (fetchedCount)
+ *fetchedCount = 0;
+
+ return E_OUTOFMEMORY;
+ }
+ }
+ if (fetchedCount)
+ *fetchedCount = boundedCount;
+
+ return boundedCount == count ? S_OK : S_FALSE;
+ }
+}
+
+HRESULT DirectShowMediaTypeList::skipMediaType(int token, int *index, ULONG count)
+{
+ if (m_mediaTypeToken != token) {
+ return VFW_E_ENUM_OUT_OF_SYNC;
+ } else {
+ *index = qMin<int>(*index + count, m_mediaTypes.size());
+
+ return *index < m_mediaTypes.size() ? S_OK : S_FALSE;
+ }
+}
+
+HRESULT DirectShowMediaTypeList::cloneMediaType(int token, int index, IEnumMediaTypes **enumeration)
+{
+ if (m_mediaTypeToken != token) {
+ return VFW_E_ENUM_OUT_OF_SYNC;
+ } else {
+ *enumeration = new DirectShowMediaTypeEnum(this, token, index);
+
+ return S_OK;
+ }
+}
+
diff --git a/src/plugins/directshow/player/directshowmediatypelist.h b/src/plugins/directshow/player/directshowmediatypelist.h
new file mode 100644
index 000000000..1b33606cb
--- /dev/null
+++ b/src/plugins/directshow/player/directshowmediatypelist.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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$
+** 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 DIRECTSHOWMEDIATYPELIST_H
+#define DIRECTSHOWMEDIATYPELIST_H
+
+#include <QtCore/qvector.h>
+
+#include <dshow.h>
+
+class DirectShowMediaTypeList : public IUnknown
+{
+public:
+ DirectShowMediaTypeList();
+
+ IEnumMediaTypes *createMediaTypeEnum();
+
+ void setMediaTypes(const QVector<AM_MEDIA_TYPE> &types);
+
+ virtual int currentMediaTypeToken();
+ virtual HRESULT nextMediaType(
+ int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount);
+ virtual HRESULT skipMediaType(int token, int *index, ULONG count);
+ virtual HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration);
+
+private:
+ int m_mediaTypeToken;
+ QVector<AM_MEDIA_TYPE> m_mediaTypes;
+};
+
+#endif
diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.cpp b/src/plugins/directshow/player/directshowmetadatacontrol.cpp
new file mode 100644
index 000000000..40c3920b4
--- /dev/null
+++ b/src/plugins/directshow/player/directshowmetadatacontrol.cpp
@@ -0,0 +1,352 @@
+/****************************************************************************
+**
+** 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$
+** 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 <dshow.h>
+#include <initguid.h>
+#include <qnetwork.h>
+
+#include "directshowmetadatacontrol.h"
+
+#include "directshowplayerservice.h"
+
+#include <QtCore/qcoreapplication.h>
+
+#ifndef QT_NO_WMSDK
+namespace
+{
+ struct QWMMetaDataKeyLookup
+ {
+ QtMultimediaKit::MetaData key;
+ const wchar_t *token;
+ };
+}
+
+static const QWMMetaDataKeyLookup qt_wmMetaDataKeys[] =
+{
+ { QtMultimediaKit::Title, L"Title" },
+ { QtMultimediaKit::SubTitle, L"WM/SubTitle" },
+ { QtMultimediaKit::Author, L"Author" },
+ { QtMultimediaKit::Comment, L"Comment" },
+ { QtMultimediaKit::Description, L"Description" },
+ { QtMultimediaKit::Category, L"WM/Category" },
+ { QtMultimediaKit::Genre, L"WM/Genre" },
+ //{ QtMultimediaKit::Date, 0 },
+ { QtMultimediaKit::Year, L"WM/Year" },
+ { QtMultimediaKit::UserRating, L"UserRating" },
+ //{ QtMultimediaKit::MetaDatawords, 0 },
+ { QtMultimediaKit::Language, L"Language" },
+ { QtMultimediaKit::Publisher, L"WM/Publisher" },
+ { QtMultimediaKit::Copyright, L"Copyright" },
+ { QtMultimediaKit::ParentalRating, L"ParentalRating" },
+ { QtMultimediaKit::RatingOrganisation, L"RatingOrganisation" },
+
+ // Media
+ { QtMultimediaKit::Size, L"FileSize" },
+ { QtMultimediaKit::MediaType, L"MediaType" },
+ { QtMultimediaKit::Duration, L"Duration" },
+
+ // Audio
+ { QtMultimediaKit::AudioBitRate, L"AudioBitRate" },
+ { QtMultimediaKit::AudioCodec, L"AudioCodec" },
+ { QtMultimediaKit::ChannelCount, L"ChannelCount" },
+ { QtMultimediaKit::SampleRate, L"Frequency" },
+
+ // Music
+ { QtMultimediaKit::AlbumTitle, L"WM/AlbumTitle" },
+ { QtMultimediaKit::AlbumArtist, L"WM/AlbumArtist" },
+ { QtMultimediaKit::ContributingArtist, L"Author" },
+ { QtMultimediaKit::Composer, L"WM/Composer" },
+ { QtMultimediaKit::Conductor, L"WM/Conductor" },
+ { QtMultimediaKit::Lyrics, L"WM/Lyrics" },
+ { QtMultimediaKit::Mood, L"WM/Mood" },
+ { QtMultimediaKit::TrackNumber, L"WM/TrackNumber" },
+ //{ QtMultimediaKit::TrackCount, 0 },
+ //{ QtMultimediaKit::CoverArtUriSmall, 0 },
+ //{ QtMultimediaKit::CoverArtUriLarge, 0 },
+
+ // Image/Video
+ //{ QtMultimediaKit::Resolution, 0 },
+ //{ QtMultimediaKit::PixelAspectRatio, 0 },
+
+ // Video
+ //{ QtMultimediaKit::FrameRate, 0 },
+ { QtMultimediaKit::VideoBitRate, L"VideoBitRate" },
+ { QtMultimediaKit::VideoCodec, L"VideoCodec" },
+
+ //{ QtMultimediaKit::PosterUri, 0 },
+
+ // Movie
+ { QtMultimediaKit::ChapterNumber, L"ChapterNumber" },
+ { QtMultimediaKit::Director, L"WM/Director" },
+ { QtMultimediaKit::LeadPerformer, L"LeadPerformer" },
+ { QtMultimediaKit::Writer, L"WM/Writer" },
+
+ // Photos
+ { QtMultimediaKit::CameraManufacturer, L"CameraManufacturer" },
+ { QtMultimediaKit::CameraModel, L"CameraModel" },
+ { QtMultimediaKit::Event, L"Event" },
+ { QtMultimediaKit::Subject, L"Subject" }
+};
+
+static QVariant getValue(IWMHeaderInfo *header, const wchar_t *key)
+{
+ WORD streamNumber = 0;
+ WMT_ATTR_DATATYPE type = WMT_TYPE_DWORD;
+ WORD size = 0;
+
+ if (header->GetAttributeByName(&streamNumber, key, &type, 0, &size) == S_OK) {
+ switch (type) {
+ case WMT_TYPE_DWORD:
+ if (size == sizeof(DWORD)) {
+ DWORD word;
+ if (header->GetAttributeByName(
+ &streamNumber,
+ key,
+ &type,
+ reinterpret_cast<BYTE *>(&word),
+ &size) == S_OK) {
+ return int(word);
+ }
+ }
+ break;
+ case WMT_TYPE_STRING:
+ {
+ QString string;
+ string.resize(size / 2 - 1);
+
+ if (header->GetAttributeByName(
+ &streamNumber,
+ key,
+ &type,
+ reinterpret_cast<BYTE *>(const_cast<ushort *>(string.utf16())),
+ &size) == S_OK) {
+ return string;
+ }
+ }
+ break;
+ case WMT_TYPE_BINARY:
+ {
+ QByteArray bytes;
+ bytes.resize(size);
+ if (header->GetAttributeByName(
+ &streamNumber,
+ key,
+ &type,
+ reinterpret_cast<BYTE *>(bytes.data()),
+ &size) == S_OK) {
+ return bytes;
+ }
+ }
+ break;
+ case WMT_TYPE_BOOL:
+ if (size == sizeof(DWORD)) {
+ DWORD word;
+ if (header->GetAttributeByName(
+ &streamNumber,
+ key,
+ &type,
+ reinterpret_cast<BYTE *>(&word),
+ &size) == S_OK) {
+ return bool(word);
+ }
+ }
+ break;
+ case WMT_TYPE_QWORD:
+ if (size == sizeof(QWORD)) {
+ QWORD word;
+ if (header->GetAttributeByName(
+ &streamNumber,
+ key,
+ &type,
+ reinterpret_cast<BYTE *>(&word),
+ &size) == S_OK) {
+ return qint64(word);
+ }
+ }
+ break;
+ case WMT_TYPE_WORD:
+ if (size == sizeof(WORD)){
+ WORD word;
+ if (header->GetAttributeByName(
+ &streamNumber,
+ key,
+ &type,
+ reinterpret_cast<BYTE *>(&word),
+ &size) == S_OK) {
+ return short(word);
+ }
+ }
+ break;
+ case WMT_TYPE_GUID:
+ if (size == 16) {
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return QVariant();
+}
+#endif
+
+DirectShowMetaDataControl::DirectShowMetaDataControl(QObject *parent)
+ : QMetaDataReaderControl(parent)
+ , m_content(0)
+#ifndef QT_NO_WMSDK
+ , m_headerInfo(0)
+#endif
+{
+}
+
+DirectShowMetaDataControl::~DirectShowMetaDataControl()
+{
+}
+
+bool DirectShowMetaDataControl::isMetaDataAvailable() const
+{
+#ifndef QT_NO_WMSDK
+ return m_content || m_headerInfo;
+#else
+ return m_content;
+#endif
+}
+
+QVariant DirectShowMetaDataControl::metaData(QtMultimediaKit::MetaData key) const
+{
+ QVariant value;
+
+#ifndef QT_NO_WMSDK
+ if (m_headerInfo) {
+ static const int count = sizeof(qt_wmMetaDataKeys) / sizeof(QWMMetaDataKeyLookup);
+ for (int i = 0; i < count; ++i) {
+ if (qt_wmMetaDataKeys[i].key == key) {
+ value = getValue(m_headerInfo, qt_wmMetaDataKeys[i].token);
+ break;
+ }
+ }
+ } else if (m_content) {
+#else
+ if (m_content) {
+#endif
+ BSTR string = 0;
+
+ switch (key) {
+ case QtMultimediaKit::Author:
+ m_content->get_AuthorName(&string);
+ break;
+ case QtMultimediaKit::Title:
+ m_content->get_Title(&string);
+ break;
+ case QtMultimediaKit::ParentalRating:
+ m_content->get_Rating(&string);
+ break;
+ case QtMultimediaKit::Description:
+ m_content->get_Description(&string);
+ break;
+ case QtMultimediaKit::Copyright:
+ m_content->get_Copyright(&string);
+ break;
+ default:
+ break;
+ }
+
+ if (string) {
+ value = QString::fromUtf16(reinterpret_cast<ushort *>(string), ::SysStringLen(string));
+
+ ::SysFreeString(string);
+ }
+ }
+ return value;
+}
+
+QList<QtMultimediaKit::MetaData> DirectShowMetaDataControl::availableMetaData() const
+{
+ return QList<QtMultimediaKit::MetaData>();
+}
+
+QVariant DirectShowMetaDataControl::extendedMetaData(const QString &) const
+{
+ return QVariant();
+}
+
+QStringList DirectShowMetaDataControl::availableExtendedMetaData() const
+{
+ return QStringList();
+}
+
+void DirectShowMetaDataControl::updateGraph(IFilterGraph2 *graph, IBaseFilter *source)
+{
+ if (m_content)
+ m_content->Release();
+
+ if (!graph || graph->QueryInterface(
+ IID_IAMMediaContent, reinterpret_cast<void **>(&m_content)) != S_OK) {
+ m_content = 0;
+ }
+
+#ifdef QT_NO_WMSDK
+ Q_UNUSED(source);
+#else
+ if (m_headerInfo)
+ m_headerInfo->Release();
+
+ m_headerInfo = com_cast<IWMHeaderInfo>(source, IID_IWMHeaderInfo);
+#endif
+ // DirectShowMediaPlayerService holds a lock at this point so defer emitting signals to a later
+ // time.
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(MetaDataChanged)));
+}
+
+void DirectShowMetaDataControl::customEvent(QEvent *event)
+{
+ if (event->type() == QEvent::Type(MetaDataChanged)) {
+ event->accept();
+
+ emit metaDataChanged();
+#ifndef QT_NO_WMSDK
+ emit metaDataAvailableChanged(m_content || m_headerInfo);
+#else
+ emit metaDataAvailableChanged(m_content);
+#endif
+ } else {
+ QMetaDataReaderControl::customEvent(event);
+ }
+}
diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.h b/src/plugins/directshow/player/directshowmetadatacontrol.h
new file mode 100644
index 000000000..6826d783d
--- /dev/null
+++ b/src/plugins/directshow/player/directshowmetadatacontrol.h
@@ -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$
+** 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 DIRECTSHOWMETADATACONTROL_H
+#define DIRECTSHOWMETADATACONTROL_H
+
+#include <qmetadatareadercontrol.h>
+
+#include "directshowglobal.h"
+
+#include <qnetwork.h>
+
+#ifndef QT_NO_WMSDK
+#include <wmsdk.h>
+#endif
+
+#include <QtCore/qcoreevent.h>
+
+class DirectShowPlayerService;
+
+QT_USE_NAMESPACE
+
+class DirectShowMetaDataControl : public QMetaDataReaderControl
+{
+ Q_OBJECT
+public:
+ DirectShowMetaDataControl(QObject *parent = 0);
+ ~DirectShowMetaDataControl();
+
+ bool isMetaDataAvailable() const;
+
+ QVariant metaData(QtMultimediaKit::MetaData key) const;
+ QList<QtMultimediaKit::MetaData> availableMetaData() const;
+
+ QVariant extendedMetaData(const QString &key) const;
+ QStringList availableExtendedMetaData() const;
+
+ void updateGraph(IFilterGraph2 *graph, IBaseFilter *source);
+
+protected:
+ void customEvent(QEvent *event);
+
+private:
+ enum Event
+ {
+ MetaDataChanged = QEvent::User
+ };
+
+ IAMMediaContent *m_content;
+#ifndef QT_NO_WMSDK
+ IWMHeaderInfo *m_headerInfo;
+#endif
+};
+
+#endif
diff --git a/src/plugins/directshow/player/directshowpinenum.cpp b/src/plugins/directshow/player/directshowpinenum.cpp
new file mode 100644
index 000000000..28093eaee
--- /dev/null
+++ b/src/plugins/directshow/player/directshowpinenum.cpp
@@ -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$
+** 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 "directshowpinenum.h"
+
+
+DirectShowPinEnum::DirectShowPinEnum(const QList<IPin *> &pins)
+ : m_ref(1)
+ , m_pins(pins)
+ , m_index(0)
+{
+ foreach (IPin *pin, m_pins)
+ pin->AddRef();
+}
+
+DirectShowPinEnum::~DirectShowPinEnum()
+{
+ foreach (IPin *pin, m_pins)
+ pin->Release();
+}
+
+HRESULT DirectShowPinEnum::QueryInterface(REFIID riid, void **ppvObject)
+{
+ if (riid == IID_IUnknown
+ || riid == IID_IEnumPins) {
+ AddRef();
+
+ *ppvObject = static_cast<IEnumPins *>(this);
+
+ return S_OK;
+ } else {
+ *ppvObject = 0;
+
+ return E_NOINTERFACE;
+ }
+}
+
+ULONG DirectShowPinEnum::AddRef()
+{
+ return InterlockedIncrement(&m_ref);
+}
+
+ULONG DirectShowPinEnum::Release()
+{
+ ULONG ref = InterlockedDecrement(&m_ref);
+
+ if (ref == 0) {
+ delete this;
+ }
+
+ return ref;
+}
+
+HRESULT DirectShowPinEnum::Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched)
+{
+ if (ppPins && (pcFetched || cPins == 1)) {
+ ULONG count = qBound<ULONG>(0, cPins, m_pins.count() - m_index);
+
+ for (ULONG i = 0; i < count; ++i, ++m_index) {
+ ppPins[i] = m_pins.at(m_index);
+ ppPins[i]->AddRef();
+ }
+
+ if (pcFetched)
+ *pcFetched = count;
+
+ return count == cPins ? S_OK : S_FALSE;
+ } else {
+ return E_POINTER;
+ }
+}
+
+HRESULT DirectShowPinEnum::Skip(ULONG cPins)
+{
+ m_index = qMin(int(m_index + cPins), m_pins.count());
+
+ return m_index < m_pins.count() ? S_OK : S_FALSE;
+}
+
+HRESULT DirectShowPinEnum::Reset()
+{
+ m_index = 0;
+
+ return S_OK;
+}
+
+HRESULT DirectShowPinEnum::Clone(IEnumPins **ppEnum)
+{
+ if (ppEnum) {
+ *ppEnum = new DirectShowPinEnum(m_pins);
+
+ return S_OK;
+ } else {
+ return E_POINTER;
+ }
+}
diff --git a/src/plugins/directshow/player/directshowpinenum.h b/src/plugins/directshow/player/directshowpinenum.h
new file mode 100644
index 000000000..9fba3e84e
--- /dev/null
+++ b/src/plugins/directshow/player/directshowpinenum.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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$
+** 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 DIRECTSHOWPINENUM_H
+#define DIRECTSHOWPINENUM_H
+
+#include <QtCore/qlist.h>
+
+#include <dshow.h>
+
+class DirectShowPinEnum : public IEnumPins
+{
+public:
+ DirectShowPinEnum(const QList<IPin *> &pins);
+ ~DirectShowPinEnum();
+
+ // IUnknown
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ // IEnumPins
+ HRESULT STDMETHODCALLTYPE Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched);
+ HRESULT STDMETHODCALLTYPE Skip(ULONG cPins);
+ HRESULT STDMETHODCALLTYPE Reset();
+ HRESULT STDMETHODCALLTYPE Clone(IEnumPins **ppEnum);
+
+private:
+ LONG m_ref;
+ QList<IPin *> m_pins;
+ int m_index;
+};
+
+#endif
diff --git a/src/plugins/directshow/player/directshowplayercontrol.cpp b/src/plugins/directshow/player/directshowplayercontrol.cpp
new file mode 100644
index 000000000..9035a8b21
--- /dev/null
+++ b/src/plugins/directshow/player/directshowplayercontrol.cpp
@@ -0,0 +1,405 @@
+/****************************************************************************
+**
+** 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$
+** 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 "directshowplayercontrol.h"
+
+#include "directshowplayerservice.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qmath.h>
+
+static int volumeToDecibels(int volume)
+{
+ if (volume == 0) {
+ return -10000;
+ } else if (volume == 100) {
+ return 0;
+#ifdef QT_USE_MATH_H_FLOATS
+ } else if (sizeof(qreal) == sizeof(float)) {
+ return qRound(::log10f(float(volume) / 100) * 5000);
+#endif
+ } else {
+ return qRound(::log10(qreal(volume) / 100) * 5000);
+ }
+}
+
+static int decibelsToVolume(int dB)
+{
+ if (dB == -10000) {
+ return 0;
+ } else if (dB == 0) {
+ return 100;
+ } else {
+ return qRound(100 * qPow(10, qreal(dB) / 5000));
+ }
+}
+
+DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent)
+ : QMediaPlayerControl(parent)
+ , m_service(service)
+ , m_audio(0)
+ , m_updateProperties(0)
+ , m_state(QMediaPlayer::StoppedState)
+ , m_status(QMediaPlayer::NoMedia)
+ , m_error(QMediaPlayer::NoError)
+ , m_streamTypes(0)
+ , m_muteVolume(-1)
+ , m_position(0)
+ , m_duration(0)
+ , m_playbackRate(0)
+ , m_seekable(false)
+{
+}
+
+DirectShowPlayerControl::~DirectShowPlayerControl()
+{
+ if (m_audio)
+ m_audio->Release();
+}
+
+QMediaPlayer::State DirectShowPlayerControl::state() const
+{
+ return m_state;
+}
+
+QMediaPlayer::MediaStatus DirectShowPlayerControl::mediaStatus() const
+{
+ return m_status;
+}
+
+qint64 DirectShowPlayerControl::duration() const
+{
+ return m_duration;
+}
+
+qint64 DirectShowPlayerControl::position() const
+{
+ return const_cast<qint64 &>(m_position) = m_service->position();
+}
+
+void DirectShowPlayerControl::setPosition(qint64 position)
+{
+ m_service->seek(position);
+}
+
+int DirectShowPlayerControl::volume() const
+{
+ if (m_muteVolume >= 0) {
+ return m_muteVolume;
+ } else if (m_audio) {
+ long dB = 0;
+
+ m_audio->get_Volume(&dB);
+
+ return decibelsToVolume(dB);
+ } else {
+ return 0;
+ }
+}
+
+void DirectShowPlayerControl::setVolume(int volume)
+{
+ int boundedVolume = qBound(0, volume, 100);
+
+ if (m_muteVolume >= 0) {
+ m_muteVolume = boundedVolume;
+
+ emit volumeChanged(m_muteVolume);
+ } else if (m_audio) {
+ m_audio->put_Volume(volumeToDecibels(volume));
+
+ emit volumeChanged(boundedVolume);
+ }
+}
+
+bool DirectShowPlayerControl::isMuted() const
+{
+ return m_muteVolume >= 0;
+}
+
+void DirectShowPlayerControl::setMuted(bool muted)
+{
+ if (muted && m_muteVolume < 0) {
+ if (m_audio) {
+ long dB = 0;
+
+ m_audio->get_Volume(&dB);
+
+ m_muteVolume = decibelsToVolume(dB);
+
+ m_audio->put_Volume(-10000);
+ } else {
+ m_muteVolume = 0;
+ }
+
+ emit mutedChanged(muted);
+ } else if (!muted && m_muteVolume >= 0) {
+ if (m_audio) {
+ m_audio->put_Volume(volumeToDecibels(m_muteVolume));
+ }
+ m_muteVolume = -1;
+
+ emit mutedChanged(muted);
+ }
+}
+
+int DirectShowPlayerControl::bufferStatus() const
+{
+ return m_service->bufferStatus();
+}
+
+bool DirectShowPlayerControl::isAudioAvailable() const
+{
+ return m_streamTypes & DirectShowPlayerService::AudioStream;
+}
+
+bool DirectShowPlayerControl::isVideoAvailable() const
+{
+ return m_streamTypes & DirectShowPlayerService::VideoStream;
+}
+
+bool DirectShowPlayerControl::isSeekable() const
+{
+ return m_seekable;
+}
+
+QMediaTimeRange DirectShowPlayerControl::availablePlaybackRanges() const
+{
+ return m_service->availablePlaybackRanges();
+}
+
+qreal DirectShowPlayerControl::playbackRate() const
+{
+ return m_playbackRate;
+}
+
+void DirectShowPlayerControl::setPlaybackRate(qreal rate)
+{
+ if (m_playbackRate != rate) {
+ m_service->setRate(rate);
+
+ emit playbackRateChanged(m_playbackRate = rate);
+ }
+}
+
+QMediaContent DirectShowPlayerControl::media() const
+{
+ return m_media;
+}
+
+const QIODevice *DirectShowPlayerControl::mediaStream() const
+{
+ return m_stream;
+}
+
+void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream)
+{
+ m_media = media;
+ m_stream = stream;
+
+ m_updateProperties &= PlaybackRateProperty;
+
+ m_service->load(media, stream);
+
+ emit mediaChanged(m_media);
+ emitPropertyChanges();
+}
+
+void DirectShowPlayerControl::play()
+{
+ if (m_status == QMediaPlayer::NoMedia)
+ return;
+ if (m_status == QMediaPlayer::InvalidMedia) {
+ setMedia(m_media, m_stream);
+ if (m_error != QMediaPlayer::NoError)
+ return;
+ }
+ m_service->play();
+ emit stateChanged(m_state = QMediaPlayer::PlayingState);
+}
+
+void DirectShowPlayerControl::pause()
+{
+ if (m_status == QMediaPlayer::NoMedia)
+ return;
+ if (m_status == QMediaPlayer::InvalidMedia) {
+ setMedia(m_media, m_stream);
+ if (m_error != QMediaPlayer::NoError)
+ return;
+ }
+ m_service->pause();
+ emit stateChanged(m_state = QMediaPlayer::PausedState);
+}
+
+void DirectShowPlayerControl::stop()
+{
+ m_service->stop();
+ emit stateChanged(m_state = QMediaPlayer::StoppedState);
+}
+
+void DirectShowPlayerControl::customEvent(QEvent *event)
+{
+ if (event->type() == QEvent::Type(PropertiesChanged)) {
+ emitPropertyChanges();
+
+ event->accept();
+ } else {
+ QMediaPlayerControl::customEvent(event);
+ }
+}
+
+void DirectShowPlayerControl::emitPropertyChanges()
+{
+ int properties = m_updateProperties;
+ m_updateProperties = 0;
+
+ if ((properties & ErrorProperty) && m_error != QMediaPlayer::NoError)
+ emit error(m_error, m_errorString);
+
+ if (properties & PlaybackRateProperty)
+ emit playbackRateChanged(m_playbackRate);
+
+ if (properties & StreamTypesProperty) {
+ emit audioAvailableChanged(m_streamTypes & DirectShowPlayerService::AudioStream);
+ emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream);
+ }
+
+ if (properties & PositionProperty)
+ emit positionChanged(m_position);
+
+ if (properties & DurationProperty)
+ emit durationChanged(m_duration);
+
+ if (properties & SeekableProperty)
+ emit seekableChanged(m_seekable);
+
+ if (properties & StatusProperty)
+ emit mediaStatusChanged(m_status);
+
+ if (properties & StateProperty)
+ emit stateChanged(m_state);
+}
+
+void DirectShowPlayerControl::scheduleUpdate(int properties)
+{
+ if (m_updateProperties == 0)
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PropertiesChanged)));
+
+ m_updateProperties |= properties;
+}
+
+void DirectShowPlayerControl::updateState(QMediaPlayer::State state)
+{
+ if (m_state != state) {
+ m_state = state;
+
+ scheduleUpdate(StateProperty);
+ }
+}
+
+void DirectShowPlayerControl::updateStatus(QMediaPlayer::MediaStatus status)
+{
+ if (m_status != status) {
+ m_status = status;
+
+ scheduleUpdate(StatusProperty);
+ }
+}
+
+void DirectShowPlayerControl::updateMediaInfo(qint64 duration, int streamTypes, bool seekable)
+{
+ int properties = 0;
+
+ if (m_duration != duration) {
+ m_duration = duration;
+
+ properties |= DurationProperty;
+ }
+ if (m_streamTypes != streamTypes) {
+ m_streamTypes = streamTypes;
+
+ properties |= StreamTypesProperty;
+ }
+
+ if (m_seekable != seekable) {
+ m_seekable = seekable;
+
+ properties |= SeekableProperty;
+ }
+
+ if (properties != 0)
+ scheduleUpdate(properties);
+}
+
+void DirectShowPlayerControl::updatePlaybackRate(qreal rate)
+{
+ if (m_playbackRate != rate) {
+ m_playbackRate = rate;
+
+ scheduleUpdate(PlaybackRateProperty);
+ }
+}
+
+void DirectShowPlayerControl::updateAudioOutput(IBaseFilter *filter)
+{
+ if (m_audio)
+ m_audio->Release();
+
+ m_audio = com_cast<IBasicAudio>(filter, IID_IBasicAudio);
+}
+
+void DirectShowPlayerControl::updateError(QMediaPlayer::Error error, const QString &errorString)
+{
+ m_error = error;
+ m_errorString = errorString;
+
+ if (m_error != QMediaPlayer::NoError)
+ scheduleUpdate(ErrorProperty);
+}
+
+void DirectShowPlayerControl::updatePosition(qint64 position)
+{
+ if (m_position != position) {
+ m_position = position;
+
+ scheduleUpdate(PositionProperty);
+ }
+}
diff --git a/src/plugins/directshow/player/directshowplayercontrol.h b/src/plugins/directshow/player/directshowplayercontrol.h
new file mode 100644
index 000000000..2c1cd6ad7
--- /dev/null
+++ b/src/plugins/directshow/player/directshowplayercontrol.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** 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$
+** 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 DIRECTSHOWPLAYERCONTROL_H
+#define DIRECTSHOWPLAYERCONTROL_H
+
+#include "qmediacontent.h"
+#include "qmediaplayercontrol.h"
+
+#include <QtCore/qcoreevent.h>
+
+#include "directshowplayerservice.h"
+
+QT_USE_NAMESPACE
+
+class DirectShowPlayerControl : public QMediaPlayerControl
+{
+ Q_OBJECT
+public:
+ DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent = 0);
+ ~DirectShowPlayerControl();
+
+ QMediaPlayer::State state() const;
+
+ QMediaPlayer::MediaStatus mediaStatus() const;
+
+ qint64 duration() const;
+
+ qint64 position() const;
+ void setPosition(qint64 position);
+
+ int volume() const;
+ void setVolume(int volume);
+
+ bool isMuted() const;
+ void setMuted(bool muted);
+
+ int bufferStatus() const;
+
+ bool isAudioAvailable() const;
+ bool isVideoAvailable() const;
+
+ bool isSeekable() const;
+
+ QMediaTimeRange availablePlaybackRanges() const;
+
+ qreal playbackRate() const;
+ void setPlaybackRate(qreal rate);
+
+ QMediaContent media() const;
+ const QIODevice *mediaStream() const;
+ void setMedia(const QMediaContent &media, QIODevice *stream);
+
+ void play();
+ void pause();
+ void stop();
+
+ void updateState(QMediaPlayer::State state);
+ void updateStatus(QMediaPlayer::MediaStatus status);
+ void updateMediaInfo(qint64 duration, int streamTypes, bool seekable);
+ void updatePlaybackRate(qreal rate);
+ void updateAudioOutput(IBaseFilter *filter);
+ void updateError(QMediaPlayer::Error error, const QString &errorString);
+ void updatePosition(qint64 position);
+
+protected:
+ void customEvent(QEvent *event);
+
+private:
+ enum Properties
+ {
+ StateProperty = 0x01,
+ StatusProperty = 0x02,
+ StreamTypesProperty = 0x04,
+ DurationProperty = 0x08,
+ PlaybackRateProperty = 0x10,
+ SeekableProperty = 0x20,
+ ErrorProperty = 0x40,
+ PositionProperty = 0x80
+ };
+
+ enum Event
+ {
+ PropertiesChanged = QEvent::User
+ };
+
+ void scheduleUpdate(int properties);
+ void emitPropertyChanges();
+
+ DirectShowPlayerService *m_service;
+ IBasicAudio *m_audio;
+ QIODevice *m_stream;
+ int m_updateProperties;
+ QMediaPlayer::State m_state;
+ QMediaPlayer::MediaStatus m_status;
+ QMediaPlayer::Error m_error;
+ int m_streamTypes;
+ int m_muteVolume;
+ qint64 m_position;
+ qint64 m_duration;
+ qreal m_playbackRate;
+ bool m_seekable;
+ QMediaContent m_media;
+ QString m_errorString;
+
+};
+
+#endif
diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp
new file mode 100644
index 000000000..ac93f592c
--- /dev/null
+++ b/src/plugins/directshow/player/directshowplayerservice.cpp
@@ -0,0 +1,1408 @@
+/****************************************************************************
+**
+** 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$
+** 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 "directshowplayerservice.h"
+
+#include "directshowaudioendpointcontrol.h"
+#include "directshowiosource.h"
+#include "directshowmetadatacontrol.h"
+#include "directshowplayercontrol.h"
+#include "directshowvideorenderercontrol.h"
+#ifndef Q_WS_SIMULATOR
+#include "vmr9videowindowcontrol.h"
+#endif
+
+#include "qmediacontent.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qvarlengtharray.h>
+
+Q_GLOBAL_STATIC(DirectShowEventLoop, qt_directShowEventLoop)
+
+
+// QMediaPlayer uses millisecond time units, direct show uses 100 nanosecond units.
+static const int qt_directShowTimeScale = 10000;
+
+class DirectShowPlayerServiceThread : public QThread
+{
+public:
+ DirectShowPlayerServiceThread(DirectShowPlayerService *service)
+ : m_service(service)
+ {
+ }
+
+protected:
+ void run() { m_service->run(); }
+
+private:
+ DirectShowPlayerService *m_service;
+};
+
+DirectShowPlayerService::DirectShowPlayerService(QObject *parent)
+ : QMediaService(parent)
+ , m_playerControl(0)
+ , m_metaDataControl(0)
+ , m_videoRendererControl(0)
+#ifndef Q_WS_SIMULATOR
+ , m_videoWindowControl(0)
+#endif
+ , m_audioEndpointControl(0)
+ , m_taskThread(0)
+ , m_loop(qt_directShowEventLoop())
+ , m_pendingTasks(0)
+ , m_executingTask(0)
+ , m_executedTasks(0)
+ , m_taskHandle(::CreateEvent(0, 0, 0, 0))
+ , m_eventHandle(0)
+ , m_graphStatus(NoMedia)
+ , m_stream(0)
+ , m_graph(0)
+ , m_source(0)
+ , m_audioOutput(0)
+ , m_videoOutput(0)
+ , m_rate(1.0)
+ , m_position(0)
+ , m_duration(0)
+ , m_buffering(false)
+ , m_seekable(false)
+ , m_atEnd(false)
+{
+ CoInitialize(NULL);
+ m_playerControl = new DirectShowPlayerControl(this);
+ m_metaDataControl = new DirectShowMetaDataControl(this);
+ m_audioEndpointControl = new DirectShowAudioEndpointControl(this);
+
+ m_taskThread = new DirectShowPlayerServiceThread(this);
+ m_taskThread->start();
+}
+
+DirectShowPlayerService::~DirectShowPlayerService()
+{
+ {
+ QMutexLocker locker(&m_mutex);
+
+ releaseGraph();
+
+ m_pendingTasks = Shutdown;
+ ::SetEvent(m_taskHandle);
+ }
+
+ m_taskThread->wait();
+ delete m_taskThread;
+
+ if (m_audioOutput) {
+ m_audioOutput->Release();
+ m_audioOutput = 0;
+ }
+
+ if (m_videoOutput) {
+ m_videoOutput->Release();
+ m_videoOutput = 0;
+ }
+
+ delete m_playerControl;
+ delete m_audioEndpointControl;
+ delete m_metaDataControl;
+ delete m_videoRendererControl;
+#ifndef Q_WS_SIMULATOR
+ delete m_videoWindowControl;
+#endif
+
+ ::CloseHandle(m_taskHandle);
+ CoUninitialize();
+}
+
+QMediaControl *DirectShowPlayerService::requestControl(const char *name)
+{
+ if (qstrcmp(name, QMediaPlayerControl_iid) == 0) {
+ return m_playerControl;
+ } else if (qstrcmp(name, QAudioEndpointSelector_iid) == 0) {
+ return m_audioEndpointControl;
+ } else if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) {
+ return m_metaDataControl;
+ } else if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+#ifndef Q_WS_SIMULATOR
+ if (!m_videoRendererControl && !m_videoWindowControl) {
+#else
+ if (!m_videoRendererControl) {
+#endif
+ m_videoRendererControl = new DirectShowVideoRendererControl(m_loop);
+
+ connect(m_videoRendererControl, SIGNAL(filterChanged()),
+ this, SLOT(videoOutputChanged()));
+
+ return m_videoRendererControl;
+ }
+#ifndef Q_WS_SIMULATOR
+ } else if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
+ if (!m_videoRendererControl && !m_videoWindowControl) {
+ m_videoWindowControl = new Vmr9VideoWindowControl;
+
+ setVideoOutput(m_videoWindowControl->filter());
+
+ return m_videoWindowControl;
+ }
+#endif
+ }
+ return 0;
+}
+
+void DirectShowPlayerService::releaseControl(QMediaControl *control)
+{
+ if (!control) {
+ qWarning("QMediaService::releaseControl():"
+ " Attempted release of null control");
+ } else if (control == m_videoRendererControl) {
+ setVideoOutput(0);
+
+ delete m_videoRendererControl;
+
+ m_videoRendererControl = 0;
+#ifndef Q_WS_SIMULATOR
+ } else if (control == m_videoWindowControl) {
+ setVideoOutput(0);
+
+ delete m_videoWindowControl;
+
+ m_videoWindowControl = 0;
+#endif
+ }
+}
+
+void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream)
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_pendingTasks = 0;
+
+ if (m_graph)
+ releaseGraph();
+
+ m_resources = media.resources();
+ m_stream = stream;
+ m_error = QMediaPlayer::NoError;
+ m_errorString = QString();
+ m_position = 0;
+ m_duration = 0;
+ m_streamTypes = 0;
+ m_executedTasks = 0;
+ m_buffering = false;
+ m_seekable = false;
+ m_atEnd = false;
+ m_metaDataControl->updateGraph(0, 0);
+
+ if (m_resources.isEmpty() && !stream) {
+ m_pendingTasks = 0;
+ m_graphStatus = NoMedia;
+
+ m_url.clear();
+ } else if (stream && (!stream->isReadable() || stream->isSequential())) {
+ m_pendingTasks = 0;
+ m_graphStatus = InvalidMedia;
+ m_error = QMediaPlayer::ResourceError;
+ } else {
+ // {36b73882-c2c8-11cf-8b46-00805f6cef60}
+ static const GUID iid_IFilterGraph2 = {
+ 0x36b73882, 0xc2c8, 0x11cf, {0x8b, 0x46, 0x00, 0x80, 0x5f, 0x6c, 0xef, 0x60} };
+ m_graphStatus = Loading;
+
+ m_graph = com_new<IFilterGraph2>(CLSID_FilterGraph, iid_IFilterGraph2);
+
+ if (stream)
+ m_pendingTasks = SetStreamSource;
+ else
+ m_pendingTasks = SetUrlSource;
+
+ ::SetEvent(m_taskHandle);
+ }
+
+ m_playerControl->updateError(m_error, m_errorString);
+ m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable);
+ m_playerControl->updateState(QMediaPlayer::StoppedState);
+ m_playerControl->updatePosition(m_position);
+ updateStatus();
+}
+
+void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker)
+{
+ IBaseFilter *source = 0;
+
+ QMediaResource resource = m_resources.takeFirst();
+ QUrl url = resource.url();
+
+ HRESULT hr = E_FAIL;
+
+ if (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https")) {
+ static const GUID clsid_WMAsfReader = {
+ 0x187463a0, 0x5bb7, 0x11d3, {0xac, 0xbe, 0x00, 0x80, 0xc7, 0x5e, 0x24, 0x6e} };
+
+ // {56a868a6-0ad4-11ce-b03a-0020af0ba770}
+ static const GUID iid_IFileSourceFilter = {
+ 0x56a868a6, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} };
+
+ if (IFileSourceFilter *fileSource = com_new<IFileSourceFilter>(
+ clsid_WMAsfReader, iid_IFileSourceFilter)) {
+ locker->unlock();
+ hr = fileSource->Load(reinterpret_cast<const OLECHAR *>(url.toString().utf16()), 0);
+
+ if (SUCCEEDED(hr)) {
+ source = com_cast<IBaseFilter>(fileSource, IID_IBaseFilter);
+
+ if (!SUCCEEDED(hr = m_graph->AddFilter(source, L"Source")) && source) {
+ source->Release();
+ source = 0;
+ }
+ }
+ fileSource->Release();
+ locker->relock();
+ }
+ } else if (url.scheme() == QLatin1String("qrc")) {
+ DirectShowRcSource *rcSource = new DirectShowRcSource(m_loop);
+
+ locker->unlock();
+ if (rcSource->open(url) && SUCCEEDED(hr = m_graph->AddFilter(rcSource, L"Source")))
+ source = rcSource;
+ else
+ rcSource->Release();
+ locker->relock();
+ }
+
+ if (!SUCCEEDED(hr)) {
+ locker->unlock();
+ hr = m_graph->AddSourceFilter(
+ reinterpret_cast<const OLECHAR *>(url.toString().utf16()), L"Source", &source);
+ locker->relock();
+ }
+
+ if (SUCCEEDED(hr)) {
+ m_executedTasks = SetSource;
+ m_pendingTasks |= Render;
+
+ if (m_audioOutput)
+ m_pendingTasks |= SetAudioOutput;
+ if (m_videoOutput)
+ m_pendingTasks |= SetVideoOutput;
+
+ if (m_rate != 1.0)
+ m_pendingTasks |= SetRate;
+
+ m_source = source;
+ } else if (!m_resources.isEmpty()) {
+ m_pendingTasks |= SetUrlSource;
+ } else {
+ m_pendingTasks = 0;
+ m_graphStatus = InvalidMedia;
+
+ switch (hr) {
+ case VFW_E_UNKNOWN_FILE_TYPE:
+ m_error = QMediaPlayer::FormatError;
+ m_errorString = QString();
+ break;
+ case E_OUTOFMEMORY:
+ case VFW_E_CANNOT_LOAD_SOURCE_FILTER:
+ case VFW_E_NOT_FOUND:
+ m_error = QMediaPlayer::ResourceError;
+ m_errorString = QString();
+ break;
+ default:
+ m_error = QMediaPlayer::ResourceError;
+ m_errorString = QString();
+ qWarning("DirectShowPlayerService::doSetUrlSource: Unresolved error code %x", uint(hr));
+ break;
+ }
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error)));
+ }
+}
+
+void DirectShowPlayerService::doSetStreamSource(QMutexLocker *locker)
+{
+ DirectShowIOSource *source = new DirectShowIOSource(m_loop);
+ source->setDevice(m_stream);
+
+ if (SUCCEEDED(m_graph->AddFilter(source, L"Source"))) {
+ m_executedTasks = SetSource;
+ m_pendingTasks |= Render;
+
+ if (m_audioOutput)
+ m_pendingTasks |= SetAudioOutput;
+ if (m_videoOutput)
+ m_pendingTasks |= SetVideoOutput;
+
+ if (m_rate != 1.0)
+ m_pendingTasks |= SetRate;
+
+ m_source = source;
+ } else {
+ source->Release();
+
+ m_pendingTasks = 0;
+ m_graphStatus = InvalidMedia;
+
+ m_error = QMediaPlayer::ResourceError;
+ m_errorString = QString();
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error)));
+ }
+}
+
+void DirectShowPlayerService::doRender(QMutexLocker *locker)
+{
+ m_pendingTasks |= m_executedTasks & (Play | Pause);
+
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
+ control->Stop();
+ control->Release();
+ }
+
+ if (m_pendingTasks & SetAudioOutput) {
+ m_graph->AddFilter(m_audioOutput, L"AudioOutput");
+
+ m_pendingTasks ^= SetAudioOutput;
+ m_executedTasks |= SetAudioOutput;
+ }
+ if (m_pendingTasks & SetVideoOutput) {
+ m_graph->AddFilter(m_videoOutput, L"VideoOutput");
+
+ m_pendingTasks ^= SetVideoOutput;
+ m_executedTasks |= SetVideoOutput;
+ }
+
+ IFilterGraph2 *graph = m_graph;
+ graph->AddRef();
+
+ QVarLengthArray<IBaseFilter *, 16> filters;
+ m_source->AddRef();
+ filters.append(m_source);
+
+ bool rendered = false;
+
+ HRESULT renderHr = S_OK;
+
+ while (!filters.isEmpty()) {
+ IEnumPins *pins = 0;
+ IBaseFilter *filter = filters[filters.size() - 1];
+ filters.removeLast();
+
+ if (!(m_pendingTasks & ReleaseFilters) && SUCCEEDED(filter->EnumPins(&pins))) {
+ int outputs = 0;
+ for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) {
+ PIN_DIRECTION direction;
+ if (pin->QueryDirection(&direction) == S_OK && direction == PINDIR_OUTPUT) {
+ ++outputs;
+
+ IPin *peer = 0;
+ if (pin->ConnectedTo(&peer) == S_OK) {
+ PIN_INFO peerInfo;
+ if (SUCCEEDED(peer->QueryPinInfo(&peerInfo)))
+ filters.append(peerInfo.pFilter);
+ peer->Release();
+ } else {
+ locker->unlock();
+ HRESULT hr;
+ if (SUCCEEDED(hr = graph->RenderEx(
+ pin, /*AM_RENDEREX_RENDERTOEXISTINGRENDERERS*/ 1, 0))) {
+ rendered = true;
+ } else if (renderHr == S_OK || renderHr == VFW_E_NO_DECOMPRESSOR){
+ renderHr = hr;
+ }
+ locker->relock();
+ }
+ }
+ }
+
+ pins->Release();
+
+ if (outputs == 0)
+ rendered = true;
+ }
+ filter->Release();
+ }
+
+ if (m_audioOutput && !isConnected(m_audioOutput, PINDIR_INPUT)) {
+ graph->RemoveFilter(m_audioOutput);
+
+ m_executedTasks &= ~SetAudioOutput;
+ }
+
+ if (m_videoOutput && !isConnected(m_videoOutput, PINDIR_INPUT)) {
+ graph->RemoveFilter(m_videoOutput);
+
+ m_executedTasks &= ~SetVideoOutput;
+ }
+
+ graph->Release();
+
+ if (!(m_pendingTasks & ReleaseFilters)) {
+ if (rendered) {
+ if (!(m_executedTasks & FinalizeLoad))
+ m_pendingTasks |= FinalizeLoad;
+ } else {
+ m_pendingTasks = 0;
+
+ m_graphStatus = InvalidMedia;
+
+ if (!m_audioOutput && !m_videoOutput) {
+ m_error = QMediaPlayer::ResourceError;
+ m_errorString = QString();
+ } else {
+ switch (renderHr) {
+ case VFW_E_UNSUPPORTED_AUDIO:
+ case VFW_E_UNSUPPORTED_VIDEO:
+ case VFW_E_UNSUPPORTED_STREAM:
+ m_error = QMediaPlayer::FormatError;
+ m_errorString = QString();
+ break;
+ default:
+ m_error = QMediaPlayer::ResourceError;
+ m_errorString = QString();
+ qWarning("DirectShowPlayerService::doRender: Unresolved error code %x",
+ uint(renderHr));
+ }
+ }
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error)));
+ }
+
+ m_executedTasks |= Render;
+ }
+
+ m_loop->wake();
+}
+
+void DirectShowPlayerService::doFinalizeLoad(QMutexLocker *locker)
+{
+ if (m_graphStatus != Loaded) {
+ if (IMediaEvent *event = com_cast<IMediaEvent>(m_graph, IID_IMediaEvent)) {
+ event->GetEventHandle(reinterpret_cast<OAEVENT *>(&m_eventHandle));
+ event->Release();
+ }
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ LONGLONG duration = 0;
+ seeking->GetDuration(&duration);
+ m_duration = duration / qt_directShowTimeScale;
+
+ DWORD capabilities = 0;
+ seeking->GetCapabilities(&capabilities);
+ m_seekable = capabilities & AM_SEEKING_CanSeekAbsolute;
+
+ seeking->Release();
+ }
+ }
+
+ if ((m_executedTasks & SetOutputs) == SetOutputs) {
+ m_streamTypes = AudioStream | VideoStream;
+ } else {
+ m_streamTypes = findStreamTypes(m_source);
+ }
+
+ m_executedTasks |= FinalizeLoad;
+
+ m_graphStatus = Loaded;
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(FinalizedLoad)));
+}
+
+void DirectShowPlayerService::releaseGraph()
+{
+ if (m_graph) {
+ if (m_executingTask != 0) {
+ // {8E1C39A1-DE53-11cf-AA63-0080C744528D}
+ static const GUID iid_IAMOpenProgress = {
+ 0x8E1C39A1, 0xDE53, 0x11cf, {0xAA, 0x63, 0x00, 0x80, 0xC7, 0x44, 0x52, 0x8D} };
+
+ if (IAMOpenProgress *progress = com_cast<IAMOpenProgress>(
+ m_graph, iid_IAMOpenProgress)) {
+ progress->AbortOperation();
+ progress->Release();
+ }
+ m_graph->Abort();
+ }
+
+ m_pendingTasks = ReleaseGraph;
+
+ ::SetEvent(m_taskHandle);
+
+ m_loop->wait(&m_mutex);
+ }
+}
+
+void DirectShowPlayerService::doReleaseGraph(QMutexLocker *locker)
+{
+ Q_UNUSED(locker);
+
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
+ control->Stop();
+ control->Release();
+ }
+
+ if (m_source) {
+ m_source->Release();
+ m_source = 0;
+ }
+
+ m_eventHandle = 0;
+
+ m_graph->Release();
+ m_graph = 0;
+
+ m_loop->wake();
+}
+
+int DirectShowPlayerService::findStreamTypes(IBaseFilter *source) const
+{
+ QVarLengthArray<IBaseFilter *, 16> filters;
+ source->AddRef();
+ filters.append(source);
+
+ int streamTypes = 0;
+
+ while (!filters.isEmpty()) {
+ IEnumPins *pins = 0;
+ IBaseFilter *filter = filters[filters.size() - 1];
+ filters.removeLast();
+
+ if (SUCCEEDED(filter->EnumPins(&pins))) {
+ for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) {
+ PIN_DIRECTION direction;
+ if (pin->QueryDirection(&direction) == S_OK && direction == PINDIR_OUTPUT) {
+ AM_MEDIA_TYPE connectionType;
+ if (SUCCEEDED(pin->ConnectionMediaType(&connectionType))) {
+ IPin *peer = 0;
+
+ if (connectionType.majortype == MEDIATYPE_Audio) {
+ streamTypes |= AudioStream;
+ } else if (connectionType.majortype == MEDIATYPE_Video) {
+ streamTypes |= VideoStream;
+ } else if (SUCCEEDED(pin->ConnectedTo(&peer))) {
+ PIN_INFO peerInfo;
+ if (SUCCEEDED(peer->QueryPinInfo(&peerInfo)))
+ filters.append(peerInfo.pFilter);
+ peer->Release();
+ }
+ } else {
+ streamTypes |= findStreamType(pin);
+ }
+ }
+ }
+ }
+ filter->Release();
+ }
+ return streamTypes;
+}
+
+int DirectShowPlayerService::findStreamType(IPin *pin) const
+{
+ IEnumMediaTypes *types;
+
+ if (SUCCEEDED(pin->EnumMediaTypes(&types))) {
+ bool video = false;
+ bool audio = false;
+ bool other = false;
+
+ for (AM_MEDIA_TYPE *type = 0;
+ types->Next(1, &type, 0) == S_OK;
+ DirectShowMediaType::deleteType(type)) {
+ if (type->majortype == MEDIATYPE_Audio)
+ audio = true;
+ else if (type->majortype == MEDIATYPE_Video)
+ video = true;
+ else
+ other = true;
+ }
+ types->Release();
+
+ if (other)
+ return 0;
+ else if (audio && !video)
+ return AudioStream;
+ else if (!audio && video)
+ return VideoStream;
+ else
+ return 0;
+ } else {
+ return 0;
+ }
+}
+
+void DirectShowPlayerService::play()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_pendingTasks &= ~Pause;
+ m_pendingTasks |= Play;
+
+ if (m_executedTasks & Render) {
+ if (m_executedTasks & Stop) {
+ m_atEnd = false;
+ m_position = 0;
+ m_pendingTasks |= Seek;
+ m_executedTasks ^= Stop;
+ }
+
+ ::SetEvent(m_taskHandle);
+ }
+
+ updateStatus();
+}
+
+void DirectShowPlayerService::doPlay(QMutexLocker *locker)
+{
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
+ locker->unlock();
+ HRESULT hr = control->Run();
+ locker->relock();
+
+ control->Release();
+
+ if (SUCCEEDED(hr)) {
+ m_executedTasks |= Play;
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange)));
+ } else {
+ m_error = QMediaPlayer::ResourceError;
+ m_errorString = QString();
+ qWarning("DirectShowPlayerService::doPlay: Unresolved error code %x", uint(hr));
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error)));
+ }
+ }
+}
+
+void DirectShowPlayerService::pause()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_pendingTasks &= ~Play;
+ m_pendingTasks |= Pause;
+
+ if (m_executedTasks & Render) {
+ if (m_executedTasks & Stop) {
+ m_atEnd = false;
+ m_position = 0;
+ m_pendingTasks |= Seek;
+ m_executedTasks ^= Stop;
+ }
+
+ ::SetEvent(m_taskHandle);
+ }
+
+ updateStatus();
+}
+
+void DirectShowPlayerService::doPause(QMutexLocker *locker)
+{
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
+ locker->unlock();
+ HRESULT hr = control->Pause();
+ locker->relock();
+
+ control->Release();
+
+ if (SUCCEEDED(hr)) {
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ LONGLONG position = 0;
+
+ seeking->GetCurrentPosition(&position);
+ seeking->Release();
+
+ m_position = position / qt_directShowTimeScale;
+ } else {
+ m_position = 0;
+ }
+
+ m_executedTasks |= Pause;
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange)));
+ } else {
+ m_error = QMediaPlayer::ResourceError;
+ m_errorString = QString();
+ qWarning("DirectShowPlayerService::doPause: Unresolved error code %x", uint(hr));
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error)));
+ }
+ }
+}
+
+void DirectShowPlayerService::stop()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_pendingTasks &= ~(Play | Pause | Seek);
+
+ if ((m_executingTask | m_executedTasks) & (Play | Pause | Seek)) {
+ m_pendingTasks |= Stop;
+
+ ::SetEvent(m_taskHandle);
+
+ m_loop->wait(&m_mutex);
+ }
+
+ updateStatus();
+}
+
+void DirectShowPlayerService::doStop(QMutexLocker *locker)
+{
+ if (m_executedTasks & (Play | Pause)) {
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
+ control->Stop();
+ control->Release();
+ }
+
+ m_position = 0;
+ m_pendingTasks |= Seek;
+
+ m_executedTasks &= ~(Play | Pause);
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange)));
+ }
+
+ m_executedTasks |= Stop;
+
+ m_loop->wake();
+}
+
+void DirectShowPlayerService::setRate(qreal rate)
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_rate = rate;
+
+ m_pendingTasks |= SetRate;
+
+ if (m_executedTasks & FinalizeLoad)
+ ::SetEvent(m_taskHandle);
+}
+
+void DirectShowPlayerService::doSetRate(QMutexLocker *locker)
+{
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ // Cache current values as we can't query IMediaSeeking during a seek due to the
+ // possibility of a deadlock when flushing the VideoSurfaceFilter.
+ LONGLONG currentPosition = 0;
+ seeking->GetCurrentPosition(&currentPosition);
+ m_position = currentPosition / qt_directShowTimeScale;
+
+ LONGLONG minimum = 0;
+ LONGLONG maximum = 0;
+ m_playbackRange = SUCCEEDED(seeking->GetAvailable(&minimum, &maximum))
+ ? QMediaTimeRange(minimum / qt_directShowTimeScale, maximum / qt_directShowTimeScale)
+ : QMediaTimeRange();
+
+ locker->unlock();
+ HRESULT hr = seeking->SetRate(m_rate);
+ locker->relock();
+
+ if (!SUCCEEDED(hr)) {
+ double rate = 0.0;
+ m_rate = seeking->GetRate(&rate)
+ ? rate
+ : 1.0;
+ }
+
+ seeking->Release();
+ } else if (m_rate != 1.0) {
+ m_rate = 1.0;
+ }
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(RateChange)));
+}
+
+qint64 DirectShowPlayerService::position() const
+{
+ QMutexLocker locker(const_cast<QMutex *>(&m_mutex));
+
+ if (m_graphStatus == Loaded) {
+ if (m_executingTask == Seek || m_executingTask == SetRate || (m_pendingTasks & Seek)) {
+ return m_position;
+ } else if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ LONGLONG position = 0;
+
+ seeking->GetCurrentPosition(&position);
+ seeking->Release();
+
+ const_cast<qint64 &>(m_position) = position / qt_directShowTimeScale;
+
+ return m_position;
+ }
+ }
+ return 0;
+}
+
+QMediaTimeRange DirectShowPlayerService::availablePlaybackRanges() const
+{
+ QMutexLocker locker(const_cast<QMutex *>(&m_mutex));
+
+ if (m_graphStatus == Loaded) {
+ if (m_executingTask == Seek || m_executingTask == SetRate || (m_pendingTasks & Seek)) {
+ return m_playbackRange;
+ } else if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ LONGLONG minimum = 0;
+ LONGLONG maximum = 0;
+
+ HRESULT hr = seeking->GetAvailable(&minimum, &maximum);
+ seeking->Release();
+
+ if (SUCCEEDED(hr))
+ return QMediaTimeRange(minimum, maximum);
+ }
+ }
+ return QMediaTimeRange();
+}
+
+void DirectShowPlayerService::seek(qint64 position)
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_position = position;
+
+ m_pendingTasks |= Seek;
+
+ if (m_executedTasks & FinalizeLoad)
+ ::SetEvent(m_taskHandle);
+}
+
+void DirectShowPlayerService::doSeek(QMutexLocker *locker)
+{
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ LONGLONG seekPosition = LONGLONG(m_position) * qt_directShowTimeScale;
+
+ // Cache current values as we can't query IMediaSeeking during a seek due to the
+ // possibility of a deadlock when flushing the VideoSurfaceFilter.
+ LONGLONG currentPosition = 0;
+ seeking->GetCurrentPosition(&currentPosition);
+ m_position = currentPosition / qt_directShowTimeScale;
+
+ LONGLONG minimum = 0;
+ LONGLONG maximum = 0;
+ m_playbackRange = SUCCEEDED(seeking->GetAvailable(&minimum, &maximum))
+ ? QMediaTimeRange(
+ minimum / qt_directShowTimeScale, maximum / qt_directShowTimeScale)
+ : QMediaTimeRange();
+
+ locker->unlock();
+ seeking->SetPositions(
+ &seekPosition, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning);
+ locker->relock();
+
+ seeking->GetCurrentPosition(&currentPosition);
+ m_position = currentPosition / qt_directShowTimeScale;
+
+ seeking->Release();
+ } else {
+ m_position = 0;
+ }
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PositionChange)));
+}
+
+int DirectShowPlayerService::bufferStatus() const
+{
+#ifndef QT_NO_WMSDK
+ QMutexLocker locker(const_cast<QMutex *>(&m_mutex));
+
+ if (IWMReaderAdvanced2 *reader = com_cast<IWMReaderAdvanced2>(
+ m_source, IID_IWMReaderAdvanced2)) {
+ DWORD percentage = 0;
+
+ reader->GetBufferProgress(&percentage, 0);
+ reader->Release();
+
+ return percentage;
+ } else {
+ return 0;
+ }
+#else
+ return 0;
+#endif
+}
+
+void DirectShowPlayerService::setAudioOutput(IBaseFilter *filter)
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (m_graph) {
+ if (m_audioOutput) {
+ if (m_executedTasks & SetAudioOutput) {
+ m_pendingTasks |= ReleaseAudioOutput;
+
+ ::SetEvent(m_taskHandle);
+
+ m_loop->wait(&m_mutex);
+ }
+ m_audioOutput->Release();
+ }
+
+ m_audioOutput = filter;
+
+ if (m_audioOutput) {
+ m_audioOutput->AddRef();
+
+ m_pendingTasks |= SetAudioOutput;
+
+ if (m_executedTasks & SetSource) {
+ m_pendingTasks |= Render;
+
+ ::SetEvent(m_taskHandle);
+ }
+ } else {
+ m_pendingTasks &= ~ SetAudioOutput;
+ }
+ } else {
+ if (m_audioOutput)
+ m_audioOutput->Release();
+
+ m_audioOutput = filter;
+
+ if (m_audioOutput)
+ m_audioOutput->AddRef();
+ }
+
+ m_playerControl->updateAudioOutput(m_audioOutput);
+}
+
+void DirectShowPlayerService::doReleaseAudioOutput(QMutexLocker *locker)
+{
+ m_pendingTasks |= m_executedTasks & (Play | Pause);
+
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
+ control->Stop();
+ control->Release();
+ }
+
+ IBaseFilter *decoder = getConnected(m_audioOutput, PINDIR_INPUT);
+ if (!decoder) {
+ decoder = m_audioOutput;
+ decoder->AddRef();
+ }
+
+ // {DCFBDCF6-0DC2-45f5-9AB2-7C330EA09C29}
+ static const GUID iid_IFilterChain = {
+ 0xDCFBDCF6, 0x0DC2, 0x45f5, {0x9A, 0xB2, 0x7C, 0x33, 0x0E, 0xA0, 0x9C, 0x29} };
+
+ if (IFilterChain *chain = com_cast<IFilterChain>(m_graph, iid_IFilterChain)) {
+ chain->RemoveChain(decoder, m_audioOutput);
+ chain->Release();
+ } else {
+ m_graph->RemoveFilter(m_audioOutput);
+ }
+
+ decoder->Release();
+
+ m_executedTasks &= ~SetAudioOutput;
+
+ m_loop->wake();
+}
+
+void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter)
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (m_graph) {
+ if (m_videoOutput) {
+ if (m_executedTasks & SetVideoOutput) {
+ m_pendingTasks |= ReleaseVideoOutput;
+
+ ::SetEvent(m_taskHandle);
+
+ m_loop->wait(&m_mutex);
+ }
+ m_videoOutput->Release();
+ }
+
+ m_videoOutput = filter;
+
+ if (m_videoOutput) {
+ m_videoOutput->AddRef();
+
+ m_pendingTasks |= SetVideoOutput;
+
+ if (m_executedTasks & SetSource) {
+ m_pendingTasks |= Render;
+
+ ::SetEvent(m_taskHandle);
+ }
+ }
+ } else {
+ if (m_videoOutput)
+ m_videoOutput->Release();
+
+ m_videoOutput = filter;
+
+ if (m_videoOutput)
+ m_videoOutput->AddRef();
+ }
+}
+
+void DirectShowPlayerService::doReleaseVideoOutput(QMutexLocker *locker)
+{
+ m_pendingTasks |= m_executedTasks & (Play | Pause);
+
+ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) {
+ control->Stop();
+ control->Release();
+ }
+
+ IBaseFilter *intermediate = 0;
+ if (!SUCCEEDED(m_graph->FindFilterByName(L"Color Space Converter", &intermediate))) {
+ intermediate = m_videoOutput;
+ intermediate->AddRef();
+ }
+
+ IBaseFilter *decoder = getConnected(intermediate, PINDIR_INPUT);
+ if (!decoder) {
+ decoder = intermediate;
+ decoder->AddRef();
+ }
+
+ // {DCFBDCF6-0DC2-45f5-9AB2-7C330EA09C29}
+ static const GUID iid_IFilterChain = {
+ 0xDCFBDCF6, 0x0DC2, 0x45f5, {0x9A, 0xB2, 0x7C, 0x33, 0x0E, 0xA0, 0x9C, 0x29} };
+
+ if (IFilterChain *chain = com_cast<IFilterChain>(m_graph, iid_IFilterChain)) {
+ chain->RemoveChain(decoder, m_videoOutput);
+ chain->Release();
+ } else {
+ m_graph->RemoveFilter(m_videoOutput);
+ }
+
+ intermediate->Release();
+ decoder->Release();
+
+ m_executedTasks &= ~SetVideoOutput;
+
+ m_loop->wake();
+}
+
+void DirectShowPlayerService::customEvent(QEvent *event)
+{
+ if (event->type() == QEvent::Type(FinalizedLoad)) {
+ QMutexLocker locker(&m_mutex);
+
+ m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable);
+ m_metaDataControl->updateGraph(m_graph, m_source);
+
+ updateStatus();
+ } else if (event->type() == QEvent::Type(Error)) {
+ QMutexLocker locker(&m_mutex);
+
+ if (m_error != QMediaPlayer::NoError) {
+ m_playerControl->updateError(m_error, m_errorString);
+ m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable);
+ m_playerControl->updateState(QMediaPlayer::StoppedState);
+ updateStatus();
+ }
+ } else if (event->type() == QEvent::Type(RateChange)) {
+ QMutexLocker locker(&m_mutex);
+
+ m_playerControl->updatePlaybackRate(m_rate);
+ } else if (event->type() == QEvent::Type(StatusChange)) {
+ QMutexLocker locker(&m_mutex);
+
+ updateStatus();
+ m_playerControl->updatePosition(m_position);
+ } else if (event->type() == QEvent::Type(DurationChange)) {
+ QMutexLocker locker(&m_mutex);
+
+ m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable);
+ } else if (event->type() == QEvent::Type(EndOfMedia)) {
+ QMutexLocker locker(&m_mutex);
+
+ if (m_atEnd) {
+ m_playerControl->updateState(QMediaPlayer::StoppedState);
+ m_playerControl->updateStatus(QMediaPlayer::EndOfMedia);
+ m_playerControl->updatePosition(m_position);
+ }
+ } else if (event->type() == QEvent::Type(PositionChange)) {
+ QMutexLocker locker(&m_mutex);
+
+ if (m_playerControl->mediaStatus() == QMediaPlayer::EndOfMedia)
+ m_playerControl->updateStatus(QMediaPlayer::LoadedMedia);
+ m_playerControl->updatePosition(m_position);
+ } else {
+ QMediaService::customEvent(event);
+ }
+}
+
+void DirectShowPlayerService::videoOutputChanged()
+{
+ setVideoOutput(m_videoRendererControl->filter());
+}
+
+void DirectShowPlayerService::graphEvent(QMutexLocker *locker)
+{
+ if (IMediaEvent *event = com_cast<IMediaEvent>(m_graph, IID_IMediaEvent)) {
+ long eventCode;
+ LONG_PTR param1;
+ LONG_PTR param2;
+
+ while (event->GetEvent(&eventCode, &param1, &param2, 0) == S_OK) {
+ switch (eventCode) {
+ case EC_BUFFERING_DATA:
+ m_buffering = param1;
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange)));
+ break;
+ case EC_COMPLETE:
+ m_executedTasks &= ~(Play | Pause);
+ m_executedTasks |= Stop;
+
+ m_buffering = false;
+ m_atEnd = true;
+
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ LONGLONG position = 0;
+
+ seeking->GetCurrentPosition(&position);
+ seeking->Release();
+
+ m_position = position / qt_directShowTimeScale;
+ }
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(EndOfMedia)));
+ break;
+ case EC_LENGTH_CHANGED:
+ if (IMediaSeeking *seeking = com_cast<IMediaSeeking>(m_graph, IID_IMediaSeeking)) {
+ LONGLONG duration = 0;
+ seeking->GetDuration(&duration);
+ m_duration = duration / qt_directShowTimeScale;
+
+ DWORD capabilities = 0;
+ seeking->GetCapabilities(&capabilities);
+ m_seekable = capabilities & AM_SEEKING_CanSeekAbsolute;
+
+ seeking->Release();
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(DurationChange)));
+ }
+ break;
+ default:
+ break;
+ }
+
+ event->FreeEventParams(eventCode, param1, param2);
+ }
+ event->Release();
+ }
+}
+
+void DirectShowPlayerService::updateStatus()
+{
+ switch (m_graphStatus) {
+ case NoMedia:
+ m_playerControl->updateStatus(QMediaPlayer::NoMedia);
+ break;
+ case Loading:
+ m_playerControl->updateStatus(QMediaPlayer::LoadingMedia);
+ break;
+ case Loaded:
+ if ((m_pendingTasks | m_executingTask | m_executedTasks) & (Play | Pause)) {
+ if (m_buffering)
+ m_playerControl->updateStatus(QMediaPlayer::BufferingMedia);
+ else
+ m_playerControl->updateStatus(QMediaPlayer::BufferedMedia);
+ } else {
+ m_playerControl->updateStatus(QMediaPlayer::LoadedMedia);
+ }
+ break;
+ case InvalidMedia:
+ m_playerControl->updateStatus(QMediaPlayer::InvalidMedia);
+ break;
+ default:
+ m_playerControl->updateStatus(QMediaPlayer::UnknownMediaStatus);
+ }
+}
+
+bool DirectShowPlayerService::isConnected(IBaseFilter *filter, PIN_DIRECTION direction) const
+{
+ bool connected = false;
+
+ IEnumPins *pins = 0;
+
+ if (SUCCEEDED(filter->EnumPins(&pins))) {
+ for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) {
+ PIN_DIRECTION dir;
+ if (SUCCEEDED(pin->QueryDirection(&dir)) && dir == direction) {
+ IPin *peer = 0;
+ if (SUCCEEDED(pin->ConnectedTo(&peer))) {
+ connected = true;
+
+ peer->Release();
+ }
+ }
+ }
+ pins->Release();
+ }
+ return connected;
+}
+
+IBaseFilter *DirectShowPlayerService::getConnected(
+ IBaseFilter *filter, PIN_DIRECTION direction) const
+{
+ IBaseFilter *connected = 0;
+
+ IEnumPins *pins = 0;
+
+ if (SUCCEEDED(filter->EnumPins(&pins))) {
+ for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) {
+ PIN_DIRECTION dir;
+ if (SUCCEEDED(pin->QueryDirection(&dir)) && dir == direction) {
+ IPin *peer = 0;
+ if (SUCCEEDED(pin->ConnectedTo(&peer))) {
+ PIN_INFO info;
+
+ if (SUCCEEDED(peer->QueryPinInfo(&info))) {
+ if (connected) {
+ qWarning("DirectShowPlayerService::getConnected: "
+ "Multiple connected filters");
+ connected->Release();
+ }
+ connected = info.pFilter;
+ }
+ peer->Release();
+ }
+ }
+ }
+ pins->Release();
+ }
+ return connected;
+}
+
+void DirectShowPlayerService::run()
+{
+ QMutexLocker locker(&m_mutex);
+
+ for (;;) {
+ ::ResetEvent(m_taskHandle);
+
+ while (m_pendingTasks == 0) {
+ DWORD result = 0;
+
+ locker.unlock();
+ if (m_eventHandle) {
+ HANDLE handles[] = { m_taskHandle, m_eventHandle };
+
+ result = ::WaitForMultipleObjects(2, handles, false, INFINITE);
+ } else {
+ result = ::WaitForSingleObject(m_taskHandle, INFINITE);
+ }
+ locker.relock();
+
+ if (result == WAIT_OBJECT_0 + 1) {
+ graphEvent(&locker);
+ }
+ }
+
+ if (m_pendingTasks & ReleaseGraph) {
+ m_pendingTasks ^= ReleaseGraph;
+ m_executingTask = ReleaseGraph;
+
+ doReleaseGraph(&locker);
+ //if the graph is released, we should not process other operations later
+ if (m_pendingTasks & Shutdown) {
+ m_pendingTasks = 0;
+ return;
+ }
+ m_pendingTasks = 0;
+ } else if (m_pendingTasks & Shutdown) {
+ return;
+ } else if (m_pendingTasks & ReleaseAudioOutput) {
+ m_pendingTasks ^= ReleaseAudioOutput;
+ m_executingTask = ReleaseAudioOutput;
+
+ doReleaseAudioOutput(&locker);
+ } else if (m_pendingTasks & ReleaseVideoOutput) {
+ m_pendingTasks ^= ReleaseVideoOutput;
+ m_executingTask = ReleaseVideoOutput;
+
+ doReleaseVideoOutput(&locker);
+ } else if (m_pendingTasks & SetUrlSource) {
+ m_pendingTasks ^= SetUrlSource;
+ m_executingTask = SetUrlSource;
+
+ doSetUrlSource(&locker);
+ } else if (m_pendingTasks & SetStreamSource) {
+ m_pendingTasks ^= SetStreamSource;
+ m_executingTask = SetStreamSource;
+
+ doSetStreamSource(&locker);
+ } else if (m_pendingTasks & Render) {
+ m_pendingTasks ^= Render;
+ m_executingTask = Render;
+
+ doRender(&locker);
+ } else if (!(m_executedTasks & Render)) {
+ m_pendingTasks &= ~(FinalizeLoad | SetRate | Stop | Pause | Seek | Play);
+ } else if (m_pendingTasks & FinalizeLoad) {
+ m_pendingTasks ^= FinalizeLoad;
+ m_executingTask = FinalizeLoad;
+
+ doFinalizeLoad(&locker);
+ } else if (m_pendingTasks & Stop) {
+ m_pendingTasks ^= Stop;
+ m_executingTask = Stop;
+
+ doStop(&locker);
+ } else if (m_pendingTasks & SetRate) {
+ m_pendingTasks ^= SetRate;
+ m_executingTask = SetRate;
+
+ doSetRate(&locker);
+ } else if (m_pendingTasks & Pause) {
+ m_pendingTasks ^= Pause;
+ m_executingTask = Pause;
+
+ doPause(&locker);
+ } else if (m_pendingTasks & Seek) {
+ m_pendingTasks ^= Seek;
+ m_executingTask = Seek;
+
+ doSeek(&locker);
+ } else if (m_pendingTasks & Play) {
+ m_pendingTasks ^= Play;
+ m_executingTask = Play;
+
+ doPlay(&locker);
+ }
+ m_executingTask = 0;
+ }
+}
diff --git a/src/plugins/directshow/player/directshowplayerservice.h b/src/plugins/directshow/player/directshowplayerservice.h
new file mode 100644
index 000000000..cc0cac1cf
--- /dev/null
+++ b/src/plugins/directshow/player/directshowplayerservice.h
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** 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$
+** 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 DIRECTSHOWPLAYERSERVICE_H
+#define DIRECTSHOWPLAYERSERVICE_H
+
+#include "qmediaplayer.h"
+#include "qmediaresource.h"
+#include "qmediaservice.h"
+#include "qmediatimerange.h"
+
+#include "directshoweventloop.h"
+#include "directshowglobal.h"
+
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qwaitcondition.h>
+
+class DirectShowAudioEndpointControl;
+class DirectShowMetaDataControl;
+class DirectShowPlayerControl;
+class DirectShowVideoRendererControl;
+#ifndef Q_WS_SIMULATOR
+class Vmr9VideoWindowControl;
+#endif
+
+QT_BEGIN_NAMESPACE
+class QMediaContent;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class DirectShowPlayerService : public QMediaService
+{
+ Q_OBJECT
+public:
+ enum StreamType
+ {
+ AudioStream = 0x01,
+ VideoStream = 0x02
+ };
+
+ DirectShowPlayerService(QObject *parent = 0);
+ ~DirectShowPlayerService();
+
+ QMediaControl* requestControl(const char *name);
+ void releaseControl(QMediaControl *control);
+
+ void load(const QMediaContent &media, QIODevice *stream);
+ void play();
+ void pause();
+ void stop();
+
+ qint64 position() const;
+ QMediaTimeRange availablePlaybackRanges() const;
+
+ void seek(qint64 position);
+ void setRate(qreal rate);
+
+ int bufferStatus() const;
+
+ void setAudioOutput(IBaseFilter *filter);
+ void setVideoOutput(IBaseFilter *filter);
+
+protected:
+ void customEvent(QEvent *event);
+
+private Q_SLOTS:
+ void videoOutputChanged();
+
+private:
+ void releaseGraph();
+ void updateStatus();
+
+ int findStreamTypes(IBaseFilter *source) const;
+ int findStreamType(IPin *pin) const;
+
+ bool isConnected(IBaseFilter *filter, PIN_DIRECTION direction) const;
+ IBaseFilter *getConnected(IBaseFilter *filter, PIN_DIRECTION direction) const;
+
+ void run();
+
+ void doSetUrlSource(QMutexLocker *locker);
+ void doSetStreamSource(QMutexLocker *locker);
+ void doRender(QMutexLocker *locker);
+ void doFinalizeLoad(QMutexLocker *locker);
+ void doSetRate(QMutexLocker *locker);
+ void doSeek(QMutexLocker *locker);
+ void doPlay(QMutexLocker *locker);
+ void doPause(QMutexLocker *locker);
+ void doStop(QMutexLocker *locker);
+ void doReleaseAudioOutput(QMutexLocker *locker);
+ void doReleaseVideoOutput(QMutexLocker *locker);
+ void doReleaseGraph(QMutexLocker *locker);
+
+ void graphEvent(QMutexLocker *locker);
+
+ enum Task
+ {
+ Shutdown = 0x0001,
+ SetUrlSource = 0x0002,
+ SetStreamSource = 0x0004,
+ SetSource = SetUrlSource | SetStreamSource,
+ SetAudioOutput = 0x0008,
+ SetVideoOutput = 0x0010,
+ SetOutputs = SetAudioOutput | SetVideoOutput,
+ Render = 0x0020,
+ FinalizeLoad = 0x0040,
+ SetRate = 0x0080,
+ Seek = 0x0100,
+ Play = 0x0200,
+ Pause = 0x0400,
+ Stop = 0x0800,
+ ReleaseGraph = 0x1000,
+ ReleaseAudioOutput = 0x2000,
+ ReleaseVideoOutput = 0x4000,
+ ReleaseFilters = ReleaseGraph | ReleaseAudioOutput | ReleaseVideoOutput
+ };
+
+ enum Event
+ {
+ FinalizedLoad = QEvent::User,
+ Error,
+ RateChange,
+ Started,
+ Paused,
+ DurationChange,
+ StatusChange,
+ EndOfMedia,
+ PositionChange
+ };
+
+ enum GraphStatus
+ {
+ NoMedia,
+ Loading,
+ Loaded,
+ InvalidMedia
+ };
+
+ DirectShowPlayerControl *m_playerControl;
+ DirectShowMetaDataControl *m_metaDataControl;
+ DirectShowVideoRendererControl *m_videoRendererControl;
+#ifndef Q_WS_SIMULATOR
+ Vmr9VideoWindowControl *m_videoWindowControl;
+#endif
+ DirectShowAudioEndpointControl *m_audioEndpointControl;
+
+ QThread *m_taskThread;
+ DirectShowEventLoop *m_loop;
+ int m_pendingTasks;
+ int m_executingTask;
+ int m_executedTasks;
+ HANDLE m_taskHandle;
+ HANDLE m_eventHandle;
+ GraphStatus m_graphStatus;
+ QMediaPlayer::Error m_error;
+ QIODevice *m_stream;
+ IFilterGraph2 *m_graph;
+ IBaseFilter *m_source;
+ IBaseFilter *m_audioOutput;
+ IBaseFilter *m_videoOutput;
+ int m_streamTypes;
+ qreal m_rate;
+ qint64 m_position;
+ qint64 m_duration;
+ bool m_buffering;
+ bool m_seekable;
+ bool m_atEnd;
+ QMediaTimeRange m_playbackRange;
+ QUrl m_url;
+ QMediaResourceList m_resources;
+ QString m_errorString;
+ QMutex m_mutex;
+
+ friend class DirectShowPlayerServiceThread;
+};
+
+
+#endif
diff --git a/src/plugins/directshow/player/directshowsamplescheduler.cpp b/src/plugins/directshow/player/directshowsamplescheduler.cpp
new file mode 100644
index 000000000..48b7899c6
--- /dev/null
+++ b/src/plugins/directshow/player/directshowsamplescheduler.cpp
@@ -0,0 +1,437 @@
+/****************************************************************************
+**
+** 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$
+** 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 "directshowsamplescheduler.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qcoreevent.h>
+
+class DirectShowTimedSample
+{
+public:
+ DirectShowTimedSample(IMediaSample *sample)
+ : m_next(0)
+ , m_sample(sample)
+ , m_cookie(0)
+ , m_lastSample(false)
+ {
+ m_sample->AddRef();
+ }
+
+ ~DirectShowTimedSample()
+ {
+ m_sample->Release();
+ }
+
+ IMediaSample *sample() const { return m_sample; }
+
+ DirectShowTimedSample *nextSample() const { return m_next; }
+ void setNextSample(DirectShowTimedSample *sample) { Q_ASSERT(!m_next); m_next = sample; }
+
+ DirectShowTimedSample *remove() {
+ DirectShowTimedSample *next = m_next; delete this; return next; }
+
+ bool schedule(IReferenceClock *clock, REFERENCE_TIME startTime, HANDLE handle);
+ void unschedule(IReferenceClock *clock);
+
+ bool isReady(IReferenceClock *clock) const;
+
+ bool isLast() const { return m_lastSample; }
+ void setLast() { m_lastSample = true; }
+
+private:
+ DirectShowTimedSample *m_next;
+ IMediaSample *m_sample;
+ DWORD_PTR m_cookie;
+ bool m_lastSample;
+};
+
+bool DirectShowTimedSample::schedule(
+ IReferenceClock *clock, REFERENCE_TIME startTime, HANDLE handle)
+{
+ REFERENCE_TIME sampleStartTime;
+ REFERENCE_TIME sampleEndTime;
+ if (m_sample->GetTime(&sampleStartTime, &sampleEndTime) == S_OK) {
+ if (clock->AdviseTime(
+ startTime, sampleStartTime, reinterpret_cast<HEVENT>(handle), &m_cookie) == S_OK) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void DirectShowTimedSample::unschedule(IReferenceClock *clock)
+{
+ clock->Unadvise(m_cookie);
+}
+
+bool DirectShowTimedSample::isReady(IReferenceClock *clock) const
+{
+ REFERENCE_TIME sampleStartTime;
+ REFERENCE_TIME sampleEndTime;
+ REFERENCE_TIME currentTime;
+ if (m_sample->GetTime(&sampleStartTime, &sampleEndTime) == S_OK) {
+ if (clock->GetTime(&currentTime) == S_OK)
+ return currentTime >= sampleStartTime;
+ }
+ return true;
+}
+
+DirectShowSampleScheduler::DirectShowSampleScheduler(IUnknown *pin, QObject *parent)
+ : QObject(parent)
+ , m_pin(pin)
+ , m_clock(0)
+ , m_allocator(0)
+ , m_head(0)
+ , m_tail(0)
+ , m_maximumSamples(1)
+ , m_state(Stopped)
+ , m_startTime(0)
+ , m_timeoutEvent(::CreateEvent(0, 0, 0, 0))
+ , m_flushEvent(::CreateEvent(0, 0, 0, 0))
+{
+ m_semaphore.release(m_maximumSamples);
+}
+
+DirectShowSampleScheduler::~DirectShowSampleScheduler()
+{
+ ::CloseHandle(m_timeoutEvent);
+ ::CloseHandle(m_flushEvent);
+
+ Q_ASSERT(!m_clock);
+ Q_ASSERT(!m_allocator);
+}
+
+HRESULT DirectShowSampleScheduler::QueryInterface(REFIID riid, void **ppvObject)
+{
+ return m_pin->QueryInterface(riid, ppvObject);
+}
+
+ULONG DirectShowSampleScheduler::AddRef()
+{
+ return m_pin->AddRef();
+}
+
+ULONG DirectShowSampleScheduler::Release()
+{
+ return m_pin->Release();
+}
+
+// IMemInputPin
+HRESULT DirectShowSampleScheduler::GetAllocator(IMemAllocator **ppAllocator)
+{
+ if (!ppAllocator) {
+ return E_POINTER;
+ } else {
+ QMutexLocker locker(&m_mutex);
+
+ if (!m_allocator) {
+ return VFW_E_NO_ALLOCATOR;
+ } else {
+ *ppAllocator = m_allocator;
+
+ return S_OK;
+ }
+ }
+}
+
+HRESULT DirectShowSampleScheduler::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
+{
+ Q_UNUSED(bReadOnly);
+
+ HRESULT hr;
+ ALLOCATOR_PROPERTIES properties;
+
+ if (!pAllocator) {
+ if (m_allocator)
+ m_allocator->Release();
+
+ m_allocator = 0;
+
+ return S_OK;
+ } else if ((hr = pAllocator->GetProperties(&properties)) != S_OK) {
+ return hr;
+ } else {
+ if (properties.cBuffers == 1) {
+ ALLOCATOR_PROPERTIES actual;
+
+ properties.cBuffers = 2;
+ if ((hr = pAllocator->SetProperties(&properties, &actual)) != S_OK)
+ return hr;
+ }
+
+ QMutexLocker locker(&m_mutex);
+
+ if (m_allocator)
+ m_allocator->Release();
+
+ m_allocator = pAllocator;
+ m_allocator->AddRef();
+
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowSampleScheduler::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
+{
+ if (!pProps)
+ return E_POINTER;
+
+ pProps->cBuffers = 2;
+
+ return S_OK;
+}
+
+HRESULT DirectShowSampleScheduler::Receive(IMediaSample *pSample)
+{
+ if (!pSample)
+ return E_POINTER;
+
+ m_semaphore.acquire(1);
+
+ QMutexLocker locker(&m_mutex);
+
+ if (m_state & Flushing) {
+ m_semaphore.release(1);
+
+ return S_FALSE;
+ } else if (m_state == Stopped) {
+ m_semaphore.release();
+
+ return VFW_E_WRONG_STATE;
+ } else {
+ DirectShowTimedSample *timedSample = new DirectShowTimedSample(pSample);
+
+ if (m_tail)
+ m_tail->setNextSample(timedSample);
+ else
+ m_head = timedSample;
+
+ m_tail = timedSample;
+
+ if (m_state == Running) {
+ if (!timedSample->schedule(m_clock, m_startTime, m_timeoutEvent)) {
+ // Timing information is unavailable, so schedule frames immediately.
+ QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
+ } else {
+ locker.unlock();
+ HANDLE handles[] = { m_flushEvent, m_timeoutEvent };
+ DWORD result = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
+ locker.relock();
+
+ if (result == WAIT_OBJECT_0 + 1)
+ QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
+ }
+ } else if (m_tail == m_head) {
+ // If this is the first frame make it available.
+ QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
+
+ if (m_state == Paused) {
+ ::ResetEvent(m_timeoutEvent);
+
+ locker.unlock();
+ HANDLE handles[] = { m_flushEvent, m_timeoutEvent };
+ ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
+ locker.relock();
+ }
+ }
+
+ return S_OK;
+ }
+}
+
+HRESULT DirectShowSampleScheduler::ReceiveMultiple(
+ IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
+{
+ if (!pSamples || !nSamplesProcessed)
+ return E_POINTER;
+
+ for (*nSamplesProcessed = 0; *nSamplesProcessed < nSamples; ++(*nSamplesProcessed)) {
+ HRESULT hr = Receive(pSamples[*nSamplesProcessed]);
+
+ if (hr != S_OK)
+ return hr;
+ }
+ return S_OK;
+}
+
+HRESULT DirectShowSampleScheduler::ReceiveCanBlock()
+{
+ return S_OK;
+}
+
+void DirectShowSampleScheduler::run(REFERENCE_TIME startTime)
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_state = (m_state & Flushing) | Running;
+ m_startTime = startTime;
+
+ for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample()) {
+ sample->schedule(m_clock, m_startTime, m_timeoutEvent);
+ }
+
+ if (!(m_state & Flushing))
+ ::ResetEvent(m_flushEvent);
+
+ if (!m_head)
+ ::SetEvent(m_timeoutEvent);
+
+}
+
+void DirectShowSampleScheduler::pause()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_state = (m_state & Flushing) | Paused;
+
+ for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample())
+ sample->unschedule(m_clock);
+
+ if (!(m_state & Flushing))
+ ::ResetEvent(m_flushEvent);
+}
+
+void DirectShowSampleScheduler::stop()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_state = m_state & Flushing;
+
+ for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) {
+ sample->unschedule(m_clock);
+
+ m_semaphore.release(1);
+ }
+
+ m_head = 0;
+ m_tail = 0;
+
+ ::SetEvent(m_flushEvent);
+}
+
+void DirectShowSampleScheduler::setFlushing(bool flushing)
+{
+ QMutexLocker locker(&m_mutex);
+
+ const bool isFlushing = m_state & Flushing;
+
+ if (isFlushing != flushing) {
+ if (flushing) {
+ m_state |= Flushing;
+
+ for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) {
+ sample->unschedule(m_clock);
+
+ m_semaphore.release(1);
+ }
+ m_head = 0;
+ m_tail = 0;
+
+ ::SetEvent(m_flushEvent);
+ } else {
+ m_state &= ~Flushing;
+
+ if (m_state != Stopped)
+ ::ResetEvent(m_flushEvent);
+ }
+ }
+}
+
+void DirectShowSampleScheduler::setClock(IReferenceClock *clock)
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (m_clock)
+ m_clock->Release();
+
+ m_clock = clock;
+
+ if (m_clock)
+ m_clock->AddRef();
+}
+
+IMediaSample *DirectShowSampleScheduler::takeSample(bool *eos)
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (m_head && m_head->isReady(m_clock)) {
+ IMediaSample *sample = m_head->sample();
+ sample->AddRef();
+
+ *eos = m_head->isLast();
+
+ m_head = m_head->remove();
+
+ if (!m_head)
+ m_tail = 0;
+
+ m_semaphore.release(1);
+
+ return sample;
+ } else {
+ return 0;
+ }
+}
+
+bool DirectShowSampleScheduler::scheduleEndOfStream()
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (m_tail) {
+ m_tail->setLast();
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool DirectShowSampleScheduler::event(QEvent *event)
+{
+ if (event->type() == QEvent::UpdateRequest) {
+ emit sampleReady();
+
+ return true;
+ } else {
+ return QObject::event(event);
+ }
+}
diff --git a/src/plugins/directshow/player/directshowsamplescheduler.h b/src/plugins/directshow/player/directshowsamplescheduler.h
new file mode 100644
index 000000000..bea833ef9
--- /dev/null
+++ b/src/plugins/directshow/player/directshowsamplescheduler.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 DIRECTSHOWSAMPLESCHEDULER_H
+#define DIRECTSHOWSAMPLESCHEDULER_H
+
+#include <QtCore/qmutex.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qsemaphore.h>
+
+#include <dshow.h>
+
+class DirectShowTimedSample;
+
+class DirectShowSampleScheduler : public QObject, public IMemInputPin
+{
+ Q_OBJECT
+public:
+
+ enum State
+ {
+ Stopped = 0x00,
+ Running = 0x01,
+ Paused = 0x02,
+ RunMask = 0x03,
+ Flushing = 0x04
+ };
+
+ DirectShowSampleScheduler(IUnknown *pin, QObject *parent = 0);
+ ~DirectShowSampleScheduler();
+
+ // IUnknown
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ // IMemInputPin
+ HRESULT STDMETHODCALLTYPE GetAllocator(IMemAllocator **ppAllocator);
+ HRESULT STDMETHODCALLTYPE NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly);
+ HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);
+
+ HRESULT STDMETHODCALLTYPE Receive(IMediaSample *pSample);
+ HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed);
+ HRESULT STDMETHODCALLTYPE ReceiveCanBlock();
+
+ void run(REFERENCE_TIME startTime);
+ void pause();
+ void stop();
+ void setFlushing(bool flushing);
+
+ IReferenceClock *clock() const { return m_clock; }
+ void setClock(IReferenceClock *clock);
+
+ bool schedule(IMediaSample *sample);
+ bool scheduleEndOfStream();
+
+ IMediaSample *takeSample(bool *eos);
+
+ bool event(QEvent *event);
+
+Q_SIGNALS:
+ void sampleReady();
+
+private:
+ IUnknown *m_pin;
+ IReferenceClock *m_clock;
+ IMemAllocator *m_allocator;
+ DirectShowTimedSample *m_head;
+ DirectShowTimedSample *m_tail;
+ int m_maximumSamples;
+ int m_state;
+ REFERENCE_TIME m_startTime;
+ HANDLE m_timeoutEvent;
+ HANDLE m_flushEvent;
+ QSemaphore m_semaphore;
+ QMutex m_mutex;
+};
+
+#endif
diff --git a/src/plugins/directshow/player/directshowvideorenderercontrol.cpp b/src/plugins/directshow/player/directshowvideorenderercontrol.cpp
new file mode 100644
index 000000000..429d5e1ec
--- /dev/null
+++ b/src/plugins/directshow/player/directshowvideorenderercontrol.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "directshowvideorenderercontrol.h"
+
+#include "videosurfacefilter.h"
+
+DirectShowVideoRendererControl::DirectShowVideoRendererControl(DirectShowEventLoop *loop, QObject *parent)
+ : QVideoRendererControl(parent)
+ , m_loop(loop)
+ , m_surface(0)
+ , m_filter(0)
+{
+}
+
+DirectShowVideoRendererControl::~DirectShowVideoRendererControl()
+{
+ delete m_filter;
+}
+
+QAbstractVideoSurface *DirectShowVideoRendererControl::surface() const
+{
+ return m_surface;
+}
+
+void DirectShowVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
+{
+ if (surface != m_surface) {
+ m_surface = surface;
+
+ VideoSurfaceFilter *existingFilter = m_filter;
+
+ if (surface) {
+ m_filter = new VideoSurfaceFilter(surface, m_loop);
+ } else {
+ m_filter = 0;
+ }
+
+ emit filterChanged();
+
+ delete existingFilter;
+ }
+}
+
+IBaseFilter *DirectShowVideoRendererControl::filter()
+{
+ return m_filter;
+}
diff --git a/src/plugins/directshow/player/directshowvideorenderercontrol.h b/src/plugins/directshow/player/directshowvideorenderercontrol.h
new file mode 100644
index 000000000..5057a94e0
--- /dev/null
+++ b/src/plugins/directshow/player/directshowvideorenderercontrol.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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$
+** 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 DIRECTSHOWVIDEORENDERERCONTROL_H
+#define DIRECTSHOWVIDEORENDERERCONTROL_H
+
+#include "qvideorenderercontrol.h"
+
+#include <dshow.h>
+
+class DirectShowEventLoop;
+class VideoSurfaceFilter;
+
+QT_USE_NAMESPACE
+
+class DirectShowVideoRendererControl : public QVideoRendererControl
+{
+ Q_OBJECT
+public:
+ DirectShowVideoRendererControl(DirectShowEventLoop *loop, QObject *parent = 0);
+ ~DirectShowVideoRendererControl();
+
+ QAbstractVideoSurface *surface() const;
+ void setSurface(QAbstractVideoSurface *surface);
+
+ IBaseFilter *filter();
+
+Q_SIGNALS:
+ void filterChanged();
+
+private:
+ DirectShowEventLoop *m_loop;
+ QAbstractVideoSurface *m_surface;
+ VideoSurfaceFilter *m_filter;
+};
+
+#endif
diff --git a/src/plugins/directshow/player/mediasamplevideobuffer.cpp b/src/plugins/directshow/player/mediasamplevideobuffer.cpp
new file mode 100644
index 000000000..a2d1d7cee
--- /dev/null
+++ b/src/plugins/directshow/player/mediasamplevideobuffer.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "mediasamplevideobuffer.h"
+
+MediaSampleVideoBuffer::MediaSampleVideoBuffer(IMediaSample *sample, int bytesPerLine)
+ : QAbstractVideoBuffer(NoHandle)
+ , m_sample(sample)
+ , m_bytesPerLine(bytesPerLine)
+ , m_mapMode(NotMapped)
+{
+ m_sample->AddRef();
+}
+
+MediaSampleVideoBuffer::~MediaSampleVideoBuffer()
+{
+ m_sample->Release();
+}
+
+uchar *MediaSampleVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
+{
+ if (m_mapMode == NotMapped && mode != NotMapped) {
+ if (numBytes)
+ *numBytes = m_sample->GetActualDataLength();
+
+ if (bytesPerLine)
+ *bytesPerLine = m_bytesPerLine;
+
+ BYTE *bytes = 0;
+
+ if (m_sample->GetPointer(&bytes) == S_OK) {
+ m_mapMode = mode;
+
+ return reinterpret_cast<uchar *>(bytes);
+ }
+ }
+ return 0;
+}
+
+void MediaSampleVideoBuffer::unmap()
+{
+ m_mapMode = NotMapped;
+}
+
+QAbstractVideoBuffer::MapMode MediaSampleVideoBuffer::mapMode() const
+{
+ return m_mapMode;
+}
diff --git a/src/plugins/directshow/player/mediasamplevideobuffer.h b/src/plugins/directshow/player/mediasamplevideobuffer.h
new file mode 100644
index 000000000..0d44e7a1f
--- /dev/null
+++ b/src/plugins/directshow/player/mediasamplevideobuffer.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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$
+** 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 MEDIASAMPLEVIDEOBUFFER_H
+#define MEDIASAMPLEVIDEOBUFFER_H
+
+#include <qabstractvideobuffer.h>
+
+#include <dshow.h>
+
+class MediaSampleVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ MediaSampleVideoBuffer(IMediaSample *sample, int bytesPerLine);
+ ~MediaSampleVideoBuffer();
+
+ IMediaSample *sample() { return m_sample; }
+
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine);
+ void unmap();
+
+ MapMode mapMode() const;
+
+private:
+ IMediaSample *m_sample;
+ int m_bytesPerLine;
+ MapMode m_mapMode;
+};
+
+
+#endif
diff --git a/src/plugins/directshow/player/player.pri b/src/plugins/directshow/player/player.pri
new file mode 100644
index 000000000..a058b0659
--- /dev/null
+++ b/src/plugins/directshow/player/player.pri
@@ -0,0 +1,47 @@
+INCLUDEPATH += $$PWD
+
+DEFINES += QMEDIA_DIRECTSHOW_PLAYER
+
+HEADERS += \
+ $$PWD/directshowaudioendpointcontrol.h \
+ $$PWD/directshoweventloop.h \
+ $$PWD/directshowglobal.h \
+ $$PWD/directshowioreader.h \
+ $$PWD/directshowiosource.h \
+ $$PWD/directshowmediatype.h \
+ $$PWD/directshowmediatypelist.h \
+ $$PWD/directshowmetadatacontrol.h \
+ $$PWD/directshowpinenum.h \
+ $$PWD/directshowplayercontrol.h \
+ $$PWD/directshowplayerservice.h \
+ $$PWD/directshowsamplescheduler.h \
+ $$PWD/directshowvideorenderercontrol.h \
+ $$PWD/mediasamplevideobuffer.h \
+ $$PWD/videosurfacefilter.h
+
+SOURCES += \
+ $$PWD/directshowaudioendpointcontrol.cpp \
+ $$PWD/directshoweventloop.cpp \
+ $$PWD/directshowioreader.cpp \
+ $$PWD/directshowiosource.cpp \
+ $$PWD/directshowmediatype.cpp \
+ $$PWD/directshowmediatypelist.cpp \
+ $$PWD/directshowmetadatacontrol.cpp \
+ $$PWD/directshowpinenum.cpp \
+ $$PWD/directshowplayercontrol.cpp \
+ $$PWD/directshowplayerservice.cpp \
+ $$PWD/directshowsamplescheduler.cpp \
+ $$PWD/directshowvideorenderercontrol.cpp \
+ $$PWD/mediasamplevideobuffer.cpp \
+ $$PWD/videosurfacefilter.cpp
+
+!simulator {
+HEADERS += \
+ $$PWD/vmr9videowindowcontrol.h
+
+SOURCES += \
+ $$PWD/vmr9videowindowcontrol.cpp
+}
+
+LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 -lgdi32
+
diff --git a/src/plugins/directshow/player/videosurfacefilter.cpp b/src/plugins/directshow/player/videosurfacefilter.cpp
new file mode 100644
index 000000000..a6a3c1b4f
--- /dev/null
+++ b/src/plugins/directshow/player/videosurfacefilter.cpp
@@ -0,0 +1,631 @@
+/****************************************************************************
+**
+** 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$
+** 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 "videosurfacefilter.h"
+
+#include "directshoweventloop.h"
+#include "directshowglobal.h"
+#include "directshowpinenum.h"
+#include "mediasamplevideobuffer.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qthread.h>
+#include <qabstractvideosurface.h>
+
+#include <initguid.h>
+
+// { e23cad72-153d-406c-bf3f-4c4b523d96f2 }
+DEFINE_GUID(CLSID_VideoSurfaceFilter,
+0xe23cad72, 0x153d, 0x406c, 0xbf, 0x3f, 0x4c, 0x4b, 0x52, 0x3d, 0x96, 0xf2);
+
+VideoSurfaceFilter::VideoSurfaceFilter(
+ QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent)
+ : QObject(parent)
+ , m_ref(1)
+ , m_state(State_Stopped)
+ , m_surface(surface)
+ , m_loop(loop)
+ , m_graph(0)
+ , m_peerPin(0)
+ , m_bytesPerLine(0)
+ , m_startResult(S_OK)
+ , m_pinId(QString::fromLatin1("reference"))
+ , m_sampleScheduler(static_cast<IPin *>(this))
+{
+ connect(surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged()));
+ connect(&m_sampleScheduler, SIGNAL(sampleReady()), this, SLOT(sampleReady()));
+}
+
+VideoSurfaceFilter::~VideoSurfaceFilter()
+{
+ Q_ASSERT(m_ref == 1);
+}
+
+HRESULT VideoSurfaceFilter::QueryInterface(REFIID riid, void **ppvObject)
+{
+ // 2dd74950-a890-11d1-abe8-00a0c905f375
+ static const GUID iid_IAmFilterMiscFlags = {
+ 0x2dd74950, 0xa890, 0x11d1, {0xab, 0xe8, 0x00, 0xa0, 0xc9, 0x05, 0xf3, 0x75} };
+
+ if (!ppvObject) {
+ return E_POINTER;
+ } else if (riid == IID_IUnknown
+ || riid == IID_IPersist
+ || riid == IID_IMediaFilter
+ || riid == IID_IBaseFilter) {
+ *ppvObject = static_cast<IBaseFilter *>(this);
+ } else if (riid == iid_IAmFilterMiscFlags) {
+ *ppvObject = static_cast<IAMFilterMiscFlags *>(this);
+ } else if (riid == IID_IPin) {
+ *ppvObject = static_cast<IPin *>(this);
+ } else if (riid == IID_IMemInputPin) {
+ *ppvObject = static_cast<IMemInputPin *>(&m_sampleScheduler);
+ } else {
+ *ppvObject = 0;
+
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+
+ return S_OK;
+}
+
+ULONG VideoSurfaceFilter::AddRef()
+{
+ return InterlockedIncrement(&m_ref);
+}
+
+ULONG VideoSurfaceFilter::Release()
+{
+ ULONG ref = InterlockedDecrement(&m_ref);
+
+ Q_ASSERT(ref != 0);
+
+ return ref;
+}
+
+HRESULT VideoSurfaceFilter::GetClassID(CLSID *pClassID)
+{
+ *pClassID = CLSID_VideoSurfaceFilter;
+
+ return S_OK;
+}
+
+HRESULT VideoSurfaceFilter::Run(REFERENCE_TIME tStart)
+{
+ m_state = State_Running;
+
+ m_sampleScheduler.run(tStart);
+
+ return S_OK;
+}
+
+HRESULT VideoSurfaceFilter::Pause()
+{
+ m_state = State_Paused;
+
+ m_sampleScheduler.pause();
+
+ return S_OK;
+}
+
+HRESULT VideoSurfaceFilter::Stop()
+{
+ m_state = State_Stopped;
+
+ m_sampleScheduler.stop();
+
+ return S_OK;
+}
+
+HRESULT VideoSurfaceFilter::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
+{
+ if (!pState)
+ return E_POINTER;
+
+ *pState = m_state;
+
+ return S_OK;
+}
+
+HRESULT VideoSurfaceFilter::SetSyncSource(IReferenceClock *pClock)
+{
+
+ m_sampleScheduler.setClock(pClock);
+
+ return S_OK;
+}
+
+HRESULT VideoSurfaceFilter::GetSyncSource(IReferenceClock **ppClock)
+{
+ if (!ppClock) {
+ return E_POINTER;
+ } else {
+ *ppClock = m_sampleScheduler.clock();
+
+ if (*ppClock) {
+ (*ppClock)->AddRef();
+
+ return S_OK;
+ } else {
+ return S_FALSE;
+ }
+ }
+}
+
+HRESULT VideoSurfaceFilter::EnumPins(IEnumPins **ppEnum)
+{
+ if (ppEnum) {
+ *ppEnum = new DirectShowPinEnum(QList<IPin *>() << this);
+
+ return S_OK;
+ } else {
+ return E_POINTER;
+ }
+}
+
+HRESULT VideoSurfaceFilter::FindPin(LPCWSTR pId, IPin **ppPin)
+{
+ if (!ppPin || !pId) {
+ return E_POINTER;
+ } else if (QString::fromWCharArray(pId) == m_pinId) {
+ AddRef();
+
+ *ppPin = this;
+
+ return S_OK;
+ } else {
+ return VFW_E_NOT_FOUND;
+ }
+}
+
+HRESULT VideoSurfaceFilter::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName)
+{
+ m_graph = pGraph;
+ m_name = QString::fromWCharArray(pName);
+
+ return S_OK;
+}
+
+HRESULT VideoSurfaceFilter::QueryFilterInfo(FILTER_INFO *pInfo)
+{
+ if (pInfo) {
+ QString name = m_name;
+
+ if (name.length() >= MAX_FILTER_NAME)
+ name.truncate(MAX_FILTER_NAME - 1);
+
+ int length = name.toWCharArray(pInfo->achName);
+ pInfo->achName[length] = '\0';
+
+ if (m_graph)
+ m_graph->AddRef();
+
+ pInfo->pGraph = m_graph;
+
+ return S_OK;
+ } else {
+ return E_POINTER;
+ }
+}
+
+HRESULT VideoSurfaceFilter::QueryVendorInfo(LPWSTR *pVendorInfo)
+{
+ Q_UNUSED(pVendorInfo);
+
+ return E_NOTIMPL;
+}
+
+ULONG VideoSurfaceFilter::GetMiscFlags()
+{
+ return AM_FILTER_MISC_FLAGS_IS_RENDERER;
+}
+
+
+HRESULT VideoSurfaceFilter::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
+{
+ // This is an input pin, you shouldn't be calling Connect on it.
+ return E_POINTER;
+}
+
+HRESULT VideoSurfaceFilter::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
+{
+ if (!pConnector) {
+ return E_POINTER;
+ } else if (!pmt) {
+ return E_POINTER;
+ } else {
+ HRESULT hr;
+ QMutexLocker locker(&m_mutex);
+
+ if (m_peerPin) {
+ hr = VFW_E_ALREADY_CONNECTED;
+ } else if (pmt->majortype != MEDIATYPE_Video) {
+ hr = VFW_E_TYPE_NOT_ACCEPTED;
+ } else {
+ m_surfaceFormat = DirectShowMediaType::formatFromType(*pmt);
+ m_bytesPerLine = DirectShowMediaType::bytesPerLine(m_surfaceFormat);
+
+ if (thread() == QThread::currentThread()) {
+ hr = start();
+ } else {
+ m_loop->postEvent(this, new QEvent(QEvent::Type(StartSurface)));
+
+ m_wait.wait(&m_mutex);
+
+ hr = m_startResult;
+ }
+ }
+ if (hr == S_OK) {
+ m_peerPin = pConnector;
+ m_peerPin->AddRef();
+
+ DirectShowMediaType::copy(&m_mediaType, *pmt);
+ }
+ return hr;
+ }
+}
+
+HRESULT VideoSurfaceFilter::start()
+{
+ if (!m_surface->isFormatSupported(m_surfaceFormat)) {
+ return VFW_E_TYPE_NOT_ACCEPTED;
+ }
+ if (!m_surface->start(m_surfaceFormat)) {
+ return VFW_E_TYPE_NOT_ACCEPTED;
+ } else {
+ return S_OK;
+ }
+}
+
+HRESULT VideoSurfaceFilter::Disconnect()
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (!m_peerPin)
+ return S_FALSE;
+
+ if (thread() == QThread::currentThread()) {
+ stop();
+ } else {
+ m_loop->postEvent(this, new QEvent(QEvent::Type(StopSurface)));
+
+ m_wait.wait(&m_mutex);
+ }
+
+ m_mediaType.clear();
+
+ m_sampleScheduler.NotifyAllocator(0, FALSE);
+
+ m_peerPin->Release();
+ m_peerPin = 0;
+
+ return S_OK;
+}
+
+void VideoSurfaceFilter::stop()
+{
+ m_surface->stop();
+}
+
+HRESULT VideoSurfaceFilter::ConnectedTo(IPin **ppPin)
+{
+ if (!ppPin) {
+ return E_POINTER;
+ } else {
+ QMutexLocker locker(&m_mutex);
+
+ if (!m_peerPin) {
+ return VFW_E_NOT_CONNECTED;
+ } else {
+ m_peerPin->AddRef();
+
+ *ppPin = m_peerPin;
+
+ return S_OK;
+ }
+ }
+}
+
+HRESULT VideoSurfaceFilter::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
+{
+ if (!pmt) {
+ return E_POINTER;
+ } else {
+ QMutexLocker locker(&m_mutex);
+
+ if (!m_peerPin) {
+ return VFW_E_NOT_CONNECTED;
+ } else {
+ DirectShowMediaType::copy(pmt, m_mediaType);
+
+ return S_OK;
+ }
+ }
+}
+
+HRESULT VideoSurfaceFilter::QueryPinInfo(PIN_INFO *pInfo)
+{
+ if (!pInfo) {
+ return E_POINTER;
+ } else {
+ AddRef();
+
+ pInfo->pFilter = this;
+ pInfo->dir = PINDIR_INPUT;
+
+ const int bytes = qMin(MAX_FILTER_NAME, (m_pinId.length() + 1) * 2);
+
+ qMemCopy(pInfo->achName, m_pinId.utf16(), bytes);
+
+ return S_OK;
+ }
+}
+
+HRESULT VideoSurfaceFilter::QueryId(LPWSTR *Id)
+{
+ if (!Id) {
+ return E_POINTER;
+ } else {
+ const int bytes = (m_pinId.length() + 1) * 2;
+
+ *Id = static_cast<LPWSTR>(::CoTaskMemAlloc(bytes));
+
+ qMemCopy(*Id, m_pinId.utf16(), bytes);
+
+ return S_OK;
+ }
+}
+
+HRESULT VideoSurfaceFilter::QueryAccept(const AM_MEDIA_TYPE *pmt)
+{
+ return !m_surface->isFormatSupported(DirectShowMediaType::formatFromType(*pmt))
+ ? S_OK
+ : S_FALSE;
+}
+
+HRESULT VideoSurfaceFilter::EnumMediaTypes(IEnumMediaTypes **ppEnum)
+{
+ if (!ppEnum) {
+ return E_POINTER;
+ } else {
+ QMutexLocker locker(&m_mutex);
+
+ *ppEnum = createMediaTypeEnum();
+
+ return S_OK;
+ }
+}
+
+HRESULT VideoSurfaceFilter::QueryInternalConnections(IPin **apPin, ULONG *nPin)
+{
+ Q_UNUSED(apPin);
+ Q_UNUSED(nPin);
+
+ return E_NOTIMPL;
+}
+
+HRESULT VideoSurfaceFilter::EndOfStream()
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (!m_sampleScheduler.scheduleEndOfStream()) {
+ if (IMediaEventSink *sink = com_cast<IMediaEventSink>(m_graph, IID_IMediaEventSink)) {
+ sink->Notify(
+ EC_COMPLETE,
+ S_OK,
+ reinterpret_cast<LONG_PTR>(static_cast<IBaseFilter *>(this)));
+ sink->Release();
+ }
+ }
+
+ return S_OK;
+}
+
+HRESULT VideoSurfaceFilter::BeginFlush()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_sampleScheduler.setFlushing(true);
+
+ if (thread() == QThread::currentThread()) {
+ flush();
+ } else {
+ m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface)));
+
+ m_wait.wait(&m_mutex);
+ }
+
+ return S_OK;
+}
+
+HRESULT VideoSurfaceFilter::EndFlush()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_sampleScheduler.setFlushing(false);
+
+ return S_OK;
+}
+
+void VideoSurfaceFilter::flush()
+{
+ m_surface->present(QVideoFrame());
+
+ m_wait.wakeAll();
+}
+
+HRESULT VideoSurfaceFilter::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
+{
+ Q_UNUSED(tStart);
+ Q_UNUSED(tStop);
+ Q_UNUSED(dRate);
+
+ return S_OK;
+}
+
+HRESULT VideoSurfaceFilter::QueryDirection(PIN_DIRECTION *pPinDir)
+{
+ if (!pPinDir) {
+ return E_POINTER;
+ } else {
+ *pPinDir = PINDIR_INPUT;
+
+ return S_OK;
+ }
+}
+
+int VideoSurfaceFilter::currentMediaTypeToken()
+{
+ QMutexLocker locker(&m_mutex);
+
+ return DirectShowMediaTypeList::currentMediaTypeToken();
+}
+
+HRESULT VideoSurfaceFilter::nextMediaType(
+ int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount)
+{
+ QMutexLocker locker(&m_mutex);
+
+ return DirectShowMediaTypeList::nextMediaType(token, index, count, types, fetchedCount);
+
+}
+
+HRESULT VideoSurfaceFilter::skipMediaType(int token, int *index, ULONG count)
+{
+ QMutexLocker locker(&m_mutex);
+
+ return DirectShowMediaTypeList::skipMediaType(token, index, count);
+}
+
+HRESULT VideoSurfaceFilter::cloneMediaType(int token, int index, IEnumMediaTypes **enumeration)
+{
+ QMutexLocker locker(&m_mutex);
+
+ return DirectShowMediaTypeList::cloneMediaType(token, index, enumeration);
+}
+
+void VideoSurfaceFilter::customEvent(QEvent *event)
+{
+ if (event->type() == StartSurface) {
+ QMutexLocker locker(&m_mutex);
+
+ m_startResult = start();
+
+ m_wait.wakeAll();
+ } else if (event->type() == StopSurface) {
+ QMutexLocker locker(&m_mutex);
+
+ stop();
+
+ m_wait.wakeAll();
+ } else if (event->type() == FlushSurface) {
+ QMutexLocker locker(&m_mutex);
+
+ flush();
+
+ m_wait.wakeAll();
+ } else {
+ QObject::customEvent(event);
+ }
+}
+
+void VideoSurfaceFilter::supportedFormatsChanged()
+{
+ QMutexLocker locker(&m_mutex);
+
+ // MEDIASUBTYPE_None;
+ static const GUID none = {
+ 0xe436eb8e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70} };
+
+ QList<QVideoFrame::PixelFormat> formats = m_surface->supportedPixelFormats();
+
+ QVector<AM_MEDIA_TYPE> mediaTypes;
+ mediaTypes.reserve(formats.count());
+
+ AM_MEDIA_TYPE type;
+ type.majortype = MEDIATYPE_Video;
+ type.bFixedSizeSamples = TRUE;
+ type.bTemporalCompression = FALSE;
+ type.lSampleSize = 0;
+ type.formattype = GUID_NULL;
+ type.pUnk = 0;
+ type.cbFormat = 0;
+ type.pbFormat = 0;
+
+ foreach (QVideoFrame::PixelFormat format, formats) {
+ type.subtype = DirectShowMediaType::convertPixelFormat(format);
+
+ if (type.subtype != none)
+ mediaTypes.append(type);
+ }
+
+ setMediaTypes(mediaTypes);
+}
+
+void VideoSurfaceFilter::sampleReady()
+{
+ bool eos = false;
+
+ IMediaSample *sample = m_sampleScheduler.takeSample(&eos);
+
+ if (sample) {
+ m_surface->present(QVideoFrame(
+ new MediaSampleVideoBuffer(sample, m_bytesPerLine),
+ m_surfaceFormat.frameSize(),
+ m_surfaceFormat.pixelFormat()));
+
+ sample->Release();
+
+ if (eos) {
+ if (IMediaEventSink *sink = com_cast<IMediaEventSink>(m_graph, IID_IMediaEventSink)) {
+ sink->Notify(
+ EC_COMPLETE,
+ S_OK,
+ reinterpret_cast<LONG_PTR>(static_cast<IBaseFilter *>(this)));
+ sink->Release();
+ }
+ }
+ }
+}
+
diff --git a/src/plugins/directshow/player/videosurfacefilter.h b/src/plugins/directshow/player/videosurfacefilter.h
new file mode 100644
index 000000000..a58971630
--- /dev/null
+++ b/src/plugins/directshow/player/videosurfacefilter.h
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 VIDEOSURFACEFILTER_H
+#define VIDEOSURFACEFILTER_H
+
+#include "directshowglobal.h"
+#include "directshowmediatypelist.h"
+#include "directshowsamplescheduler.h"
+#include "directshowmediatype.h"
+
+#include <QtCore/qbasictimer.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qsemaphore.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qwaitcondition.h>
+
+#include <dshow.h>
+
+QT_BEGIN_NAMESPACE
+class QAbstractVideoSurface;
+QT_END_NAMESPACE
+
+class DirectShowEventLoop;
+
+class VideoSurfaceFilter
+ : public QObject
+ , public DirectShowMediaTypeList
+ , public IBaseFilter
+ , public IAMFilterMiscFlags
+ , public IPin
+{
+ Q_OBJECT
+public:
+ VideoSurfaceFilter(
+ QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent = 0);
+ ~VideoSurfaceFilter();
+
+ // IUnknown
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ // IPersist
+ HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
+
+ // IMediaFilter
+ HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
+ HRESULT STDMETHODCALLTYPE Pause();
+ HRESULT STDMETHODCALLTYPE Stop();
+
+ HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState);
+
+ HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
+ HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **ppClock);
+
+ // IBaseFilter
+ HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
+ HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
+
+ HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
+
+ HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
+ HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
+
+ // IAMFilterMiscFlags
+ ULONG STDMETHODCALLTYPE GetMiscFlags();
+
+ // IPin
+ HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
+ HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
+ HRESULT STDMETHODCALLTYPE Disconnect();
+ HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **ppPin);
+
+ HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
+
+ HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
+ HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
+
+ HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
+
+ HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
+
+ HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
+
+ HRESULT STDMETHODCALLTYPE EndOfStream();
+
+ HRESULT STDMETHODCALLTYPE BeginFlush();
+ HRESULT STDMETHODCALLTYPE EndFlush();
+
+ HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
+
+ HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
+
+ int currentMediaTypeToken();
+ HRESULT nextMediaType(
+ int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount);
+ HRESULT skipMediaType(int token, int *index, ULONG count);
+ HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration);
+
+protected:
+ void customEvent(QEvent *event);
+
+private Q_SLOTS:
+ void supportedFormatsChanged();
+ void sampleReady();
+
+private:
+ HRESULT start();
+ void stop();
+ void flush();
+
+ enum
+ {
+ StartSurface = QEvent::User,
+ StopSurface,
+ FlushSurface
+ };
+
+ LONG m_ref;
+ FILTER_STATE m_state;
+ QAbstractVideoSurface *m_surface;
+ DirectShowEventLoop *m_loop;
+ IFilterGraph *m_graph;
+ IPin *m_peerPin;
+ int m_bytesPerLine;
+ HRESULT m_startResult;
+ QString m_name;
+ QString m_pinId;
+ DirectShowMediaType m_mediaType;
+ QVideoSurfaceFormat m_surfaceFormat;
+ QMutex m_mutex;
+ QWaitCondition m_wait;
+ DirectShowSampleScheduler m_sampleScheduler;
+};
+
+#endif
diff --git a/src/plugins/directshow/player/vmr9videowindowcontrol.cpp b/src/plugins/directshow/player/vmr9videowindowcontrol.cpp
new file mode 100644
index 000000000..5e729844b
--- /dev/null
+++ b/src/plugins/directshow/player/vmr9videowindowcontrol.cpp
@@ -0,0 +1,329 @@
+/****************************************************************************
+**
+** 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$
+** 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 "vmr9videowindowcontrol.h"
+
+#include "directshowglobal.h"
+
+Vmr9VideoWindowControl::Vmr9VideoWindowControl(QObject *parent)
+ : QVideoWindowControl(parent)
+ , m_filter(com_new<IBaseFilter>(CLSID_VideoMixingRenderer9, IID_IBaseFilter))
+ , m_windowId(0)
+ , m_dirtyValues(0)
+ , m_aspectRatioMode(Qt::KeepAspectRatio)
+ , m_brightness(0)
+ , m_contrast(0)
+ , m_hue(0)
+ , m_saturation(0)
+ , m_fullScreen(false)
+{
+ if (IVMRFilterConfig9 *config = com_cast<IVMRFilterConfig9>(m_filter, IID_IVMRFilterConfig9)) {
+ config->SetRenderingMode(VMR9Mode_Windowless);
+ config->SetNumberOfStreams(1);
+ config->Release();
+ }
+}
+
+Vmr9VideoWindowControl::~Vmr9VideoWindowControl()
+{
+ if (m_filter)
+ m_filter->Release();
+}
+
+
+WId Vmr9VideoWindowControl::winId() const
+{
+ return m_windowId;
+
+}
+
+void Vmr9VideoWindowControl::setWinId(WId id)
+{
+ m_windowId = id;
+
+ if (QWidget *widget = QWidget::find(m_windowId)) {
+ const QColor color = widget->palette().color(QPalette::Window);
+
+ m_windowColor = RGB(color.red(), color.green(), color.blue());
+ }
+
+ if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
+ m_filter, IID_IVMRWindowlessControl9)) {
+ control->SetVideoClippingWindow(m_windowId);
+ control->SetBorderColor(m_windowColor);
+ control->Release();
+ }
+}
+
+QRect Vmr9VideoWindowControl::displayRect() const
+{
+ return m_displayRect;
+}
+
+void Vmr9VideoWindowControl::setDisplayRect(const QRect &rect)
+{
+ m_displayRect = rect;
+
+ if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
+ m_filter, IID_IVMRWindowlessControl9)) {
+ RECT sourceRect = { 0, 0, 0, 0 };
+ RECT displayRect = { rect.left(), rect.top(), rect.right() + 1, rect.bottom() + 1 };
+
+ control->GetNativeVideoSize(&sourceRect.right, &sourceRect.bottom, 0, 0);
+
+ if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
+ QSize clippedSize = rect.size();
+ clippedSize.scale(sourceRect.right, sourceRect.bottom, Qt::KeepAspectRatio);
+
+ sourceRect.left = (sourceRect.right - clippedSize.width()) / 2;
+ sourceRect.top = (sourceRect.bottom - clippedSize.height()) / 2;
+ sourceRect.right = sourceRect.left + clippedSize.width();
+ sourceRect.bottom = sourceRect.top + clippedSize.height();
+ }
+
+ control->SetVideoPosition(&sourceRect, &displayRect);
+ control->Release();
+ }
+}
+
+bool Vmr9VideoWindowControl::isFullScreen() const
+{
+ return m_fullScreen;
+}
+
+void Vmr9VideoWindowControl::setFullScreen(bool fullScreen)
+{
+ emit fullScreenChanged(m_fullScreen = fullScreen);
+}
+
+void Vmr9VideoWindowControl::repaint()
+{
+ PAINTSTRUCT paint;
+
+ if (HDC dc = ::BeginPaint(m_windowId, &paint)) {
+ HRESULT hr = E_FAIL;
+
+ if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
+ m_filter, IID_IVMRWindowlessControl9)) {
+ hr = control->RepaintVideo(m_windowId, dc);
+ control->Release();
+ }
+
+ if (!SUCCEEDED(hr)) {
+ HPEN pen = ::CreatePen(PS_SOLID, 1, m_windowColor);
+ HBRUSH brush = ::CreateSolidBrush(m_windowColor);
+ ::SelectObject(dc, pen);
+ ::SelectObject(dc, brush);
+
+ ::Rectangle(
+ dc,
+ m_displayRect.left(),
+ m_displayRect.top(),
+ m_displayRect.right() + 1,
+ m_displayRect.bottom() + 1);
+
+ ::DeleteObject(pen);
+ ::DeleteObject(brush);
+ }
+ ::EndPaint(m_windowId, &paint);
+ }
+}
+
+QSize Vmr9VideoWindowControl::nativeSize() const
+{
+ QSize size;
+
+ if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
+ m_filter, IID_IVMRWindowlessControl9)) {
+ LONG width;
+ LONG height;
+
+ if (control->GetNativeVideoSize(&width, &height, 0, 0) == S_OK)
+ size = QSize(width, height);
+ control->Release();
+ }
+ return size;
+}
+
+Qt::AspectRatioMode Vmr9VideoWindowControl::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void Vmr9VideoWindowControl::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_aspectRatioMode = mode;
+
+ if (IVMRWindowlessControl9 *control = com_cast<IVMRWindowlessControl9>(
+ m_filter, IID_IVMRWindowlessControl9)) {
+ switch (mode) {
+ case Qt::IgnoreAspectRatio:
+ control->SetAspectRatioMode(VMR9ARMode_None);
+ break;
+ case Qt::KeepAspectRatio:
+ control->SetAspectRatioMode(VMR9ARMode_LetterBox);
+ break;
+ case Qt::KeepAspectRatioByExpanding:
+ control->SetAspectRatioMode(VMR9ARMode_LetterBox);
+ setDisplayRect(m_displayRect);
+ break;
+ default:
+ break;
+ }
+ control->Release();
+ }
+}
+
+int Vmr9VideoWindowControl::brightness() const
+{
+ return m_brightness;
+}
+
+void Vmr9VideoWindowControl::setBrightness(int brightness)
+{
+ m_brightness = brightness;
+
+ m_dirtyValues |= ProcAmpControl9_Brightness;
+
+ setProcAmpValues();
+
+ emit brightnessChanged(brightness);
+}
+
+int Vmr9VideoWindowControl::contrast() const
+{
+ return m_contrast;
+}
+
+void Vmr9VideoWindowControl::setContrast(int contrast)
+{
+ m_contrast = contrast;
+
+ m_dirtyValues |= ProcAmpControl9_Contrast;
+
+ setProcAmpValues();
+
+ emit contrastChanged(contrast);
+}
+
+int Vmr9VideoWindowControl::hue() const
+{
+ return m_hue;
+}
+
+void Vmr9VideoWindowControl::setHue(int hue)
+{
+ m_hue = hue;
+
+ m_dirtyValues |= ProcAmpControl9_Hue;
+
+ setProcAmpValues();
+
+ emit hueChanged(hue);
+}
+
+int Vmr9VideoWindowControl::saturation() const
+{
+ return m_saturation;
+}
+
+void Vmr9VideoWindowControl::setSaturation(int saturation)
+{
+ m_saturation = saturation;
+
+ m_dirtyValues |= ProcAmpControl9_Saturation;
+
+ setProcAmpValues();
+
+ emit saturationChanged(saturation);
+}
+
+void Vmr9VideoWindowControl::setProcAmpValues()
+{
+ if (IVMRMixerControl9 *control = com_cast<IVMRMixerControl9>(m_filter, IID_IVMRMixerControl9)) {
+ VMR9ProcAmpControl procAmp;
+ procAmp.dwSize = sizeof(VMR9ProcAmpControl);
+ procAmp.dwFlags = m_dirtyValues;
+
+ if (m_dirtyValues & ProcAmpControl9_Brightness) {
+ procAmp.Brightness = scaleProcAmpValue(
+ control, ProcAmpControl9_Brightness, m_brightness);
+ }
+ if (m_dirtyValues & ProcAmpControl9_Contrast) {
+ procAmp.Contrast = scaleProcAmpValue(
+ control, ProcAmpControl9_Contrast, m_contrast);
+ }
+ if (m_dirtyValues & ProcAmpControl9_Hue) {
+ procAmp.Hue = scaleProcAmpValue(
+ control, ProcAmpControl9_Hue, m_hue);
+ }
+ if (m_dirtyValues & ProcAmpControl9_Saturation) {
+ procAmp.Saturation = scaleProcAmpValue(
+ control, ProcAmpControl9_Saturation, m_saturation);
+ }
+
+ if (SUCCEEDED(control->SetProcAmpControl(0, &procAmp))) {
+ m_dirtyValues = 0;
+ }
+
+ control->Release();
+ }
+}
+
+float Vmr9VideoWindowControl::scaleProcAmpValue(
+ IVMRMixerControl9 *control, VMR9ProcAmpControlFlags property, int value) const
+{
+ float scaledValue = 0.0;
+
+ VMR9ProcAmpControlRange range;
+ range.dwSize = sizeof(VMR9ProcAmpControlRange);
+ range.dwProperty = property;
+
+ if (SUCCEEDED(control->GetProcAmpControlRange(0, &range))) {
+ scaledValue = range.DefaultValue;
+ if (value > 0)
+ scaledValue += float(value) * (range.MaxValue - range.DefaultValue) / 100;
+ else if (value < 0)
+ scaledValue -= float(value) * (range.MinValue - range.DefaultValue) / 100;
+ }
+
+ return scaledValue;
+}
diff --git a/src/plugins/directshow/player/vmr9videowindowcontrol.h b/src/plugins/directshow/player/vmr9videowindowcontrol.h
new file mode 100644
index 000000000..b4e39a7fd
--- /dev/null
+++ b/src/plugins/directshow/player/vmr9videowindowcontrol.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** 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$
+** 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 VMR9VIDEOWINDOWCONTROL_H
+#define VMR9VIDEOWINDOWCONTROL_H
+
+#include "qvideowindowcontrol.h"
+
+#include <dshow.h>
+#include <d3d9.h>
+#include <vmr9.h>
+
+QT_USE_NAMESPACE
+
+class Vmr9VideoWindowControl : public QVideoWindowControl
+{
+ Q_OBJECT
+public:
+ Vmr9VideoWindowControl(QObject *parent = 0);
+ ~Vmr9VideoWindowControl();
+
+ IBaseFilter *filter() const { return m_filter; }
+
+ WId winId() const;
+ void setWinId(WId id);
+
+ QRect displayRect() const;
+ void setDisplayRect(const QRect &rect);
+
+ bool isFullScreen() const;
+ void setFullScreen(bool fullScreen);
+
+ void repaint();
+
+ QSize nativeSize() const;
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+private:
+ void setProcAmpValues();
+ float scaleProcAmpValue(
+ IVMRMixerControl9 *control, VMR9ProcAmpControlFlags property, int value) const;
+
+ IBaseFilter *m_filter;
+ WId m_windowId;
+ COLORREF m_windowColor;
+ DWORD m_dirtyValues;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QRect m_displayRect;
+ int m_brightness;
+ int m_contrast;
+ int m_hue;
+ int m_saturation;
+ bool m_fullScreen;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/camerabin/camerabin.pri b/src/plugins/gstreamer/camerabin/camerabin.pri
new file mode 100644
index 000000000..5c266e784
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabin.pri
@@ -0,0 +1,50 @@
+INCLUDEPATH += $$PWD \
+ $${SOURCE_DIR}/src/multimedia
+
+INCLUDEPATH += camerabin
+
+DEFINES += QMEDIA_GSTREAMER_CAMERABIN
+
+LIBS += -lgstphotography-0.10
+
+DEFINES += GST_USE_UNSTABLE_API #prevents warnings because of unstable photography API
+
+HEADERS += \
+ $$PWD/camerabinservice.h \
+ $$PWD/camerabinsession.h \
+ $$PWD/camerabincontrol.h \
+ $$PWD/camerabinaudioencoder.h \
+ $$PWD/camerabinfocus.h \
+ $$PWD/camerabinimageencoder.h \
+ $$PWD/camerabinlocks.h \
+ $$PWD/camerabinrecorder.h \
+ $$PWD/camerabincontainer.h \
+ $$PWD/camerabinexposure.h \
+ $$PWD/camerabinflash.h \
+ $$PWD/camerabinimagecapture.h \
+ $$PWD/camerabinimageprocessing.h \
+ $$PWD/camerabinmetadata.h \
+ $$PWD/camerabinvideoencoder.h \
+ $$PWD/camerabinresourcepolicy.h \
+ $$PWD/camerabincapturedestination.h \
+ $$PWD/camerabincapturebufferformat.h
+
+SOURCES += \
+ $$PWD/camerabinservice.cpp \
+ $$PWD/camerabinsession.cpp \
+ $$PWD/camerabincontrol.cpp \
+ $$PWD/camerabinaudioencoder.cpp \
+ $$PWD/camerabincontainer.cpp \
+ $$PWD/camerabinexposure.cpp \
+ $$PWD/camerabinflash.cpp \
+ $$PWD/camerabinfocus.cpp \
+ $$PWD/camerabinimagecapture.cpp \
+ $$PWD/camerabinimageencoder.cpp \
+ $$PWD/camerabinimageprocessing.cpp \
+ $$PWD/camerabinlocks.cpp \
+ $$PWD/camerabinmetadata.cpp \
+ $$PWD/camerabinrecorder.cpp \
+ $$PWD/camerabinvideoencoder.cpp \
+ $$PWD/camerabinresourcepolicy.cpp \
+ $$PWD/camerabincapturedestination.cpp \
+ $$PWD/camerabincapturebufferformat.cpp
diff --git a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp
new file mode 100644
index 000000000..d028fb3e7
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.cpp
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** 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$
+** 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 "camerabinaudioencoder.h"
+#include "camerabincontainer.h"
+
+#include <QtCore/qdebug.h>
+
+CameraBinAudioEncoder::CameraBinAudioEncoder(QObject *parent)
+ :QAudioEncoderControl(parent)
+{
+ QList<QByteArray> codecCandidates;
+
+#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
+ codecCandidates << "audio/AAC" << "audio/PCM" << "audio/AMR" << "audio/AMR-WB" << "audio/speex"
+ << "audio/ADPCM" << "audio/iLBC" << "audio/vorbis" << "audio/mpeg" << "audio/FLAC";
+
+ m_elementNames["audio/AAC"] = "nokiaaacenc";
+ m_elementNames["audio/speex"] = "speexenc";
+ m_elementNames["audio/PCM"] = "audioresample";
+ m_elementNames["audio/AMR"] = "nokiaamrnbenc";
+ m_elementNames["audio/AMR-WB"] = "nokiaamrwbenc";
+ m_elementNames["audio/ADPCM"] = "nokiaadpcmenc";
+ m_elementNames["audio/iLBC"] = "nokiailbcenc";
+ m_elementNames["audio/vorbis"] = "vorbisenc";
+ m_elementNames["audio/FLAC"] = "flacenc";
+ m_elementNames["audio/mpeg"] = "ffenc_mp2";
+#else
+ codecCandidates << "audio/mpeg" << "audio/vorbis" << "audio/speex" << "audio/GSM"
+ << "audio/PCM" << "audio/AMR" << "audio/AMR-WB";
+
+ m_elementNames["audio/mpeg"] = "lamemp3enc";
+ m_elementNames["audio/vorbis"] = "vorbisenc";
+ m_elementNames["audio/speex"] = "speexenc";
+ m_elementNames["audio/GSM"] = "gsmenc";
+ m_elementNames["audio/PCM"] = "audioresample";
+ m_elementNames["audio/AMR"] = "amrnbenc";
+ m_elementNames["audio/AMR-WB"] = "amrwbenc";
+
+ m_codecOptions["audio/vorbis"] = QStringList() << "min-bitrate" << "max-bitrate";
+ m_codecOptions["audio/mpeg"] = QStringList() << "mode";
+ m_codecOptions["audio/speex"] = QStringList() << "mode" << "vbr" << "vad" << "dtx";
+ m_codecOptions["audio/GSM"] = QStringList();
+ m_codecOptions["audio/PCM"] = QStringList();
+ m_codecOptions["audio/AMR"] = QStringList();
+ m_codecOptions["audio/AMR-WB"] = QStringList();
+#endif
+
+ foreach( const QByteArray& codecName, codecCandidates ) {
+ QByteArray elementName = m_elementNames[codecName];
+ GstElementFactory *factory = gst_element_factory_find(elementName.constData());
+
+ if (factory) {
+ m_codecs.append(codecName);
+ const gchar *descr = gst_element_factory_get_description(factory);
+
+ if (codecName == QByteArray("audio/PCM"))
+ m_codecDescriptions.insert(codecName, tr("Raw PCM audio"));
+ else
+ m_codecDescriptions.insert(codecName, QString::fromUtf8(descr));
+
+ m_streamTypes.insert(codecName,
+ CameraBinContainer::supportedStreamTypes(factory, GST_PAD_SRC));
+
+ gst_object_unref(GST_OBJECT(factory));
+ }
+ }
+}
+
+CameraBinAudioEncoder::~CameraBinAudioEncoder()
+{
+}
+
+QStringList CameraBinAudioEncoder::supportedAudioCodecs() const
+{
+ return m_codecs;
+}
+
+QString CameraBinAudioEncoder::codecDescription(const QString &codecName) const
+{
+ return m_codecDescriptions.value(codecName);
+}
+
+QStringList CameraBinAudioEncoder::supportedEncodingOptions(const QString &codec) const
+{
+ return m_codecOptions.value(codec);
+}
+
+QVariant CameraBinAudioEncoder::encodingOption(
+ const QString &codec, const QString &name) const
+{
+ return m_options[codec].value(name);
+}
+
+void CameraBinAudioEncoder::setEncodingOption(
+ const QString &codec, const QString &name, const QVariant &value)
+{
+ m_options[codec][name] = value;
+}
+
+QList<int> CameraBinAudioEncoder::supportedSampleRates(const QAudioEncoderSettings &, bool *) const
+{
+ //TODO check element caps to find actual values
+
+ return QList<int>();
+}
+
+QAudioEncoderSettings CameraBinAudioEncoder::audioSettings() const
+{
+ return m_audioSettings;
+}
+
+void CameraBinAudioEncoder::setAudioSettings(const QAudioEncoderSettings &settings)
+{
+ m_userSettings = settings;
+ m_audioSettings = settings;
+ emit settingsChanged();
+}
+
+void CameraBinAudioEncoder::setActualAudioSettings(const QAudioEncoderSettings &settings)
+{
+ m_audioSettings = settings;
+}
+
+void CameraBinAudioEncoder::resetActualSettings()
+{
+ m_audioSettings = m_userSettings;
+}
+
+GstElement *CameraBinAudioEncoder::createEncoder()
+{
+ QString codec = m_audioSettings.codec();
+ QByteArray encoderElementName = m_elementNames.value(codec);
+ GstElement *encoderElement = gst_element_factory_make(encoderElementName.constData(), NULL);
+ if (!encoderElement)
+ return 0;
+
+ GstBin * encoderBin = GST_BIN(gst_bin_new("audio-encoder-bin"));
+ GstElement *capsFilter = gst_element_factory_make("capsfilter", NULL);
+
+ gst_bin_add(encoderBin, capsFilter);
+ gst_bin_add(encoderBin, encoderElement);
+ gst_element_link(capsFilter, encoderElement);
+
+ // add ghostpads
+ GstPad *pad = gst_element_get_static_pad(capsFilter, "sink");
+ gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("sink", pad));
+ gst_object_unref(GST_OBJECT(pad));
+
+ pad = gst_element_get_static_pad(encoderElement, "src");
+ gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("src", pad));
+ gst_object_unref(GST_OBJECT(pad));
+
+ if (m_audioSettings.sampleRate() > 0 || m_audioSettings.channelCount() > 0) {
+ GstCaps *caps = gst_caps_new_empty();
+ GstStructure *structure = gst_structure_new("audio/x-raw-int", NULL);
+
+ if (m_audioSettings.sampleRate() > 0)
+ gst_structure_set(structure, "rate", G_TYPE_INT, m_audioSettings.sampleRate(), NULL );
+
+ if (m_audioSettings.channelCount() > 0)
+ gst_structure_set(structure, "channels", G_TYPE_INT, m_audioSettings.channelCount(), NULL );
+
+ gst_caps_append_structure(caps,structure);
+
+ g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
+ }
+
+ if (encoderElement) {
+ if (m_audioSettings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
+ QtMultimediaKit::EncodingQuality qualityValue = m_audioSettings.quality();
+
+ if (encoderElementName == "lamemp3enc") {
+ g_object_set(G_OBJECT(encoderElement), "target", 0, NULL); //constant quality mode
+ qreal quality[] = {
+ 10.0, //VeryLow
+ 6.0, //Low
+ 4.0, //Normal
+ 2.0, //High
+ 0.0 //VeryHigh
+ };
+ g_object_set(G_OBJECT(encoderElement), "quality", quality[qualityValue], NULL);
+ } else if (encoderElementName == "ffenc_mp2") {
+ int quality[] = {
+ 8000, //VeryLow
+ 64000, //Low
+ 128000, //Normal
+ 192000, //High
+ 320000 //VeryHigh
+ };
+ g_object_set(G_OBJECT(encoderElement), "bitrate", quality[qualityValue], NULL);
+ } else if (codec == QLatin1String("audio/speex")) {
+ //0-10 range with default 8
+ double qualityTable[] = {
+ 2, //VeryLow
+ 5, //Low
+ 8, //Normal
+ 9, //High
+ 10 //VeryHigh
+ };
+ g_object_set(G_OBJECT(encoderElement), "quality", qualityTable[qualityValue], NULL);
+ } else if (codec.startsWith("audio/AMR")) {
+ int band[] = {
+ 0, //VeryLow
+ 2, //Low
+ 4, //Normal
+ 6, //High
+ 7 //VeryHigh
+ };
+
+ g_object_set(G_OBJECT(encoderElement), "band-mode", band[qualityValue], NULL);
+ }
+ } else {
+ int bitrate = m_audioSettings.bitRate();
+ if (bitrate > 0) {
+ g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
+ }
+ }
+
+ QMap<QString, QVariant> options = m_options.value(codec);
+ QMapIterator<QString,QVariant> it(options);
+ while (it.hasNext()) {
+ it.next();
+ QString option = it.key();
+ QVariant value = it.value();
+
+ switch (value.type()) {
+ case QVariant::Int:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toInt(), NULL);
+ break;
+ case QVariant::Bool:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toBool(), NULL);
+ break;
+ case QVariant::Double:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toDouble(), NULL);
+ break;
+ case QVariant::String:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toString().toUtf8().constData(), NULL);
+ break;
+ default:
+ qWarning() << "unsupported option type:" << option << value;
+ break;
+ }
+ }
+ }
+
+ return GST_ELEMENT(encoderBin);
+
+}
+
+
+QSet<QString> CameraBinAudioEncoder::supportedStreamTypes(const QString &codecName) const
+{
+ return m_streamTypes.value(codecName);
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h
new file mode 100644
index 000000000..1790fc37d
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** 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$
+** 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 CAMERABINAUDIOENCODE_H
+#define CAMERABINAUDIOENCODE_H
+
+#include <qaudioencodercontrol.h>
+class CameraBinSession;
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qset.h>
+
+#include <gst/gst.h>
+
+#include <qaudioformat.h>
+
+QT_USE_NAMESPACE
+
+class CameraBinAudioEncoder : public QAudioEncoderControl
+{
+ Q_OBJECT
+public:
+ CameraBinAudioEncoder(QObject *parent);
+ virtual ~CameraBinAudioEncoder();
+
+ QStringList supportedAudioCodecs() const;
+ QString codecDescription(const QString &codecName) const;
+
+ QStringList supportedEncodingOptions(const QString &codec) const;
+ QVariant encodingOption(const QString &codec, const QString &name) const;
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
+
+ QList<int> supportedSampleRates(const QAudioEncoderSettings &settings = QAudioEncoderSettings(),
+ bool *isContinuous = 0) const;
+ QList<int> supportedChannelCounts(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const;
+ QList<int> supportedSampleSizes(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const;
+
+ QAudioEncoderSettings audioSettings() const;
+ void setAudioSettings(const QAudioEncoderSettings&);
+
+
+ GstElement *createEncoder();
+
+ QSet<QString> supportedStreamTypes(const QString &codecName) const;
+
+ void setActualAudioSettings(const QAudioEncoderSettings&);
+ void resetActualSettings();
+
+Q_SIGNALS:
+ void settingsChanged();
+
+private:
+ QStringList m_codecs;
+ QMap<QString,QByteArray> m_elementNames;
+ QMap<QString,QString> m_codecDescriptions;
+ QMap<QString,QStringList> m_codecOptions;
+
+ QMap<QString, QMap<QString, QVariant> > m_options;
+
+ QMap<QString, QSet<QString> > m_streamTypes;
+
+ QAudioEncoderSettings m_audioSettings;
+ QAudioEncoderSettings m_userSettings;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.cpp b/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.cpp
new file mode 100644
index 000000000..b99024f22
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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$
+** 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 "camerabincapturebufferformat.h"
+#include "camerabinsession.h"
+
+CameraBinCaptureBufferFormat::CameraBinCaptureBufferFormat(CameraBinSession *session)
+ :QCameraCaptureBufferFormatControl(session)
+ , m_session(session)
+ , m_format(QVideoFrame::Format_Jpeg)
+{
+}
+
+CameraBinCaptureBufferFormat::~CameraBinCaptureBufferFormat()
+{
+}
+
+QList<QVideoFrame::PixelFormat> CameraBinCaptureBufferFormat::supportedBufferFormats() const
+{
+ //the exact YUV format is unknown with camerabin until the first capture is requested
+ return QList<QVideoFrame::PixelFormat>()
+ << QVideoFrame::Format_Jpeg
+#ifdef Q_WS_MAEMO_6
+ << QVideoFrame::Format_UYVY
+#endif
+ ;
+}
+
+QVideoFrame::PixelFormat CameraBinCaptureBufferFormat::bufferFormat() const
+{
+ return m_format;
+}
+
+void CameraBinCaptureBufferFormat::setBufferFormat(QVideoFrame::PixelFormat format)
+{
+ if (m_format != format) {
+ m_format = format;
+ emit bufferFormatChanged(format);
+ }
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.h b/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.h
new file mode 100644
index 000000000..579ed239e
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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$
+** 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 CAMERABINCAPTUREBUFFERFORMAT_H
+#define CAMERABINCAPTUREBUFFERFORMAT_H
+
+#include <qcamera.h>
+#include <qcameracapturebufferformatcontrol.h>
+
+#include <gst/gst.h>
+#include <glib.h>
+
+class CameraBinSession;
+
+QT_USE_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT CameraBinCaptureBufferFormat : public QCameraCaptureBufferFormatControl
+{
+ Q_OBJECT
+public:
+ CameraBinCaptureBufferFormat(CameraBinSession *session);
+ virtual ~CameraBinCaptureBufferFormat();
+
+ QList<QVideoFrame::PixelFormat> supportedBufferFormats() const;
+
+ QVideoFrame::PixelFormat bufferFormat() const;
+ void setBufferFormat(QVideoFrame::PixelFormat format);
+
+private:
+ CameraBinSession *m_session;
+ QVideoFrame::PixelFormat m_format;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/camerabin/camerabincapturedestination.cpp b/src/plugins/gstreamer/camerabin/camerabincapturedestination.cpp
new file mode 100644
index 000000000..2a83637b4
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabincapturedestination.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** 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$
+** 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 "camerabincapturedestination.h"
+#include "camerabinsession.h"
+
+CameraBinCaptureDestination::CameraBinCaptureDestination(CameraBinSession *session)
+ :QCameraCaptureDestinationControl(session)
+ , m_session(session)
+ , m_destination(QCameraImageCapture::CaptureToFile)
+{
+}
+
+CameraBinCaptureDestination::~CameraBinCaptureDestination()
+{
+}
+
+
+bool CameraBinCaptureDestination::isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const
+{
+ //capture to buffer, file and both are supported.
+ return destination & (QCameraImageCapture::CaptureToFile | QCameraImageCapture::CaptureToBuffer);
+}
+
+QCameraImageCapture::CaptureDestinations CameraBinCaptureDestination::captureDestination() const
+{
+ return m_destination;
+}
+
+void CameraBinCaptureDestination::setCaptureDestination(QCameraImageCapture::CaptureDestinations destination)
+{
+ if (m_destination != destination) {
+ m_destination = destination;
+ emit captureDestinationChanged(m_destination);
+ }
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabincapturedestination.h b/src/plugins/gstreamer/camerabin/camerabincapturedestination.h
new file mode 100644
index 000000000..92c02f1b0
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabincapturedestination.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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$
+** 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 CAMERABINCAPTUREDESTINATION_H
+#define CAMERABINCAPTUREDESTINATION_H
+
+#include <qcameraimagecapture.h>
+#include <qcameracapturedestinationcontrol.h>
+
+
+class CameraBinSession;
+
+QT_USE_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT CameraBinCaptureDestination : public QCameraCaptureDestinationControl
+{
+ Q_OBJECT
+public:
+ CameraBinCaptureDestination(CameraBinSession *session);
+ virtual ~CameraBinCaptureDestination();
+
+ bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const;
+ QCameraImageCapture::CaptureDestinations captureDestination() const;
+ void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination);
+
+private:
+ CameraBinSession *m_session;
+ QCameraImageCapture::CaptureDestinations m_destination;
+};
+
+#endif // CAMERABINFLASHCONTROL_H
diff --git a/src/plugins/gstreamer/camerabin/camerabincontainer.cpp b/src/plugins/gstreamer/camerabin/camerabincontainer.cpp
new file mode 100644
index 000000000..97349204d
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabincontainer.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "camerabincontainer.h"
+
+
+#include <QtCore/qdebug.h>
+
+CameraBinContainer::CameraBinContainer(QObject *parent)
+ :QMediaContainerControl(parent)
+{
+ QList<QByteArray> formatCandidates;
+ formatCandidates << "mp4" << "ogg" << "wav" << "amr" << "mkv"
+ << "avi" << "3gp" << "3gp2" << "webm" << "mjpeg" << "asf" << "mov";
+
+ QMap<QString,QByteArray> elementNames;
+
+ elementNames.insertMulti("mp4", "ffmux_mp4");
+ elementNames.insertMulti("mp4", "hantromp4mux");
+ elementNames.insertMulti("mp4", "mp4mux");
+ elementNames.insert("ogg", "oggmux");
+ elementNames["wav"] = "wavenc";
+ elementNames["amr"] = "ffmux_amr";
+ elementNames["mkv"] = "matroskamux";
+ elementNames["avi"] = "avimux";
+ elementNames["3gp"] = "ffmux_3gp";
+ elementNames["3gp2"] = "ffmux_3g2";
+ elementNames["webm"] = "webmmux";
+ elementNames["mjpeg"] = "ffmux_mjpeg";
+ elementNames["asf"] = "ffmux_asf";
+ elementNames["mov"] = "qtmux";
+
+ QSet<QString> allTypes;
+
+ foreach(const QByteArray &formatName, formatCandidates) {
+ foreach(const QByteArray &elementName, elementNames.values(formatName)) {
+ GstElementFactory *factory = gst_element_factory_find(elementName.constData());
+ if (factory) {
+ m_supportedContainers.append(formatName);
+ const gchar *descr = gst_element_factory_get_description(factory);
+ m_containerDescriptions.insert(formatName, QString::fromUtf8(descr));
+
+
+ if (formatName == QByteArray("raw")) {
+ m_streamTypes.insert(formatName, allTypes);
+ } else {
+ QSet<QString> types = supportedStreamTypes(factory, GST_PAD_SINK);
+ m_streamTypes.insert(formatName, types);
+ allTypes.unite(types);
+ }
+
+ gst_object_unref(GST_OBJECT(factory));
+
+ m_elementNames.insert(formatName, elementName);
+ break;
+ }
+ }
+ }
+}
+
+QSet<QString> CameraBinContainer::supportedStreamTypes(GstElementFactory *factory, GstPadDirection direction)
+{
+ QSet<QString> types;
+ const GList *pads = gst_element_factory_get_static_pad_templates(factory);
+ for (const GList *pad = pads; pad; pad = g_list_next(pad)) {
+ GstStaticPadTemplate *templ = (GstStaticPadTemplate*)pad->data;
+ if (templ->direction == direction) {
+ GstCaps *caps = gst_static_caps_get(&templ->static_caps);
+ for (uint i=0; i<gst_caps_get_size(caps); i++) {
+ GstStructure *structure = gst_caps_get_structure(caps, i);
+ types.insert( QString::fromUtf8(gst_structure_get_name(structure)) );
+ }
+ gst_caps_unref(caps);
+ }
+ }
+
+ return types;
+}
+
+
+QSet<QString> CameraBinContainer::supportedStreamTypes(const QString &container) const
+{
+ return m_streamTypes.value(container);
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabincontainer.h b/src/plugins/gstreamer/camerabin/camerabincontainer.h
new file mode 100644
index 000000000..3eac48342
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabincontainer.h
@@ -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$
+** 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 CAMERABINMEDIACONTAINERCONTROL_H
+#define CAMERABINMEDIACONTAINERCONTROL_H
+
+#include <qmediacontainercontrol.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qset.h>
+
+#include <gst/gst.h>
+
+QT_USE_NAMESPACE
+
+class CameraBinContainer : public QMediaContainerControl
+{
+Q_OBJECT
+public:
+ CameraBinContainer(QObject *parent);
+ virtual ~CameraBinContainer() {}
+
+ virtual QStringList supportedContainers() const { return m_supportedContainers; }
+ virtual QString containerMimeType() const { return m_format; }
+ virtual void setContainerMimeType(const QString &formatMimeType)
+ {
+ m_format = formatMimeType;
+
+ if (m_userFormat != formatMimeType) {
+ m_userFormat = formatMimeType;
+ emit settingsChanged();
+ }
+ }
+
+ void setActualContainer(const QString &formatMimeType)
+ {
+ m_format = formatMimeType;
+ }
+
+ void resetActualContainer()
+ {
+ m_format = m_userFormat;
+ }
+
+ virtual QString containerDescription(const QString &formatMimeType) const { return m_containerDescriptions.value(formatMimeType); }
+
+ QByteArray formatElementName() const { return m_elementNames.value(containerMimeType()); }
+
+ QSet<QString> supportedStreamTypes(const QString &container) const;
+
+ static QSet<QString> supportedStreamTypes(GstElementFactory *factory, GstPadDirection direction);
+
+Q_SIGNALS:
+ void settingsChanged();
+
+private:
+ QString m_format; // backend selected format, using m_userFormat
+ QString m_userFormat;
+ QStringList m_supportedContainers;
+ QMap<QString,QByteArray> m_elementNames;
+ QMap<QString, QString> m_containerDescriptions;
+ QMap<QString, QSet<QString> > m_streamTypes;
+};
+
+#endif // CAMERABINMEDIACONTAINERCONTROL_H
diff --git a/src/plugins/gstreamer/camerabin/camerabincontrol.cpp b/src/plugins/gstreamer/camerabin/camerabincontrol.cpp
new file mode 100644
index 000000000..2c30fd656
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabincontrol.cpp
@@ -0,0 +1,356 @@
+/****************************************************************************
+**
+** 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 "camerabincontrol.h"
+#include "camerabincontainer.h"
+#include "camerabinaudioencoder.h"
+#include "camerabinvideoencoder.h"
+#include "camerabinimageencoder.h"
+#include "camerabinresourcepolicy.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qmetaobject.h>
+
+#include <linux/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <linux/videodev2.h>
+
+//#define CAMEABIN_DEBUG 1
+#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
+
+CameraBinControl::CameraBinControl(CameraBinSession *session)
+ :QCameraControl(session),
+ m_session(session),
+ m_state(QCamera::UnloadedState),
+ m_status(QCamera::UnloadedStatus),
+ m_reloadPending(false)
+{
+ connect(m_session, SIGNAL(stateChanged(QCamera::State)),
+ this, SLOT(updateStatus()));
+
+ connect(m_session->audioEncodeControl(), SIGNAL(settingsChanged()),
+ SLOT(reloadLater()));
+ connect(m_session->videoEncodeControl(), SIGNAL(settingsChanged()),
+ SLOT(reloadLater()));
+ connect(m_session->mediaContainerControl(), SIGNAL(settingsChanged()),
+ SLOT(reloadLater()));
+ connect(m_session->imageEncodeControl(), SIGNAL(settingsChanged()),
+ SLOT(reloadLater()));
+ connect(m_session, SIGNAL(viewfinderChanged()),
+ SLOT(reloadLater()));
+ connect(m_session, SIGNAL(readyChanged(bool)),
+ SLOT(reloadLater()));
+ connect(m_session, SIGNAL(error(int,QString)),
+ SLOT(handleCameraError(int,QString)));
+
+ m_resourcePolicy = new CamerabinResourcePolicy(this);
+ connect(m_resourcePolicy, SIGNAL(resourcesGranted()),
+ SLOT(handleResourcesGranted()));
+ connect(m_resourcePolicy, SIGNAL(resourcesDenied()),
+ SLOT(handleResourcesLost()));
+ connect(m_resourcePolicy, SIGNAL(resourcesLost()),
+ SLOT(handleResourcesLost()));
+
+ connect(m_session, SIGNAL(busyChanged(bool)),
+ SLOT(handleBusyChanged(bool)));
+}
+
+CameraBinControl::~CameraBinControl()
+{
+}
+
+QCamera::CaptureMode CameraBinControl::captureMode() const
+{
+ return m_session->captureMode();
+}
+
+void CameraBinControl::setCaptureMode(QCamera::CaptureMode mode)
+{
+ if (m_session->captureMode() != mode) {
+ m_session->setCaptureMode(mode);
+ reloadLater();
+
+ if (m_state == QCamera::ActiveState) {
+ m_resourcePolicy->setResourceSet(
+ captureMode() == QCamera::CaptureStillImage ?
+ CamerabinResourcePolicy::ImageCaptureResources :
+ CamerabinResourcePolicy::VideoCaptureResources);
+ }
+ emit captureModeChanged(mode);
+ }
+}
+
+bool CameraBinControl::isCaptureModeSupported(QCamera::CaptureMode mode) const
+{
+#ifdef Q_WS_MAEMO_5
+ //Front camera on N900 supports only video capture
+ if (m_session->cameraRole() == CameraBinSession::FrontCamera)
+ return mode == QCamera::CaptureVideo;
+#endif
+
+ return mode == QCamera::CaptureStillImage || mode == QCamera::CaptureVideo;
+}
+
+void CameraBinControl::setState(QCamera::State state)
+{
+#ifdef CAMEABIN_DEBUG
+ qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", state);
+#endif
+ if (m_state != state) {
+ m_state = state;
+
+ //special case for stopping the camera while it's busy,
+ //it should be delayed until the camera is idle
+ if (state == QCamera::LoadedState &&
+ m_session->state() == QCamera::ActiveState &&
+ m_session->isBusy()) {
+#ifdef CAMEABIN_DEBUG
+ qDebug() << Q_FUNC_INFO << "Camera is busy, QCamera::stop() is delayed";
+#endif
+ emit stateChanged(m_state);
+ return;
+ }
+
+ CamerabinResourcePolicy::ResourceSet resourceSet;
+ switch (state) {
+ case QCamera::UnloadedState:
+ resourceSet = CamerabinResourcePolicy::NoResources;
+ break;
+ case QCamera::LoadedState:
+ resourceSet = CamerabinResourcePolicy::LoadedResources;
+ break;
+ case QCamera::ActiveState:
+ resourceSet = captureMode() == QCamera::CaptureStillImage ?
+ CamerabinResourcePolicy::ImageCaptureResources :
+ CamerabinResourcePolicy::VideoCaptureResources;
+ break;
+ }
+
+ m_resourcePolicy->setResourceSet(resourceSet);
+
+ if (m_resourcePolicy->isResourcesGranted()) {
+ //postpone changing to Active if the session is nor ready yet
+ if (state == QCamera::ActiveState) {
+ if (m_session->isReady()) {
+ m_session->setState(state);
+ } else {
+#ifdef CAMEABIN_DEBUG
+ qDebug() << "Camera session is not ready yet, postpone activating";
+#endif
+ }
+ } else
+ m_session->setState(state);
+ }
+
+ emit stateChanged(m_state);
+ }
+}
+
+QCamera::State CameraBinControl::state() const
+{
+ return m_state;
+}
+
+void CameraBinControl::updateStatus()
+{
+ QCamera::State sessionState = m_session->state();
+ QCamera::Status oldStatus = m_status;
+
+ switch (m_state) {
+ case QCamera::UnloadedState:
+ m_status = QCamera::UnloadedStatus;
+ break;
+ case QCamera::LoadedState:
+ switch (sessionState) {
+ case QCamera::UnloadedState:
+ m_status = QCamera::LoadingStatus;
+ break;
+ case QCamera::LoadedState:
+ m_status = QCamera::LoadedStatus;
+ break;
+ case QCamera::ActiveState:
+ m_status = QCamera::ActiveStatus;
+ break;
+ }
+ break;
+ case QCamera::ActiveState:
+ switch (sessionState) {
+ case QCamera::UnloadedState:
+ m_status = QCamera::LoadingStatus;
+ break;
+ case QCamera::LoadedState:
+ m_status = QCamera::StartingStatus;
+ break;
+ case QCamera::ActiveState:
+ m_status = QCamera::ActiveStatus;
+ break;
+ }
+ }
+
+ if (m_status != oldStatus) {
+#ifdef CAMEABIN_DEBUG
+ qDebug() << "Camera status changed" << ENUM_NAME(QCamera, "Status", m_status);
+#endif
+ emit statusChanged(m_status);
+ }
+}
+
+void CameraBinControl::reloadLater()
+{
+#ifdef CAMEABIN_DEBUG
+ qDebug() << "CameraBinControl: reload pipeline requested" << ENUM_NAME(QCamera, "State", m_state);
+#endif
+ if (!m_reloadPending && m_state == QCamera::ActiveState) {
+ m_reloadPending = true;
+
+ if (!m_session->isBusy()) {
+ m_session->setState(QCamera::LoadedState);
+ QMetaObject::invokeMethod(this, "delayedReload", Qt::QueuedConnection);
+ }
+ }
+}
+
+void CameraBinControl::handleResourcesLost()
+{
+#ifdef CAMEABIN_DEBUG
+ qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", m_state);
+#endif
+ m_session->setState(QCamera::UnloadedState);
+}
+
+void CameraBinControl::handleResourcesGranted()
+{
+#ifdef CAMEABIN_DEBUG
+ qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", m_state);
+#endif
+
+ //camera will be started soon by delayedReload()
+ if (m_reloadPending && m_state == QCamera::ActiveState)
+ return;
+
+ if (m_state == QCamera::ActiveState && m_session->isReady())
+ m_session->setState(QCamera::ActiveState);
+ else if (m_state == QCamera::LoadedState)
+ m_session->setState(QCamera::LoadedState);
+}
+
+void CameraBinControl::handleBusyChanged(bool busy)
+{
+ if (!busy && m_session->state() == QCamera::ActiveState) {
+ if (m_state == QCamera::LoadedState) {
+ //handle delayed stop() because of busy camera
+ m_resourcePolicy->setResourceSet(CamerabinResourcePolicy::LoadedResources);
+ m_session->setState(QCamera::LoadedState);
+ } else if (m_state == QCamera::ActiveState && m_reloadPending) {
+ //handle delayed reload because of busy camera
+ m_session->setState(QCamera::LoadedState);
+ QMetaObject::invokeMethod(this, "delayedReload", Qt::QueuedConnection);
+ }
+ }
+}
+
+void CameraBinControl::handleCameraError(int errorCode, const QString &errorString)
+{
+ emit error(errorCode, errorString);
+ setState(QCamera::UnloadedState);
+}
+
+void CameraBinControl::delayedReload()
+{
+#ifdef CAMEABIN_DEBUG
+ qDebug() << "CameraBinControl: reload pipeline";
+#endif
+ if (m_reloadPending) {
+ m_reloadPending = false;
+ if (m_state == QCamera::ActiveState &&
+ m_session->isReady() &&
+ m_resourcePolicy->isResourcesGranted()) {
+ m_session->setState(QCamera::ActiveState);
+ }
+ }
+}
+
+bool CameraBinControl::canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const
+{
+ Q_UNUSED(status);
+
+ switch (changeType) {
+ case QCameraControl::CaptureMode:
+ case QCameraControl::ImageEncodingSettings:
+ case QCameraControl::VideoEncodingSettings:
+ case QCameraControl::Viewfinder:
+ return true;
+ default:
+ return false;
+ }
+}
+
+#define VIEWFINDER_COLORSPACE_CONVERSION 0x00000004
+
+bool CameraBinControl::viewfinderColorSpaceConversion() const
+{
+ gint flags = 0;
+ g_object_get(G_OBJECT(m_session->cameraBin()), "flags", &flags, NULL);
+
+ return flags & VIEWFINDER_COLORSPACE_CONVERSION;
+}
+
+void CameraBinControl::setViewfinderColorSpaceConversion(bool enabled)
+{
+ gint flags = 0;
+ g_object_get(G_OBJECT(m_session->cameraBin()), "flags", &flags, NULL);
+
+ if (enabled)
+ flags |= VIEWFINDER_COLORSPACE_CONVERSION;
+ else
+ flags &= ~VIEWFINDER_COLORSPACE_CONVERSION;
+
+ g_object_set(G_OBJECT(m_session->cameraBin()), "flags", flags, NULL);
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabincontrol.h b/src/plugins/gstreamer/camerabin/camerabincontrol.h
new file mode 100644
index 000000000..1e5f28e01
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabincontrol.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 CAMERABINCONTROL_H
+#define CAMERABINCONTROL_H
+
+#include <QHash>
+#include <qcameracontrol.h>
+#include "camerabinsession.h"
+
+QT_USE_NAMESPACE
+
+class CamerabinResourcePolicy;
+
+class CameraBinControl : public QCameraControl
+{
+ Q_OBJECT
+ Q_PROPERTY(bool viewfinderColorSpaceConversion READ viewfinderColorSpaceConversion WRITE setViewfinderColorSpaceConversion)
+public:
+ CameraBinControl( CameraBinSession *session );
+ virtual ~CameraBinControl();
+
+ bool isValid() const { return true; }
+
+ QCamera::State state() const;
+ void setState(QCamera::State state);
+
+ QCamera::Status status() const { return m_status; }
+
+ QCamera::CaptureMode captureMode() const;
+ void setCaptureMode(QCamera::CaptureMode mode);
+
+ bool isCaptureModeSupported(QCamera::CaptureMode mode) const;
+ bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const;
+ bool viewfinderColorSpaceConversion() const;
+
+public slots:
+ void reloadLater();
+ void setViewfinderColorSpaceConversion(bool enabled);
+
+private slots:
+ void updateStatus();
+ void delayedReload();
+
+ void handleResourcesGranted();
+ void handleResourcesLost();
+
+ void handleBusyChanged(bool);
+ void handleCameraError(int error, const QString &errorString);
+
+private:
+ void updateSupportedResolutions(const QString &device);
+
+ CameraBinSession *m_session;
+ QCamera::State m_state;
+ QCamera::Status m_status;
+ CamerabinResourcePolicy *m_resourcePolicy;
+
+ bool m_reloadPending;
+};
+
+#endif // CAMERABINCONTROL_H
diff --git a/src/plugins/gstreamer/camerabin/camerabinexposure.cpp b/src/plugins/gstreamer/camerabin/camerabinexposure.cpp
new file mode 100644
index 000000000..3401d07fc
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinexposure.cpp
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** 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 "camerabinexposure.h"
+#include "camerabinsession.h"
+#include <gst/interfaces/photography.h>
+
+#include <QDebug>
+
+CameraBinExposure::CameraBinExposure(CameraBinSession *session)
+ :QCameraExposureControl(session),
+ m_session(session)
+{
+}
+
+CameraBinExposure::~CameraBinExposure()
+{
+}
+
+QCameraExposure::ExposureMode CameraBinExposure::exposureMode() const
+{
+ GstSceneMode sceneMode;
+ gst_photography_get_scene_mode(m_session->photography(), &sceneMode);
+
+ switch (sceneMode) {
+ case GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT: return QCameraExposure::ExposurePortrait;
+ case GST_PHOTOGRAPHY_SCENE_MODE_SPORT: return QCameraExposure::ExposureSports;
+ case GST_PHOTOGRAPHY_SCENE_MODE_NIGHT: return QCameraExposure::ExposureNight;
+ case GST_PHOTOGRAPHY_SCENE_MODE_MANUAL: return QCameraExposure::ExposureManual;
+ case GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP: //no direct mapping available so mapping to auto mode
+ case GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE: //no direct mapping available so mapping to auto mode
+ case GST_PHOTOGRAPHY_SCENE_MODE_AUTO:
+ default:
+ return QCameraExposure::ExposureAuto;
+ }
+}
+
+void CameraBinExposure::setExposureMode(QCameraExposure::ExposureMode mode)
+{
+ GstSceneMode sceneMode;
+ gst_photography_get_scene_mode(m_session->photography(), &sceneMode);
+
+ switch (mode) {
+ case QCameraExposure::ExposureManual: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_MANUAL; break;
+ case QCameraExposure::ExposurePortrait: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT; break;
+ case QCameraExposure::ExposureSports: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_SPORT; break;
+ case QCameraExposure::ExposureNight: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_NIGHT; break;
+ case QCameraExposure::ExposureAuto: sceneMode = GST_PHOTOGRAPHY_SCENE_MODE_AUTO; break;
+ default:
+ break;
+ }
+
+ gst_photography_set_scene_mode(m_session->photography(), sceneMode);
+}
+
+bool CameraBinExposure::isExposureModeSupported(QCameraExposure::ExposureMode mode) const
+{
+ //Similar mode names can be found in gst as GstSceneMode
+ return mode == QCameraExposure::ExposureAuto ||
+ mode == QCameraExposure::ExposurePortrait ||
+ mode == QCameraExposure::ExposureSports ||
+ mode == QCameraExposure::ExposureNight;
+
+ //No direct mapping available for GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP and
+ //GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE
+}
+
+QCameraExposure::MeteringMode CameraBinExposure::meteringMode() const
+{
+ return QCameraExposure::MeteringMatrix;
+}
+
+void CameraBinExposure::setMeteringMode(QCameraExposure::MeteringMode mode)
+{
+ Q_UNUSED(mode);
+}
+
+bool CameraBinExposure::isMeteringModeSupported(QCameraExposure::MeteringMode mode) const
+{
+ return mode == QCameraExposure::MeteringMatrix;
+}
+
+bool CameraBinExposure::isParameterSupported(ExposureParameter parameter) const
+{
+ switch (parameter) {
+ case QCameraExposureControl::ExposureCompensation:
+ case QCameraExposureControl::ISO:
+ case QCameraExposureControl::Aperture:
+ case QCameraExposureControl::ShutterSpeed:
+ return true;
+ default:
+ return false;
+ }
+}
+
+QVariant CameraBinExposure::exposureParameter(ExposureParameter parameter) const
+{
+ switch (parameter) {
+ case QCameraExposureControl::ExposureCompensation:
+ {
+ gfloat ev;
+ gst_photography_get_ev_compensation(m_session->photography(), &ev);
+ return QVariant(ev);
+ }
+ case QCameraExposureControl::ISO:
+ {
+ guint isoSpeed = 0;
+ gst_photography_get_iso_speed(m_session->photography(), &isoSpeed);
+ return QVariant(isoSpeed);
+ }
+ case QCameraExposureControl::Aperture:
+ return QVariant(2.8);
+ case QCameraExposureControl::ShutterSpeed:
+ {
+ guint32 shutterSpeed = 0;
+ gst_photography_get_exposure(m_session->photography(), &shutterSpeed);
+
+ return QVariant(shutterSpeed/1000000.0);
+ }
+ default:
+ return QVariant();
+ }
+}
+
+QCameraExposureControl::ParameterFlags CameraBinExposure::exposureParameterFlags(ExposureParameter parameter) const
+{
+ QCameraExposureControl::ParameterFlags flags = 0;
+
+ switch (parameter) {
+ case QCameraExposureControl::ExposureCompensation:
+ flags |= ContinuousRange;
+ break;
+ case QCameraExposureControl::Aperture:
+ flags |= ReadOnly;
+ break;
+ default:
+ break;
+ }
+
+ return flags;
+}
+
+QVariantList CameraBinExposure::supportedParameterRange(ExposureParameter parameter) const
+{
+ QVariantList res;
+ switch (parameter) {
+ case QCameraExposureControl::ExposureCompensation:
+ res << -2.0 << 2.0;
+ break;
+ case QCameraExposureControl::ISO:
+ res << 100 << 200 << 400;
+ break;
+ case QCameraExposureControl::Aperture:
+ res << 2.8;
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+bool CameraBinExposure::setExposureParameter(ExposureParameter parameter, const QVariant& value)
+{
+ QVariant oldValue = exposureParameter(parameter);
+
+ switch (parameter) {
+ case QCameraExposureControl::ExposureCompensation:
+ gst_photography_set_ev_compensation(m_session->photography(), value.toReal());
+ break;
+ case QCameraExposureControl::ISO:
+ gst_photography_set_iso_speed(m_session->photography(), value.toInt());
+ break;
+ case QCameraExposureControl::Aperture:
+ gst_photography_set_aperture(m_session->photography(), guint(value.toReal()*1000000));
+ break;
+ case QCameraExposureControl::ShutterSpeed:
+ gst_photography_set_exposure(m_session->photography(), guint(value.toReal()*1000000));
+ break;
+ default:
+ return false;
+ }
+
+ QVariant newValue = exposureParameter(parameter);
+ if (!qFuzzyCompare(oldValue.toReal(), newValue.toReal()))
+ emit exposureParameterChanged(parameter);
+
+ return true;
+}
+
+QString CameraBinExposure::extendedParameterName(ExposureParameter)
+{
+ return QString();
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabinexposure.h b/src/plugins/gstreamer/camerabin/camerabinexposure.h
new file mode 100644
index 000000000..44439253d
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinexposure.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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 CAMERABINEXPOSURECONTROL_MAEMO_H
+#define CAMERABINEXPOSURECONTROL_MAEMO_H
+
+#include <qcamera.h>
+#include <qcameraexposurecontrol.h>
+
+#include <gst/gst.h>
+#include <glib.h>
+
+class CameraBinSession;
+
+QT_USE_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT CameraBinExposure : public QCameraExposureControl
+{
+ Q_OBJECT
+
+public:
+ CameraBinExposure(CameraBinSession *session);
+ virtual ~CameraBinExposure();
+
+ QCameraExposure::ExposureMode exposureMode() const;
+ void setExposureMode(QCameraExposure::ExposureMode mode);
+ bool isExposureModeSupported(QCameraExposure::ExposureMode mode) const;
+
+ QCameraExposure::MeteringMode meteringMode() const;
+ void setMeteringMode(QCameraExposure::MeteringMode mode);
+ bool isMeteringModeSupported(QCameraExposure::MeteringMode mode) const;
+
+ bool isParameterSupported(ExposureParameter parameter) const;
+ QVariant exposureParameter(ExposureParameter parameter) const;
+ ParameterFlags exposureParameterFlags(ExposureParameter parameter) const;
+ QVariantList supportedParameterRange(ExposureParameter parameter) const;
+ bool setExposureParameter(ExposureParameter parameter, const QVariant& value);
+
+ QString extendedParameterName(ExposureParameter parameter);
+
+private:
+ CameraBinSession *m_session;
+};
+
+#endif // CAMERABINEXPOSURECONTROL_MAEMO_H
diff --git a/src/plugins/gstreamer/camerabin/camerabinflash.cpp b/src/plugins/gstreamer/camerabin/camerabinflash.cpp
new file mode 100644
index 000000000..f5b76524d
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinflash.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** 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 "camerabinflash.h"
+#include "camerabinsession.h"
+#include <gst/interfaces/photography.h>
+
+#include <QDebug>
+
+CameraBinFlash::CameraBinFlash(CameraBinSession *session)
+ :QCameraFlashControl(session),
+ m_session(session)
+{
+}
+
+CameraBinFlash::~CameraBinFlash()
+{
+}
+
+QCameraExposure::FlashModes CameraBinFlash::flashMode() const
+{
+ GstFlashMode flashMode;
+ gst_photography_get_flash_mode(m_session->photography(), &flashMode);
+
+ QCameraExposure::FlashModes modes;
+ switch (flashMode) {
+ case GST_PHOTOGRAPHY_FLASH_MODE_AUTO: modes |= QCameraExposure::FlashAuto; break;
+ case GST_PHOTOGRAPHY_FLASH_MODE_OFF: modes |= QCameraExposure::FlashOff; break;
+ case GST_PHOTOGRAPHY_FLASH_MODE_ON: modes |= QCameraExposure::FlashOn; break;
+ case GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN: modes |= QCameraExposure::FlashFill; break;
+ case GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE: modes |= QCameraExposure::FlashRedEyeReduction; break;
+ default:
+ modes |= QCameraExposure::FlashAuto;
+ break;
+ }
+ return modes;
+}
+
+void CameraBinFlash::setFlashMode(QCameraExposure::FlashModes mode)
+{
+ GstFlashMode flashMode;
+ gst_photography_get_flash_mode(m_session->photography(), &flashMode);
+
+ if (mode.testFlag(QCameraExposure::FlashAuto)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_AUTO;
+ else if (mode.testFlag(QCameraExposure::FlashOff)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_OFF;
+ else if (mode.testFlag(QCameraExposure::FlashOn)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_ON;
+ else if (mode.testFlag(QCameraExposure::FlashFill)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN;
+ else if (mode.testFlag(QCameraExposure::FlashRedEyeReduction)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE;
+
+ gst_photography_set_flash_mode(m_session->photography(), flashMode);
+}
+
+bool CameraBinFlash::isFlashModeSupported(QCameraExposure::FlashModes mode) const
+{
+ return mode == QCameraExposure::FlashOff ||
+ mode == QCameraExposure::FlashOn ||
+ mode == QCameraExposure::FlashAuto ||
+ mode == QCameraExposure::FlashRedEyeReduction ||
+ mode == QCameraExposure::FlashFill;
+}
+
+bool CameraBinFlash::isFlashReady() const
+{
+ return true;
+}
+
diff --git a/src/plugins/gstreamer/camerabin/camerabinflash.h b/src/plugins/gstreamer/camerabin/camerabinflash.h
new file mode 100644
index 000000000..7c566becf
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinflash.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** 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 CAMERABINFLASHCONTROL_H
+#define CAMERABINFLASHCONTROL_H
+
+#include <qcamera.h>
+#include <qcameraflashcontrol.h>
+
+#include <gst/gst.h>
+#include <glib.h>
+
+class CameraBinSession;
+
+QT_USE_NAMESPACE
+
+class Q_MULTIMEDIA_EXPORT CameraBinFlash : public QCameraFlashControl
+{
+ Q_OBJECT
+public:
+ CameraBinFlash(CameraBinSession *session);
+ virtual ~CameraBinFlash();
+
+ QCameraExposure::FlashModes flashMode() const;
+ void setFlashMode(QCameraExposure::FlashModes mode);
+ bool isFlashModeSupported(QCameraExposure::FlashModes mode) const;
+
+ bool isFlashReady() const;
+
+private:
+ CameraBinSession *m_session;
+};
+
+#endif // CAMERABINFLASHCONTROL_H
+
diff --git a/src/plugins/gstreamer/camerabin/camerabinfocus.cpp b/src/plugins/gstreamer/camerabin/camerabinfocus.cpp
new file mode 100644
index 000000000..cf7c9ecd8
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinfocus.cpp
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** 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 "camerabinfocus.h"
+#include "camerabinsession.h"
+
+#include <gst/interfaces/photography.h>
+
+#include <QDebug>
+#include <QtCore/qmetaobject.h>
+
+//#define CAMERABIN_DEBUG 1
+#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
+
+CameraBinFocus::CameraBinFocus(CameraBinSession *session)
+ :QCameraFocusControl(session),
+ m_session(session),
+ m_focusMode(QCameraFocus::AutoFocus),
+ m_focusStatus(QCamera::Unlocked),
+ m_focusZoneStatus(QCameraFocusZone::Selected)
+{
+ connect(m_session, SIGNAL(stateChanged(QCamera::State)),
+ this, SLOT(_q_handleCameraStateChange(QCamera::State)));
+ connect(m_session, SIGNAL(imageCaptured(int,QImage)),
+ this, SLOT(_q_handleCapturedImage()));
+}
+
+CameraBinFocus::~CameraBinFocus()
+{
+}
+
+QCameraFocus::FocusMode CameraBinFocus::focusMode() const
+{
+ return m_focusMode;
+}
+
+void CameraBinFocus::setFocusMode(QCameraFocus::FocusMode mode)
+{
+ if (isFocusModeSupported(mode)) {
+ m_focusMode = mode;
+ }
+}
+
+bool CameraBinFocus::isFocusModeSupported(QCameraFocus::FocusMode mode) const
+{
+ return mode & QCameraFocus::AutoFocus;
+}
+
+qreal CameraBinFocus::maximumOpticalZoom() const
+{
+ return 1.0;
+}
+
+qreal CameraBinFocus::maximumDigitalZoom() const
+{
+ return 10;
+}
+
+qreal CameraBinFocus::opticalZoom() const
+{
+ return 1.0;
+}
+
+qreal CameraBinFocus::digitalZoom() const
+{
+#ifdef Q_WS_MAEMO_5
+ gint zoomFactor = 0;
+ g_object_get(GST_BIN(m_session->cameraBin()), "zoom", &zoomFactor, NULL);
+ return zoomFactor/100.0;
+#else
+ gfloat zoomFactor = 1.0;
+ g_object_get(GST_BIN(m_session->cameraBin()), "zoom", &zoomFactor, NULL);
+ return zoomFactor;
+#endif
+}
+
+void CameraBinFocus::zoomTo(qreal optical, qreal digital)
+{
+ Q_UNUSED(optical);
+ digital = qBound(qreal(1.0), digital, qreal(10.0));
+#ifdef Q_WS_MAEMO_5
+ g_object_set(GST_BIN(m_session->cameraBin()), "zoom", qRound(digital*100.0), NULL);
+#else
+ g_object_set(GST_BIN(m_session->cameraBin()), "zoom", digital, NULL);
+#endif
+ emit digitalZoomChanged(digital);
+}
+
+QCameraFocus::FocusPointMode CameraBinFocus::focusPointMode() const
+{
+ return QCameraFocus::FocusPointAuto;
+}
+
+void CameraBinFocus::setFocusPointMode(QCameraFocus::FocusPointMode mode)
+{
+ Q_UNUSED(mode);
+}
+
+bool CameraBinFocus::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
+{
+ return mode == QCameraFocus::FocusPointAuto;
+}
+
+QPointF CameraBinFocus::customFocusPoint() const
+{
+ return QPointF(0.5, 0.5);
+}
+
+void CameraBinFocus::setCustomFocusPoint(const QPointF &point)
+{
+ Q_UNUSED(point);
+}
+
+QCameraFocusZoneList CameraBinFocus::focusZones() const
+{
+ return QCameraFocusZoneList() << QCameraFocusZone(QRectF(0.35, 0.35, 0.3, 0.3), m_focusZoneStatus);
+}
+
+
+void CameraBinFocus::handleFocusMessage(GstMessage *gm)
+{
+ //it's a sync message, so it's called from non main thread
+ if (gst_structure_has_name(gm->structure, GST_PHOTOGRAPHY_AUTOFOCUS_DONE)) {
+ gint status = GST_PHOTOGRAPHY_FOCUS_STATUS_NONE;
+ gst_structure_get_int (gm->structure, "status", &status);
+ QCamera::LockStatus focusStatus = m_focusStatus;
+ QCamera::LockChangeReason reason = QCamera::UserRequest;
+
+ switch (status) {
+ case GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL:
+ focusStatus = QCamera::Unlocked;
+ reason = QCamera::LockFailed;
+ break;
+ case GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS:
+ focusStatus = QCamera::Locked;
+ break;
+ case GST_PHOTOGRAPHY_FOCUS_STATUS_NONE:
+ break;
+ case GST_PHOTOGRAPHY_FOCUS_STATUS_RUNNING:
+ focusStatus = QCamera::Searching;
+ break;
+ default:
+ break;
+ }
+
+ static int signalIndex = metaObject()->indexOfSlot(
+ "_q_setFocusStatus(QCamera::LockStatus,QCamera::LockChangeReason)");
+ metaObject()->method(signalIndex).invoke(this,
+ Qt::QueuedConnection,
+ Q_ARG(QCamera::LockStatus,focusStatus),
+ Q_ARG(QCamera::LockChangeReason,reason));
+ }
+}
+
+void CameraBinFocus::_q_setFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason)
+{
+#ifdef CAMERABIN_DEBUG
+ qDebug() << Q_FUNC_INFO << "Current:"
+ << ENUM_NAME(QCamera, "LockStatus", m_focusStatus)
+ << "New:"
+ << ENUM_NAME(QCamera, "LockStatus", status) << ENUM_NAME(QCamera, "LockChangeReason", reason);
+#endif
+
+ if (m_focusStatus != status) {
+ m_focusStatus = status;
+
+ QCameraFocusZone::FocusZoneStatus zonesStatus =
+ m_focusStatus == QCamera::Locked ?
+ QCameraFocusZone::Focused : QCameraFocusZone::Selected;
+
+ if (m_focusZoneStatus != zonesStatus) {
+ m_focusZoneStatus = zonesStatus;
+ emit focusZonesChanged();
+ }
+
+ emit _q_focusStatusChanged(m_focusStatus, reason);
+ }
+}
+
+void CameraBinFocus::_q_handleCameraStateChange(QCamera::State state)
+{
+ if (state != QCamera::ActiveState)
+ _q_setFocusStatus(QCamera::Unlocked, QCamera::LockLost);
+}
+
+void CameraBinFocus::_q_handleCapturedImage()
+{
+#ifdef Q_WS_MAEMO_5
+ //N900 lost focus after image capture
+ if (m_focusStatus != QCamera::Unlocked) {
+ m_focusStatus = QCamera::Unlocked;
+ emit _q_focusStatusChanged(QCamera::Unlocked, QCamera::LockLost);
+ }
+#endif
+}
+
+void CameraBinFocus::_q_startFocusing()
+{
+ _q_setFocusStatus(QCamera::Searching, QCamera::UserRequest);
+ gst_photography_set_autofocus(m_session->photography(), TRUE);
+}
+
+void CameraBinFocus::_q_stopFocusing()
+{
+ gst_photography_set_autofocus(m_session->photography(), FALSE);
+ _q_setFocusStatus(QCamera::Unlocked, QCamera::UserRequest);
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabinfocus.h b/src/plugins/gstreamer/camerabin/camerabinfocus.h
new file mode 100644
index 000000000..e496d2e3b
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinfocus.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** 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 CAMERABINFOCUSCONTROL_H
+#define CAMERABINFOCUSCONTROL_H
+
+#include <qcamera.h>
+#include <qcamerafocuscontrol.h>
+
+#include <gst/gst.h>
+#include <glib.h>
+
+class CameraBinSession;
+
+QT_USE_NAMESPACE
+
+class CameraBinFocus : public QCameraFocusControl
+{
+ Q_OBJECT
+
+public:
+ CameraBinFocus(CameraBinSession *session);
+ virtual ~CameraBinFocus();
+
+ QCameraFocus::FocusMode focusMode() const;
+ void setFocusMode(QCameraFocus::FocusMode mode);
+ bool isFocusModeSupported(QCameraFocus::FocusMode mode) const;
+
+ qreal maximumOpticalZoom() const;
+ qreal maximumDigitalZoom() const;
+ qreal opticalZoom() const;
+ qreal digitalZoom() const;
+
+ void zoomTo(qreal optical, qreal digital) ;
+
+ QCameraFocus::FocusPointMode focusPointMode() const;
+ void setFocusPointMode(QCameraFocus::FocusPointMode mode) ;
+ bool isFocusPointModeSupported(QCameraFocus::FocusPointMode) const;
+ QPointF customFocusPoint() const;
+ void setCustomFocusPoint(const QPointF &point);
+
+ QCameraFocusZoneList focusZones() const;
+
+ void handleFocusMessage(GstMessage*);
+ QCamera::LockStatus focusStatus() const { return m_focusStatus; }
+
+Q_SIGNALS:
+ void _q_focusStatusChanged(QCamera::LockStatus status, QCamera::LockChangeReason reason);
+
+public Q_SLOTS:
+ void _q_startFocusing();
+ void _q_stopFocusing();
+
+private Q_SLOTS:
+ void _q_setFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason);
+ void _q_handleCameraStateChange(QCamera::State state);
+ void _q_handleCapturedImage();
+
+private:
+ CameraBinSession *m_session;
+ QCameraFocus::FocusMode m_focusMode;
+ QCamera::LockStatus m_focusStatus;
+ QCameraFocusZone::FocusZoneStatus m_focusZoneStatus;
+};
+
+#endif // CAMERABINFOCUSCONTROL_H
diff --git a/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp b/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp
new file mode 100644
index 000000000..3df1105bc
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp
@@ -0,0 +1,347 @@
+/****************************************************************************
+**
+** 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 "camerabinimagecapture.h"
+#include "camerabincapturedestination.h"
+#include "camerabincapturebufferformat.h"
+#include "camerabinsession.h"
+#include "qgstvideobuffer.h"
+#include "qvideosurfacegstsink.h"
+#include "qgstutils.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qbuffer.h>
+#include <QtGui/qimagereader.h>
+
+//#define DEBUG_CAPTURE
+
+#ifdef Q_WS_MAEMO_5
+#define IMAGE_DONE_SIGNAL "img-done"
+#else
+#define IMAGE_DONE_SIGNAL "image-done"
+#endif
+
+
+Q_DECLARE_METATYPE(QVideoFrame)
+Q_DECLARE_METATYPE(QtMultimediaKit::MetaData)
+
+namespace
+{
+class CameraRegisterMetaTypes
+{
+public:
+ CameraRegisterMetaTypes()
+ {
+ qRegisterMetaType<QVideoFrame>("QVideoFrame");
+ qRegisterMetaType<QtMultimediaKit::MetaData>("QtMultimediaKit::MetaData");
+ }
+} _registerCameraMetaTypes;
+}
+
+
+CameraBinImageCapture::CameraBinImageCapture(CameraBinSession *session)
+ :QCameraImageCaptureControl(session)
+ , m_session(session)
+ , m_ready(false)
+ , m_requestId(0)
+ , m_jpegEncoderElement(0)
+ , m_metadataMuxerElement(0)
+{
+ connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
+ connect(m_session, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int)));
+ connect(m_session, SIGNAL(imageCaptured(int,QImage)), this, SIGNAL(imageCaptured(int,QImage)));
+ connect(m_session, SIGNAL(busMessage(QGstreamerMessage)), SLOT(handleBusMessage(QGstreamerMessage)));
+
+ g_signal_connect(G_OBJECT(m_session->cameraBin()), IMAGE_DONE_SIGNAL, G_CALLBACK(handleImageSaved), this);
+}
+
+CameraBinImageCapture::~CameraBinImageCapture()
+{
+}
+
+bool CameraBinImageCapture::isReadyForCapture() const
+{
+ return m_ready;
+}
+
+int CameraBinImageCapture::capture(const QString &fileName)
+{
+ m_requestId++;
+
+ if (!m_ready) {
+ emit error(m_requestId, QCameraImageCapture::NotReadyError, tr("Camera not ready"));
+ return m_requestId;
+ }
+
+#ifdef DEBUG_CAPTURE
+ qDebug() << Q_FUNC_INFO << m_requestId << fileName;
+#endif
+ m_session->captureImage(m_requestId, fileName);
+ return m_requestId;
+}
+
+void CameraBinImageCapture::cancelCapture()
+{
+}
+
+void CameraBinImageCapture::updateState()
+{
+ bool ready = m_session->state() == QCamera::ActiveState;
+ if (m_ready != ready) {
+#ifdef DEBUG_CAPTURE
+ qDebug() << "readyForCaptureChanged" << ready;
+#endif
+ emit readyForCaptureChanged(m_ready = ready);
+ }
+}
+
+gboolean CameraBinImageCapture::handleImageSaved(GstElement *camera,
+ const gchar *filename,
+ CameraBinImageCapture *self)
+{
+#ifdef DEBUG_CAPTURE
+ qDebug() << "Image saved" << filename;
+#endif
+
+ Q_UNUSED(camera);
+
+ if (self->m_session->captureDestinationControl()->captureDestination() & QCameraImageCapture::CaptureToFile) {
+ QMetaObject::invokeMethod(self, "imageSaved",
+ Qt::QueuedConnection,
+ Q_ARG(int, self->m_requestId),
+ Q_ARG(QString, QString::fromUtf8(filename)));
+ } else {
+#ifdef DEBUG_CAPTURE
+ qDebug() << Q_FUNC_INFO << "Dropped saving file" << filename;
+#endif
+ //camerabin creates an empty file when captured buffer is dropped,
+ //let's remove it
+ QFileInfo info(QString::fromUtf8(filename));
+ if (info.isFile() &&
+ info.filePath().startsWith("/home") &&
+ info.size() == 0) {
+ QFile(info.absoluteFilePath()).remove();
+ }
+ }
+ return true;
+}
+
+gboolean CameraBinImageCapture::metadataEventProbe(GstPad *pad, GstEvent *event, CameraBinImageCapture *self)
+{
+
+ if (GST_EVENT_TYPE(event) == GST_EVENT_TAG) {
+ GstTagList *gstTags;
+ gst_event_parse_tag(event, &gstTags);
+ QMap<QByteArray, QVariant> extendedTags = QGstUtils::gstTagListToMap(gstTags);
+
+#ifdef DEBUG_CAPTURE
+ qDebug() << QString(gst_structure_to_string(gst_event_get_structure(event))).right(768);
+ qDebug() << "Capture event probe" << extendedTags;
+#endif
+
+ QMap<QtMultimediaKit::MetaData, QVariant> tags;
+ tags[QtMultimediaKit::ISOSpeedRatings] = extendedTags.value("capturing-iso-speed");
+ tags[QtMultimediaKit::DigitalZoomRatio] = extendedTags.value("capturing-digital-zoom-ratio");
+ tags[QtMultimediaKit::ExposureTime] = extendedTags.value("capturing-shutter-speed");
+ tags[QtMultimediaKit::WhiteBalance] = extendedTags.value("capturing-white-balance");
+ tags[QtMultimediaKit::Flash] = extendedTags.value("capturing-flash-fired");
+ tags[QtMultimediaKit::FocalLengthIn35mmFilm] = extendedTags.value("capturing-focal-length");
+ tags[QtMultimediaKit::MeteringMode] = extendedTags.value("capturing-metering-mode");
+ tags[QtMultimediaKit::ExposureMode] = extendedTags.value("capturing-exposure-mode");
+ tags[QtMultimediaKit::FNumber] = extendedTags.value("capturing-focal-ratio");
+ tags[QtMultimediaKit::ExposureMode] = extendedTags.value("capturing-exposure-mode");
+
+ QMapIterator<QtMultimediaKit::MetaData, QVariant> i(tags);
+ while (i.hasNext()) {
+ i.next();
+ if (i.value().isValid()) {
+ QMetaObject::invokeMethod(self, "imageMetadataAvailable",
+ Qt::QueuedConnection,
+ Q_ARG(int, self->m_requestId),
+ Q_ARG(QtMultimediaKit::MetaData, i.key()),
+ Q_ARG(QVariant, i.value()));
+ }
+ }
+ }
+
+ return true;
+}
+
+gboolean CameraBinImageCapture::uncompressedBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *self)
+{
+ Q_UNUSED(pad);
+ CameraBinSession *session = self->m_session;
+
+#ifdef DEBUG_CAPTURE
+ qDebug() << "Uncompressed buffer probe" << gst_caps_to_string(GST_BUFFER_CAPS(buffer));
+#endif
+
+ QCameraImageCapture::CaptureDestinations destination =
+ session->captureDestinationControl()->captureDestination();
+ QVideoFrame::PixelFormat format = session->captureBufferFormatControl()->bufferFormat();
+
+ if (destination & QCameraImageCapture::CaptureToBuffer) {
+ if (format != QVideoFrame::Format_Jpeg) {
+ GstCaps *caps = GST_BUFFER_CAPS(buffer);
+ int bytesPerLine = -1;
+ QVideoSurfaceFormat format = QVideoSurfaceGstSink::formatForCaps(caps, &bytesPerLine);
+#ifdef DEBUG_CAPTURE
+ qDebug() << "imageAvailable(uncompressed):" << format;
+#endif
+ QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer, bytesPerLine);
+
+ QVideoFrame frame(videoBuffer,
+ format.frameSize(),
+ format.pixelFormat());
+
+ QMetaObject::invokeMethod(self, "imageAvailable",
+ Qt::QueuedConnection,
+ Q_ARG(int, self->m_requestId),
+ Q_ARG(QVideoFrame, frame));
+ }
+ }
+
+ //keep the buffer if capture to file or jpeg buffer capture was reuqsted
+ bool keepBuffer = (destination & QCameraImageCapture::CaptureToFile) ||
+ ((destination & QCameraImageCapture::CaptureToBuffer) &&
+ format == QVideoFrame::Format_Jpeg);
+
+ return keepBuffer;
+}
+
+gboolean CameraBinImageCapture::jpegBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *self)
+{
+ Q_UNUSED(pad);
+ CameraBinSession *session = self->m_session;
+
+#ifdef DEBUG_CAPTURE
+ qDebug() << "Jpeg buffer probe" << gst_caps_to_string(GST_BUFFER_CAPS(buffer));
+#endif
+
+ QCameraImageCapture::CaptureDestinations destination =
+ session->captureDestinationControl()->captureDestination();
+
+ if ((destination & QCameraImageCapture::CaptureToBuffer) &&
+ session->captureBufferFormatControl()->bufferFormat() == QVideoFrame::Format_Jpeg) {
+ QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer,
+ -1); //bytesPerLine is not available for jpegs
+
+ QSize resolution = QGstUtils::capsCorrectedResolution(GST_BUFFER_CAPS(buffer));
+ //if resolution is not presented in caps, try to find it from encoded jpeg data:
+ if (resolution.isEmpty()) {
+ QBuffer data;
+ data.setData(reinterpret_cast<const char*>(GST_BUFFER_DATA(buffer)), GST_BUFFER_SIZE(buffer));
+ QImageReader reader(&data, "JPEG");
+ resolution = reader.size();
+ }
+
+ QVideoFrame frame(videoBuffer,
+ resolution,
+ QVideoFrame::Format_Jpeg);
+
+ QMetaObject::invokeMethod(self, "imageAvailable",
+ Qt::QueuedConnection,
+ Q_ARG(int, self->m_requestId),
+ Q_ARG(QVideoFrame, frame));
+ }
+
+ //drop the buffer if capture to file was disabled
+ return destination & QCameraImageCapture::CaptureToFile;
+}
+
+void CameraBinImageCapture::handleBusMessage(const QGstreamerMessage &message)
+{
+ //Install metadata event and buffer probes
+
+ //The image capture pipiline is built dynamically,
+ //it's necessary to wait until jpeg encoder is added to pipeline
+
+ GstMessage *gm = message.rawMessage();
+ if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED) {
+ GstState oldState;
+ GstState newState;
+ GstState pending;
+ gst_message_parse_state_changed(gm, &oldState, &newState, &pending);
+
+ if (newState == GST_STATE_READY) {
+ GstElement *element = GST_ELEMENT(GST_MESSAGE_SRC(gm));
+ if (!element)
+ return;
+
+ QString elementName = QString::fromLatin1(gst_element_get_name(element));
+ if (elementName.contains("jpegenc") && element != m_jpegEncoderElement) {
+ m_jpegEncoderElement = element;
+ GstPad *sinkpad = gst_element_get_static_pad(element, "sink");
+
+ //metadata event probe is installed before jpeg encoder
+ //to emit metadata available signal as soon as possible.
+#ifdef DEBUG_CAPTURE
+ qDebug() << "install metadata probe";
+#endif
+ gst_pad_add_event_probe(sinkpad,
+ G_CALLBACK(CameraBinImageCapture::metadataEventProbe),
+ this);
+
+#ifdef DEBUG_CAPTURE
+ qDebug() << "install uncompressed buffer probe";
+#endif
+ gst_pad_add_buffer_probe(sinkpad,
+ G_CALLBACK(CameraBinImageCapture::uncompressedBufferProbe),
+ this);
+
+ gst_object_unref(sinkpad);
+ } else if ((elementName.contains("jifmux") || elementName.startsWith("metadatamux"))
+ && element != m_metadataMuxerElement) {
+ //Jpeg encoded buffer probe is added after jifmux/metadatamux
+ //element to ensure the resulting jpeg buffer contains capture metadata
+ m_metadataMuxerElement = element;
+
+ GstPad *srcpad = gst_element_get_static_pad(element, "src");
+#ifdef DEBUG_CAPTURE
+ qDebug() << "install jpeg buffer probe";
+#endif
+ gst_pad_add_buffer_probe(srcpad,
+ G_CALLBACK(CameraBinImageCapture::jpegBufferProbe),
+ this);
+ gst_object_unref(srcpad);
+ }
+ }
+ }
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabinimagecapture.h b/src/plugins/gstreamer/camerabin/camerabinimagecapture.h
new file mode 100644
index 000000000..4aa5e998f
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinimagecapture.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** 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 CAMERABINIMAGECAPTURECONTROL_H
+#define CAMERABINIMAGECAPTURECONTROL_H
+
+#include <qcameraimagecapturecontrol.h>
+#include "camerabinsession.h"
+
+QT_USE_NAMESPACE
+
+class CameraBinImageCapture : public QCameraImageCaptureControl
+{
+ Q_OBJECT
+public:
+ CameraBinImageCapture(CameraBinSession *session);
+ virtual ~CameraBinImageCapture();
+
+ QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; }
+ void setDriveMode(QCameraImageCapture::DriveMode) {}
+
+ bool isReadyForCapture() const;
+ int capture(const QString &fileName);
+ void cancelCapture();
+
+private slots:
+ void updateState();
+ void handleBusMessage(const QGstreamerMessage &message);
+
+private:
+ static gboolean metadataEventProbe(GstPad *pad, GstEvent *event, CameraBinImageCapture *);
+ static gboolean uncompressedBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *);
+ static gboolean jpegBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *);
+ static gboolean handleImageSaved(GstElement *camera, const gchar *filename, CameraBinImageCapture *);
+
+ CameraBinSession *m_session;
+ bool m_ready;
+ int m_requestId;
+ GstElement *m_jpegEncoderElement;
+ GstElement *m_metadataMuxerElement;
+};
+
+#endif // CAMERABINCAPTURECORNTROL_H
diff --git a/src/plugins/gstreamer/camerabin/camerabinimageencoder.cpp b/src/plugins/gstreamer/camerabin/camerabinimageencoder.cpp
new file mode 100644
index 000000000..2def12666
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinimageencoder.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "camerabinimageencoder.h"
+#include "camerabinsession.h"
+
+#include <QtCore/qdebug.h>
+
+CameraBinImageEncoder::CameraBinImageEncoder(CameraBinSession *session)
+ :QImageEncoderControl(session), m_session(session)
+{
+}
+
+CameraBinImageEncoder::~CameraBinImageEncoder()
+{
+}
+
+QList<QSize> CameraBinImageEncoder::supportedResolutions(const QImageEncoderSettings &, bool *continuous) const
+{
+ qDebug() << "CameraBinImageEncoder::supportedResolutions()";
+ if (continuous)
+ *continuous = false;
+
+ return m_session->supportedResolutions(qMakePair<int,int>(0,0), continuous, QCamera::CaptureStillImage);
+}
+
+QStringList CameraBinImageEncoder::supportedImageCodecs() const
+{
+ return QStringList() << "jpeg";
+}
+
+QString CameraBinImageEncoder::imageCodecDescription(const QString &codecName) const
+{
+ if (codecName == "jpeg")
+ return tr("JPEG image");
+
+ return QString();
+}
+
+QImageEncoderSettings CameraBinImageEncoder::imageSettings() const
+{
+ return m_settings;
+}
+
+void CameraBinImageEncoder::setImageSettings(const QImageEncoderSettings &settings)
+{
+ m_settings = settings;
+ emit settingsChanged();
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabinimageencoder.h b/src/plugins/gstreamer/camerabin/camerabinimageencoder.h
new file mode 100644
index 000000000..ddb06a668
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinimageencoder.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 CAMERABINIMAGEENCODE_H
+#define CAMERABINIMAGEENCODE_H
+
+class CameraBinSession;
+
+#include <qimageencodercontrol.h>
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+
+#include <gst/gst.h>
+QT_USE_NAMESPACE
+
+class CameraBinImageEncoder : public QImageEncoderControl
+{
+ Q_OBJECT
+public:
+ CameraBinImageEncoder(CameraBinSession *session);
+ virtual ~CameraBinImageEncoder();
+
+ QList<QSize> supportedResolutions(const QImageEncoderSettings &settings = QImageEncoderSettings(),
+ bool *continuous = 0) const;
+
+ QStringList supportedImageCodecs() const;
+ QString imageCodecDescription(const QString &formatName) const;
+
+ QImageEncoderSettings imageSettings() const;
+ void setImageSettings(const QImageEncoderSettings &settings);
+
+Q_SIGNALS:
+ void settingsChanged();
+
+private:
+ QImageEncoderSettings m_settings;
+
+ CameraBinSession *m_session;
+
+ // Added
+ QStringList m_codecs;
+ QMap<QString,QByteArray> m_elementNames;
+ QMap<QString,QString> m_codecDescriptions;
+ QMap<QString,QStringList> m_codecOptions;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/camerabin/camerabinimageprocessing.cpp b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.cpp
new file mode 100644
index 000000000..075ff2a67
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** 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 "camerabinimageprocessing.h"
+#include "camerabinsession.h"
+
+CameraBinImageProcessing::CameraBinImageProcessing(CameraBinSession *session)
+ :QCameraImageProcessingControl(session),
+ m_session(session)
+{
+ m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_AUTO] = QCameraImageProcessing::WhiteBalanceAuto;
+ m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT] = QCameraImageProcessing::WhiteBalanceSunlight;
+ m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_CLOUDY] = QCameraImageProcessing::WhiteBalanceCloudy;
+ m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_SUNSET] = QCameraImageProcessing::WhiteBalanceSunset;
+ m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN] = QCameraImageProcessing::WhiteBalanceTungsten;
+ m_mappedWbValues[GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT] = QCameraImageProcessing::WhiteBalanceFluorescent;
+
+ updateColorBalanceValues();
+}
+
+CameraBinImageProcessing::~CameraBinImageProcessing()
+{
+}
+
+void CameraBinImageProcessing::updateColorBalanceValues()
+{
+ if (!GST_IS_COLOR_BALANCE(m_session->cameraBin())) {
+ // Camerabin doesn't implement gstcolorbalance interface
+ return;
+ }
+
+ GstColorBalance *balance = GST_COLOR_BALANCE(m_session->cameraBin());
+ const GList *controls = gst_color_balance_list_channels(balance);
+
+ const GList *item;
+ GstColorBalanceChannel *channel;
+ gint cur_value;
+
+ for (item = controls; item; item = g_list_next (item)) {
+ channel = (GstColorBalanceChannel *)item->data;
+ cur_value = gst_color_balance_get_value (balance, channel);
+
+ if (!g_ascii_strcasecmp (channel->label, "brightness")) {
+ m_values[QCameraImageProcessingControl::Brightness] = cur_value;
+ } else if (!g_ascii_strcasecmp (channel->label, "contrast")) {
+ m_values[QCameraImageProcessingControl::Contrast] = cur_value;
+ } else if (!g_ascii_strcasecmp (channel->label, "saturation")) {
+ m_values[QCameraImageProcessingControl::Saturation] = cur_value;
+ }
+ }
+}
+
+bool CameraBinImageProcessing::setColorBalanceValue(const QString& channel, int value)
+{
+
+ if (!GST_IS_COLOR_BALANCE(m_session->cameraBin())) {
+ // Camerabin doesn't implement gstcolorbalance interface
+ return false;
+ }
+
+ GstColorBalance *balance = GST_COLOR_BALANCE(m_session->cameraBin());
+ const GList *controls = gst_color_balance_list_channels(balance);
+
+ const GList *item;
+ GstColorBalanceChannel *colorBalanceChannel;
+
+ for (item = controls; item; item = g_list_next (item)) {
+ colorBalanceChannel = (GstColorBalanceChannel *)item->data;
+
+ if (!g_ascii_strcasecmp (colorBalanceChannel->label, channel.toAscii())) {
+ gst_color_balance_set_value (balance, colorBalanceChannel, value);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+QCameraImageProcessing::WhiteBalanceMode CameraBinImageProcessing::whiteBalanceMode() const
+{
+ GstWhiteBalanceMode wbMode;
+ gst_photography_get_white_balance_mode(m_session->photography(), &wbMode);
+ return m_mappedWbValues[wbMode];
+}
+
+void CameraBinImageProcessing::setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode)
+{
+ if (isWhiteBalanceModeSupported(mode))
+ gst_photography_set_white_balance_mode(m_session->photography(), m_mappedWbValues.key(mode));
+}
+
+bool CameraBinImageProcessing::isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const
+{
+ return m_mappedWbValues.values().contains(mode);
+}
+
+bool CameraBinImageProcessing::isProcessingParameterSupported(QCameraImageProcessingControl::ProcessingParameter parameter) const
+{
+ return parameter == QCameraImageProcessingControl::Contrast
+ || parameter == QCameraImageProcessingControl::Brightness
+ || parameter == QCameraImageProcessingControl::Saturation;
+}
+
+QVariant CameraBinImageProcessing::processingParameter(
+ QCameraImageProcessingControl::ProcessingParameter parameter) const
+{
+ if (m_values.contains(parameter))
+ return m_values.value(parameter);
+ else
+ return QVariant();
+}
+
+void CameraBinImageProcessing::setProcessingParameter(
+ QCameraImageProcessingControl::ProcessingParameter parameter,
+ QVariant value)
+{
+ switch (parameter) {
+ case Contrast:
+ setColorBalanceValue("contrast", value.toInt());
+ break;
+ case Brightness:
+ setColorBalanceValue("brightness", value.toInt());
+ break;
+ case Saturation:
+ setColorBalanceValue("saturation", value.toInt());
+ break;
+ default:
+ break;
+ }
+
+ updateColorBalanceValues();
+}
+
diff --git a/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h
new file mode 100644
index 000000000..661d0d9d4
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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 CAMERABINIMAGEPROCESSINGCONTROL_H
+#define CAMERABINIMAGEPROCESSINGCONTROL_H
+
+#include <qcamera.h>
+#include <qcameraimageprocessingcontrol.h>
+
+#include <gst/gst.h>
+#include <glib.h>
+
+#include <gst/interfaces/photography.h>
+#include <gst/interfaces/colorbalance.h>
+
+class CameraBinSession;
+
+QT_USE_NAMESPACE
+
+class CameraBinImageProcessing : public QCameraImageProcessingControl
+{
+ Q_OBJECT
+
+public:
+ CameraBinImageProcessing(CameraBinSession *session);
+ virtual ~CameraBinImageProcessing();
+
+ QCameraImageProcessing::WhiteBalanceMode whiteBalanceMode() const;
+ void setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode);
+ bool isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const;
+
+ bool isProcessingParameterSupported(ProcessingParameter) const;
+ QVariant processingParameter(ProcessingParameter parameter) const;
+ void setProcessingParameter(ProcessingParameter parameter, QVariant value);
+
+private:
+ bool setColorBalanceValue(const QString& channel, int value);
+ void updateColorBalanceValues();
+
+private:
+ CameraBinSession *m_session;
+ QMap<QCameraImageProcessingControl::ProcessingParameter, int> m_values;
+ QMap<GstWhiteBalanceMode, QCameraImageProcessing::WhiteBalanceMode> m_mappedWbValues;
+};
+
+#endif // CAMERABINIMAGEPROCESSINGCONTROL_H
diff --git a/src/plugins/gstreamer/camerabin/camerabinlocks.cpp b/src/plugins/gstreamer/camerabin/camerabinlocks.cpp
new file mode 100644
index 000000000..66da126f8
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinlocks.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** 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 "camerabinlocks.h"
+#include "camerabinsession.h"
+#include "camerabinfocus.h"
+
+#include <gst/interfaces/photography.h>
+
+#include <QDebug>
+
+CameraBinLocks::CameraBinLocks(CameraBinSession *session)
+ :QCameraLocksControl(session),
+ m_session(session),
+ m_focus(m_session->cameraFocusControl())
+{
+ connect(m_focus, SIGNAL(_q_focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
+ this, SLOT(updateFocusStatus(QCamera::LockStatus, QCamera::LockChangeReason)));
+}
+
+CameraBinLocks::~CameraBinLocks()
+{
+}
+
+QCamera::LockTypes CameraBinLocks::supportedLocks() const
+{
+ return QCamera::LockFocus;
+}
+
+QCamera::LockStatus CameraBinLocks::lockStatus(QCamera::LockType lock) const
+{
+ return lock == QCamera::LockFocus ? m_focus->focusStatus() : QCamera::Unlocked;
+}
+
+void CameraBinLocks::searchAndLock(QCamera::LockTypes locks)
+{
+ if (locks & QCamera::LockFocus)
+ m_focus->_q_startFocusing();
+}
+
+void CameraBinLocks::unlock(QCamera::LockTypes locks)
+{
+ if (locks & QCamera::LockFocus)
+ m_focus->_q_stopFocusing();
+}
+
+void CameraBinLocks::updateFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason)
+{
+ emit lockStatusChanged(QCamera::LockFocus, status, reason);
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabinlocks.h b/src/plugins/gstreamer/camerabin/camerabinlocks.h
new file mode 100644
index 000000000..29c4f2ece
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinlocks.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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 CAMERABINLOCKSCONTROL_H
+#define CAMERABINLOCKSCONTROL_H
+
+#include <qcamera.h>
+#include <qcameralockscontrol.h>
+
+#include <gst/gst.h>
+#include <glib.h>
+
+class CameraBinSession;
+class CameraBinFocus;
+
+QT_USE_NAMESPACE
+
+class CameraBinLocks : public QCameraLocksControl
+{
+ Q_OBJECT
+
+public:
+ CameraBinLocks(CameraBinSession *session);
+ virtual ~CameraBinLocks();
+
+ QCamera::LockTypes supportedLocks() const;
+
+ QCamera::LockStatus lockStatus(QCamera::LockType lock) const;
+
+ void searchAndLock(QCamera::LockTypes locks);
+ void unlock(QCamera::LockTypes locks);
+
+private slots:
+ void updateFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason);
+
+private:
+ CameraBinSession *m_session;
+ CameraBinFocus *m_focus;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp b/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp
new file mode 100644
index 000000000..d7036ebc2
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinmetadata.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** 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$
+** 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 "camerabinmetadata.h"
+
+#include <gst/gst.h>
+#include <gst/gstversion.h>
+
+struct QGstreamerMetaDataKeyLookup
+{
+ QtMultimediaKit::MetaData key;
+ const char *token;
+};
+
+static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] =
+{
+ { QtMultimediaKit::Title, GST_TAG_TITLE },
+ //{ QtMultimediaKit::SubTitle, 0 },
+ //{ QtMultimediaKit::Author, 0 },
+ { QtMultimediaKit::Comment, GST_TAG_COMMENT },
+ { QtMultimediaKit::Description, GST_TAG_DESCRIPTION },
+ //{ QtMultimediaKit::Category, 0 },
+ { QtMultimediaKit::Genre, GST_TAG_GENRE },
+ //{ QtMultimediaKit::Year, 0 },
+ //{ QtMultimediaKit::UserRating, 0 },
+
+ { QtMultimediaKit::Language, GST_TAG_LANGUAGE_CODE },
+
+ { QtMultimediaKit::Publisher, GST_TAG_ORGANIZATION },
+ { QtMultimediaKit::Copyright, GST_TAG_COPYRIGHT },
+ //{ QtMultimediaKit::ParentalRating, 0 },
+ //{ QtMultimediaKit::RatingOrganisation, 0 },
+
+ // Media
+ //{ QtMultimediaKit::Size, 0 },
+ //{ QtMultimediaKit::MediaType, 0 },
+ { QtMultimediaKit::Duration, GST_TAG_DURATION },
+
+ // Audio
+ { QtMultimediaKit::AudioBitRate, GST_TAG_BITRATE },
+ { QtMultimediaKit::AudioCodec, GST_TAG_AUDIO_CODEC },
+ //{ QtMultimediaKit::ChannelCount, 0 },
+ //{ QtMultimediaKit::SampleRate, 0 },
+
+ // Music
+ { QtMultimediaKit::AlbumTitle, GST_TAG_ALBUM },
+ { QtMultimediaKit::AlbumArtist, GST_TAG_ARTIST},
+ { QtMultimediaKit::ContributingArtist, GST_TAG_PERFORMER },
+#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
+ { QtMultimediaKit::Composer, GST_TAG_COMPOSER },
+#endif
+ //{ QtMultimediaKit::Conductor, 0 },
+ //{ QtMultimediaKit::Lyrics, 0 },
+ //{ QtMultimediaKit::Mood, 0 },
+ { QtMultimediaKit::TrackNumber, GST_TAG_TRACK_NUMBER },
+
+ //{ QtMultimediaKit::CoverArtUrlSmall, 0 },
+ //{ QtMultimediaKit::CoverArtUrlLarge, 0 },
+
+ // Image/Video
+ //{ QtMultimediaKit::Resolution, 0 },
+ //{ QtMultimediaKit::PixelAspectRatio, 0 },
+
+ // Video
+ //{ QtMultimediaKit::VideoFrameRate, 0 },
+ //{ QtMultimediaKit::VideoBitRate, 0 },
+ { QtMultimediaKit::VideoCodec, GST_TAG_VIDEO_CODEC },
+
+ //{ QtMultimediaKit::PosterUrl, 0 },
+
+ // Movie
+ //{ QtMultimediaKit::ChapterNumber, 0 },
+ //{ QtMultimediaKit::Director, 0 },
+ { QtMultimediaKit::LeadPerformer, GST_TAG_PERFORMER },
+ //{ QtMultimediaKit::Writer, 0 },
+
+ // Photos
+ //{ QtMultimediaKit::CameraManufacturer, 0 },
+ //{ QtMultimediaKit::CameraModel, 0 },
+ //{ QtMultimediaKit::Event, 0 },
+ //{ QtMultimediaKit::Subject, 0 }
+};
+
+CameraBinMetaData::CameraBinMetaData(QObject *parent)
+ :QMetaDataWriterControl(parent)
+{
+}
+
+QVariant CameraBinMetaData::metaData(QtMultimediaKit::MetaData key) const
+{
+ static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
+
+ for (int i = 0; i < count; ++i) {
+ if (qt_gstreamerMetaDataKeys[i].key == key) {
+ const char *name = qt_gstreamerMetaDataKeys[i].token;
+
+ return m_values.value(QByteArray::fromRawData(name, qstrlen(name)));
+ }
+ }
+ return QVariant();
+}
+
+void CameraBinMetaData::setMetaData(QtMultimediaKit::MetaData key, const QVariant &value)
+{
+ static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
+
+ for (int i = 0; i < count; ++i) {
+ if (qt_gstreamerMetaDataKeys[i].key == key) {
+ const char *name = qt_gstreamerMetaDataKeys[i].token;
+
+ m_values.insert(QByteArray::fromRawData(name, qstrlen(name)), value);
+
+ emit QMetaDataWriterControl::metaDataChanged();
+ emit metaDataChanged(m_values);
+
+ return;
+ }
+ }
+}
+
+QList<QtMultimediaKit::MetaData> CameraBinMetaData::availableMetaData() const
+{
+ static QMap<QByteArray, QtMultimediaKit::MetaData> keysMap;
+ if (keysMap.isEmpty()) {
+ const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
+ for (int i = 0; i < count; ++i) {
+ keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key;
+ }
+ }
+
+ QList<QtMultimediaKit::MetaData> res;
+ foreach (const QByteArray &key, m_values.keys()) {
+ QtMultimediaKit::MetaData tag = keysMap.value(key, QtMultimediaKit::MetaData(-1));
+ if (tag != -1)
+ res.append(tag);
+ }
+
+ return res;
+}
+
+QVariant CameraBinMetaData::extendedMetaData(QString const &name) const
+{
+ return m_values.value(name.toLatin1());
+}
+
+void CameraBinMetaData::setExtendedMetaData(QString const &name, QVariant const &value)
+{
+ m_values.insert(name.toLatin1(), value);
+ emit QMetaDataWriterControl::metaDataChanged();
+ emit metaDataChanged(m_values);
+}
+
+QStringList CameraBinMetaData::availableExtendedMetaData() const
+{
+ QStringList res;
+ foreach (const QByteArray &key, m_values.keys())
+ res.append(QString(key));
+
+ return res;
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabinmetadata.h b/src/plugins/gstreamer/camerabin/camerabinmetadata.h
new file mode 100644
index 000000000..be00da839
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinmetadata.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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$
+** 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 CAMERABINCAPTUREMETADATACONTROL_H
+#define CAMERABINCAPTUREMETADATACONTROL_H
+
+#include <qmetadatawritercontrol.h>
+
+QT_USE_NAMESPACE
+
+class CameraBinMetaData : public QMetaDataWriterControl
+{
+ Q_OBJECT
+public:
+ CameraBinMetaData(QObject *parent);
+ virtual ~CameraBinMetaData() {}
+
+
+ bool isMetaDataAvailable() const { return true; }
+ bool isWritable() const { return true; }
+
+ QVariant metaData(QtMultimediaKit::MetaData key) const;
+ void setMetaData(QtMultimediaKit::MetaData key, const QVariant &value);
+ QList<QtMultimediaKit::MetaData> availableMetaData() const;
+
+ QVariant extendedMetaData(QString const &name) const;
+ void setExtendedMetaData(QString const &name, QVariant const &value);
+ QStringList availableExtendedMetaData() const;
+
+Q_SIGNALS:
+ void metaDataChanged(const QMap<QByteArray, QVariant>&);
+
+private:
+ QMap<QByteArray, QVariant> m_values;
+};
+
+#endif // CAMERABINCAPTUREMETADATACONTROL_H
diff --git a/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp b/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp
new file mode 100644
index 000000000..0cd8a5aaf
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** 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$
+** 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 "camerabinrecorder.h"
+#include "camerabinaudioencoder.h"
+#include "camerabinvideoencoder.h"
+#include "camerabincontainer.h"
+#include <QtCore/QDebug>
+
+CameraBinRecorder::CameraBinRecorder(CameraBinSession *session)
+ :QMediaRecorderControl(session),
+ m_session(session),
+ m_state(QMediaRecorder::StoppedState)
+{
+ connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
+ connect(m_session, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged(qint64)));
+ connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool)));
+}
+
+CameraBinRecorder::~CameraBinRecorder()
+{
+}
+
+QUrl CameraBinRecorder::outputLocation() const
+{
+ return m_session->outputLocation();
+}
+
+bool CameraBinRecorder::setOutputLocation(const QUrl &sink)
+{
+ m_session->setOutputLocation(sink);
+ return true;
+}
+
+QMediaRecorder::State CameraBinRecorder::state() const
+{
+ return m_state;
+}
+
+void CameraBinRecorder::updateState()
+{
+ if (m_session->state() != QCamera::ActiveState &&
+ m_state != QMediaRecorder::StoppedState) {
+ m_session->stopVideoRecording();
+ emit stateChanged(m_state = QMediaRecorder::StoppedState);
+ }
+}
+
+qint64 CameraBinRecorder::duration() const
+{
+ return m_session->duration();
+}
+
+void CameraBinRecorder::record()
+{
+ if (m_session->state() == QCamera::ActiveState) {
+ if (m_state == QMediaRecorder::PausedState)
+ m_session->resumeVideoRecording();
+ else
+ m_session->recordVideo();
+ emit stateChanged(m_state = QMediaRecorder::RecordingState);
+ } else
+ emit error(QMediaRecorder::ResourceError, tr("Service has not been started"));
+}
+
+void CameraBinRecorder::pause()
+{
+ if (m_session->state() == QCamera::ActiveState) {
+ m_session->pauseVideoRecording();
+ emit stateChanged(m_state = QMediaRecorder::PausedState);
+ } else
+ emit error(QMediaRecorder::ResourceError, tr("Service has not been started"));
+}
+
+void CameraBinRecorder::stop()
+{
+ if (m_session->state() == QCamera::ActiveState) {
+ m_session->stopVideoRecording();
+ emit stateChanged(m_state = QMediaRecorder::StoppedState);
+ }
+}
+
+bool CameraBinRecorder::findCodecs()
+{
+ //Check the codecs are compatible with container,
+ //and choose the compatible codecs/container if omitted
+ CameraBinAudioEncoder *audioEncodeControl = m_session->audioEncodeControl();
+ CameraBinVideoEncoder *videoEncodeControl = m_session->videoEncodeControl();
+ CameraBinContainer *mediaContainerControl = m_session->mediaContainerControl();
+
+ audioEncodeControl->resetActualSettings();
+ videoEncodeControl->resetActualSettings();
+ mediaContainerControl->resetActualContainer();
+
+ QStringList containerCandidates;
+ if (mediaContainerControl->containerMimeType().isEmpty())
+ containerCandidates = mediaContainerControl->supportedContainers();
+ else
+ containerCandidates << mediaContainerControl->containerMimeType();
+
+
+ QStringList audioCandidates;
+ QAudioEncoderSettings audioSettings = audioEncodeControl->audioSettings();
+ if (audioSettings.codec().isEmpty())
+ audioCandidates = audioEncodeControl->supportedAudioCodecs();
+ else
+ audioCandidates << audioSettings.codec();
+
+ QStringList videoCandidates;
+ QVideoEncoderSettings videoSettings = videoEncodeControl->videoSettings();
+ if (videoSettings.codec().isEmpty())
+ videoCandidates = videoEncodeControl->supportedVideoCodecs();
+ else
+ videoCandidates << videoSettings.codec();
+
+ QString container;
+ QString audioCodec;
+ QString videoCodec;
+
+ foreach (const QString &containerCandidate, containerCandidates) {
+ QSet<QString> supportedTypes = mediaContainerControl->supportedStreamTypes(containerCandidate);
+
+ audioCodec.clear();
+ videoCodec.clear();
+
+ bool found = false;
+ foreach (const QString &audioCandidate, audioCandidates) {
+ QSet<QString> audioTypes = audioEncodeControl->supportedStreamTypes(audioCandidate);
+ if (!audioTypes.intersect(supportedTypes).isEmpty()) {
+ found = true;
+ audioCodec = audioCandidate;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+
+ found = false;
+ foreach (const QString &videoCandidate, videoCandidates) {
+ QSet<QString> videoTypes = videoEncodeControl->supportedStreamTypes(videoCandidate);
+ if (!videoTypes.intersect(supportedTypes).isEmpty()) {
+ found = true;
+ videoCodec = videoCandidate;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+
+
+ container = containerCandidate;
+ break;
+ }
+
+ if (container.isEmpty()) {
+ qWarning() << "Camera error: Not compatible codecs and container format.";
+ emit error(QMediaRecorder::FormatError, tr("Not compatible codecs and container format."));
+ return false;
+ } else {
+ mediaContainerControl->setActualContainer(container);
+
+ QAudioEncoderSettings audioSettings = audioEncodeControl->audioSettings();
+ audioSettings.setCodec(audioCodec);
+ audioEncodeControl->setActualAudioSettings(audioSettings);
+
+ QVideoEncoderSettings videoSettings = videoEncodeControl->videoSettings();
+ videoSettings.setCodec(videoCodec);
+ videoEncodeControl->setActualVideoSettings(videoSettings);
+ }
+
+ return true;
+}
+
+void CameraBinRecorder::applySettings()
+{
+ findCodecs();
+}
+
+bool CameraBinRecorder::isMuted() const
+{
+ return m_session->isMuted();
+}
+
+void CameraBinRecorder::setMuted(bool muted)
+{
+ m_session->setMuted(muted);
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabinrecorder.h b/src/plugins/gstreamer/camerabin/camerabinrecorder.h
new file mode 100644
index 000000000..a6faf9b64
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinrecorder.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 CAMERABINRECORDERCONTROL_H
+#define CAMERABINRECORDERCONTROL_H
+
+#include <qmediarecordercontrol.h>
+#include "camerabinsession.h"
+QT_USE_NAMESPACE
+
+class CameraBinRecorder : public QMediaRecorderControl
+{
+ Q_OBJECT
+
+public:
+ CameraBinRecorder(CameraBinSession *session);
+ virtual ~CameraBinRecorder();
+
+ QUrl outputLocation() const;
+ bool setOutputLocation(const QUrl &sink);
+
+ QMediaRecorder::State state() const;
+
+ qint64 duration() const;
+
+ bool isMuted() const;
+
+ bool findCodecs();
+
+ void applySettings();
+
+public slots:
+ void record();
+ void pause();
+ void stop();
+ void setMuted(bool);
+
+private slots:
+ void updateState();
+
+private:
+ CameraBinSession *m_session;
+ QMediaRecorder::State m_state;
+};
+
+#endif // CAMERABINCAPTURECORNTROL_H
diff --git a/src/plugins/gstreamer/camerabin/camerabinresourcepolicy.cpp b/src/plugins/gstreamer/camerabin/camerabinresourcepolicy.cpp
new file mode 100644
index 000000000..db9218c4a
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinresourcepolicy.cpp
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** 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$
+** 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 "camerabinresourcepolicy.h"
+
+#ifdef Q_WS_MAEMO_6
+#define HAVE_RESOURCE_POLICY
+#endif
+
+//#define DEBUG_RESOURCE_POLICY
+#include <QtCore/qdebug.h>
+#include <QtCore/qset.h>
+
+#ifdef HAVE_RESOURCE_POLICY
+#include <policy/resource.h>
+#include <policy/resources.h>
+#include <policy/resource-set.h>
+#endif
+
+CamerabinResourcePolicy::CamerabinResourcePolicy(QObject *parent) :
+ QObject(parent),
+ m_resourceSet(NoResources),
+ m_releasingResources(false)
+{
+#ifdef HAVE_RESOURCE_POLICY
+ //loaded resource set is also kept requested for image and video capture sets
+ m_resource = new ResourcePolicy::ResourceSet("camera");
+ m_resource->setAlwaysReply();
+ m_resource->initAndConnect();
+
+ connect(m_resource, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>)),
+ SIGNAL(resourcesGranted()));
+ connect(m_resource, SIGNAL(resourcesDenied()), SIGNAL(resourcesDenied()));
+ connect(m_resource, SIGNAL(lostResources()), SIGNAL(resourcesLost()));
+ connect(m_resource, SIGNAL(resourcesReleased()), SLOT(handleResourcesReleased()));
+#endif
+}
+
+CamerabinResourcePolicy::~CamerabinResourcePolicy()
+{
+#ifdef HAVE_RESOURCE_POLICY
+ //ensure the resources are released
+ if (m_resourceSet != NoResources)
+ setResourceSet(NoResources);
+
+ //don't delete the resource set until resources are released
+ if (m_releasingResources) {
+ m_resource->connect(m_resource, SIGNAL(resourcesReleased()),
+ SLOT(deleteLater()));
+ } else {
+ delete m_resource;
+ m_resource = 0;
+ }
+#endif
+}
+
+CamerabinResourcePolicy::ResourceSet CamerabinResourcePolicy::resourceSet() const
+{
+ return m_resourceSet;
+}
+
+void CamerabinResourcePolicy::setResourceSet(CamerabinResourcePolicy::ResourceSet set)
+{
+ CamerabinResourcePolicy::ResourceSet oldSet = m_resourceSet;
+ m_resourceSet = set;
+
+#ifdef DEBUG_RESOURCE_POLICY
+ qDebug() << Q_FUNC_INFO << set;
+#endif
+
+#ifdef HAVE_RESOURCE_POLICY
+ QSet<ResourcePolicy::ResourceType> requestedTypes;
+
+ switch (set) {
+ case NoResources:
+ break;
+ case LoadedResources:
+ requestedTypes << ResourcePolicy::LensCoverType //to detect lens cover is opened/closed
+ << ResourcePolicy::VideoRecorderType //to open camera device
+ << ResourcePolicy::SnapButtonType; //to detect capture button events
+ break;
+ case ImageCaptureResources:
+ requestedTypes << ResourcePolicy::LensCoverType
+ << ResourcePolicy::VideoPlaybackType
+ << ResourcePolicy::VideoRecorderType
+ << ResourcePolicy::AudioPlaybackType
+ << ResourcePolicy::ScaleButtonType
+ << ResourcePolicy::LedsType
+ << ResourcePolicy::SnapButtonType;
+ break;
+ case VideoCaptureResources:
+ requestedTypes << ResourcePolicy::LensCoverType
+ << ResourcePolicy::VideoPlaybackType
+ << ResourcePolicy::VideoRecorderType
+ << ResourcePolicy::AudioPlaybackType
+ << ResourcePolicy::AudioRecorderType
+ << ResourcePolicy::ScaleButtonType
+ << ResourcePolicy::LedsType
+ << ResourcePolicy::SnapButtonType;
+ break;
+ }
+
+ QSet<ResourcePolicy::ResourceType> currentTypes;
+ foreach (ResourcePolicy::Resource *resource, m_resource->resources())
+ currentTypes << resource->type();
+
+ foreach (ResourcePolicy::ResourceType resourceType, currentTypes - requestedTypes)
+ m_resource->deleteResource(resourceType);
+
+ foreach (ResourcePolicy::ResourceType resourceType, requestedTypes - currentTypes) {
+ if (resourceType == ResourcePolicy::LensCoverType) {
+ ResourcePolicy::LensCoverResource *lensCoverResource = new ResourcePolicy::LensCoverResource;
+ lensCoverResource->setOptional(true);
+ m_resource->addResourceObject(lensCoverResource);
+ } else {
+ m_resource->addResource(resourceType);
+ }
+ }
+
+ m_resource->update();
+ if (set != NoResources) {
+ m_resource->acquire();
+ } else {
+ if (oldSet != NoResources) {
+ m_releasingResources = true;
+ m_resource->release();
+ }
+ }
+#endif
+}
+
+bool CamerabinResourcePolicy::isResourcesGranted() const
+{
+#ifdef HAVE_RESOURCE_POLICY
+ foreach (ResourcePolicy::Resource *resource, m_resource->resources())
+ if (!resource->isOptional() && !resource->isGranted())
+ return false;
+#endif
+ return true;
+}
+
+void CamerabinResourcePolicy::handleResourcesReleased()
+{
+#ifdef HAVE_RESOURCE_POLICY
+#ifdef DEBUG_RESOURCE_POLICY
+ qDebug() << Q_FUNC_INFO;
+#endif
+ m_releasingResources = false;
+#endif
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabinresourcepolicy.h b/src/plugins/gstreamer/camerabin/camerabinresourcepolicy.h
new file mode 100644
index 000000000..cd2d84688
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinresourcepolicy.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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$
+** 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 CAMERARESOURCEPOLICY_H
+#define CAMERARESOURCEPOLICY_H
+
+#include <QtCore/qobject.h>
+
+namespace ResourcePolicy {
+class ResourceSet;
+};
+
+class CamerabinResourcePolicy : public QObject
+{
+ Q_OBJECT
+public:
+ enum ResourceSet {
+ NoResources,
+ LoadedResources,
+ ImageCaptureResources,
+ VideoCaptureResources
+ };
+
+ CamerabinResourcePolicy(QObject *parent);
+ ~CamerabinResourcePolicy();
+
+ ResourceSet resourceSet() const;
+ void setResourceSet(ResourceSet set);
+
+ bool isResourcesGranted() const;
+
+Q_SIGNALS:
+ void resourcesDenied();
+ void resourcesGranted();
+ void resourcesLost();
+
+private Q_SLOTS:
+ void handleResourcesReleased();
+
+private:
+ ResourceSet m_resourceSet;
+ ResourcePolicy::ResourceSet *m_resource;
+ bool m_releasingResources;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/camerabin/camerabinservice.cpp b/src/plugins/gstreamer/camerabin/camerabinservice.cpp
new file mode 100644
index 000000000..261a9c308
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinservice.cpp
@@ -0,0 +1,261 @@
+/****************************************************************************
+**
+** 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$
+** 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 "camerabinservice.h"
+#include "camerabinsession.h"
+#include "camerabinrecorder.h"
+#include "camerabincontainer.h"
+#include "camerabinaudioencoder.h"
+#include "camerabinvideoencoder.h"
+#include "camerabinimageencoder.h"
+#include "qgstreamerbushelper.h"
+#include "camerabincontrol.h"
+#include "camerabinlocks.h"
+#include "camerabinmetadata.h"
+#include "camerabinexposure.h"
+#include "camerabinflash.h"
+#include "camerabinfocus.h"
+#include "camerabinimagecapture.h"
+#include "camerabinimageprocessing.h"
+#include "camerabincapturebufferformat.h"
+#include "camerabincapturedestination.h"
+
+#include "qgstreameraudioinputendpointselector.h"
+#include "qgstreamervideoinputdevicecontrol.h"
+
+#include "qgstreamervideooverlay.h"
+#include "qgstreamervideowindow.h"
+#include "qgstreamervideorenderer.h"
+
+#if defined(Q_WS_MAEMO_6) && defined(__arm__)
+#include "qgstreamergltexturerenderer.h"
+#endif
+
+#include "qgstreamervideowidget.h"
+
+#include <qmediaserviceprovider.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qprocess.h>
+
+#if defined(Q_WS_MAEMO_5)
+#include "camerabuttonlistener_maemo.h"
+#endif
+
+#if defined(Q_WS_MAEMO_6)
+#include "camerabuttonlistener_meego.h"
+#endif
+
+CameraBinService::CameraBinService(const QString &service, QObject *parent):
+ QMediaService(parent)
+{
+ m_captureSession = 0;
+ m_cameraControl = 0;
+ m_metaDataControl = 0;
+
+ m_audioInputEndpointSelector = 0;
+ m_videoInputDevice = 0;
+
+ m_videoOutput = 0;
+ m_videoRenderer = 0;
+ m_videoWindow = 0;
+ m_videoWidgetControl = 0;
+ m_imageCaptureControl = 0;
+
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ m_captureSession = new CameraBinSession(this);
+ m_cameraControl = new CameraBinControl(m_captureSession);
+ m_videoInputDevice = new QGstreamerVideoInputDeviceControl(m_captureSession);
+ m_imageCaptureControl = new CameraBinImageCapture(m_captureSession);
+
+ connect(m_videoInputDevice, SIGNAL(selectedDeviceChanged(QString)),
+ m_captureSession, SLOT(setDevice(QString)));
+
+ if (m_videoInputDevice->deviceCount())
+ m_captureSession->setDevice(m_videoInputDevice->deviceName(m_videoInputDevice->selectedDevice()));
+
+#if defined(Q_WS_MAEMO_6) && defined(__arm__)
+ m_videoRenderer = new QGstreamerGLTextureRenderer(this);
+#else
+ m_videoRenderer = new QGstreamerVideoRenderer(this);
+#endif
+
+
+#ifdef Q_WS_MAEMO_6
+ m_videoWindow = new QGstreamerVideoWindow(this, "omapxvsink");
+ //m_videoWindow = new QGstreamerVideoWindow(this);
+#else
+ m_videoWindow = new QGstreamerVideoOverlay(this);
+#endif
+
+ m_videoWidgetControl = new QGstreamerVideoWidgetControl(this);
+
+ }
+
+ if (!m_captureSession) {
+ qWarning() << Q_FUNC_INFO << "Service type is not supported:" << service;
+ return;
+ }
+
+ m_audioInputEndpointSelector = new QGstreamerAudioInputEndpointSelector(this);
+ connect(m_audioInputEndpointSelector, SIGNAL(activeEndpointChanged(QString)), m_captureSession, SLOT(setCaptureDevice(QString)));
+
+ if (m_captureSession && m_audioInputEndpointSelector->availableEndpoints().size() > 0)
+ m_captureSession->setCaptureDevice(m_audioInputEndpointSelector->defaultEndpoint());
+
+ m_metaDataControl = new CameraBinMetaData(this);
+ connect(m_metaDataControl, SIGNAL(metaDataChanged(QMap<QByteArray,QVariant>)),
+ m_captureSession, SLOT(setMetaData(QMap<QByteArray,QVariant>)));
+
+#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
+ new CameraButtonListener(this);
+#endif
+
+#if defined(Q_WS_MAEMO_5)
+ //disable the system camera application
+ QProcess::execute("/usr/sbin/dsmetool -k /usr/bin/camera-ui");
+#endif
+}
+
+CameraBinService::~CameraBinService()
+{
+#if defined(Q_WS_MAEMO_5)
+ //restore the system camera application
+ QProcess::execute("/usr/sbin/dsmetool -U user -o /usr/bin/camera-ui");
+#endif
+}
+
+QMediaControl *CameraBinService::requestControl(const char *name)
+{
+ if (!m_captureSession)
+ return 0;
+
+ //qDebug() << "Request control" << name;
+
+ if (!m_videoOutput) {
+ if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+ m_videoOutput = m_videoRenderer;
+ m_captureSession->setViewfinder(m_videoRenderer);
+ } else if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
+ m_videoOutput = m_videoWindow;
+ m_captureSession->setViewfinder(m_videoWindow);
+ } else if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
+ m_captureSession->setViewfinder(m_videoWidgetControl);
+ m_videoOutput = m_videoWidgetControl;
+ }
+
+ if (m_videoOutput)
+ return m_videoOutput;
+ }
+
+ if (qstrcmp(name,QAudioEndpointSelector_iid) == 0)
+ return m_audioInputEndpointSelector;
+
+ if (qstrcmp(name,QVideoDeviceControl_iid) == 0)
+ return m_videoInputDevice;
+
+ if (qstrcmp(name,QMediaRecorderControl_iid) == 0)
+ return m_captureSession->recorderControl();
+
+ if (qstrcmp(name,QAudioEncoderControl_iid) == 0)
+ return m_captureSession->audioEncodeControl();
+
+ if (qstrcmp(name,QVideoEncoderControl_iid) == 0)
+ return m_captureSession->videoEncodeControl();
+
+ if (qstrcmp(name,QImageEncoderControl_iid) == 0)
+ return m_captureSession->imageEncodeControl();
+
+
+ if (qstrcmp(name,QMediaContainerControl_iid) == 0)
+ return m_captureSession->mediaContainerControl();
+
+ if (qstrcmp(name,QCameraControl_iid) == 0)
+ return m_cameraControl;
+
+ if (qstrcmp(name,QMetaDataWriterControl_iid) == 0)
+ return m_metaDataControl;
+
+ if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
+ return m_imageCaptureControl;
+
+ if (qstrcmp(name, QCameraExposureControl_iid) == 0)
+ return m_captureSession->cameraExposureControl();
+
+ if (qstrcmp(name, QCameraFlashControl_iid) == 0)
+ return m_captureSession->cameraFlashControl();
+
+ if (qstrcmp(name, QCameraFocusControl_iid) == 0)
+ return m_captureSession->cameraFocusControl();
+
+ if (qstrcmp(name, QCameraImageProcessingControl_iid) == 0)
+ return m_captureSession->imageProcessingControl();
+
+ if (qstrcmp(name, QCameraLocksControl_iid) == 0)
+ return m_captureSession->cameraLocksControl();
+
+ if (qstrcmp(name, QCameraCaptureDestinationControl_iid) == 0)
+ return m_captureSession->captureDestinationControl();
+
+ if (qstrcmp(name, QCameraCaptureBufferFormatControl_iid) == 0)
+ return m_captureSession->captureBufferFormatControl();
+
+ return 0;
+}
+
+void CameraBinService::releaseControl(QMediaControl *control)
+{
+ if (control && control == m_videoOutput) {
+ m_videoOutput = 0;
+ m_captureSession->setViewfinder(0);
+ }
+}
+
+bool CameraBinService::isCameraBinAvailable()
+{
+ GstElementFactory *factory = gst_element_factory_find("camerabin");
+ if (factory) {
+ gst_object_unref(GST_OBJECT(factory));
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabinservice.h b/src/plugins/gstreamer/camerabin/camerabinservice.h
new file mode 100644
index 000000000..11c5aeadf
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinservice.h
@@ -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$
+** 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 CAMERABINCAPTURESERVICE_H
+#define CAMERABINCAPTURESERVICE_H
+
+#include <qmediaservice.h>
+
+#include <gst/gst.h>
+QT_BEGIN_NAMESPACE
+class QAudioEndpointSelector;
+class QVideoDeviceControl;
+QT_END_NAMESPACE
+
+class CameraBinSession;
+class CameraBinControl;
+class QGstreamerMessage;
+class QGstreamerBusHelper;
+class QGstreamerVideoRenderer;
+class QGstreamerVideoOverlay;
+class QGstreamerVideoWidgetControl;
+class QGstreamerElementFactory;
+class CameraBinMetaData;
+class CameraBinImageCapture;
+class CameraBinMetaData;
+
+class CameraBinService : public QMediaService
+{
+ Q_OBJECT
+
+public:
+ CameraBinService(const QString &service, QObject *parent = 0);
+ virtual ~CameraBinService();
+
+ QMediaControl *requestControl(const char *name);
+ void releaseControl(QMediaControl *);
+
+ static bool isCameraBinAvailable();
+
+private:
+ void setAudioPreview(GstElement*);
+
+ CameraBinSession *m_captureSession;
+ CameraBinControl *m_cameraControl;
+ CameraBinMetaData *m_metaDataControl;
+
+ QAudioEndpointSelector *m_audioInputEndpointSelector;
+ QVideoDeviceControl *m_videoInputDevice;
+
+ QMediaControl *m_videoOutput;
+
+ QMediaControl *m_videoRenderer;
+ QMediaControl *m_videoWindow;
+ QGstreamerVideoWidgetControl *m_videoWidgetControl;
+ CameraBinImageCapture *m_imageCaptureControl;
+};
+
+#endif // CAMERABINCAPTURESERVICE_H
diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp
new file mode 100644
index 000000000..e84a5af24
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp
@@ -0,0 +1,1267 @@
+/****************************************************************************
+**
+** 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$
+** 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 "camerabinsession.h"
+#include "camerabinrecorder.h"
+#include "camerabincontainer.h"
+#include "camerabinaudioencoder.h"
+#include "camerabinvideoencoder.h"
+#include "camerabinimageencoder.h"
+#include "camerabinexposure.h"
+#include "camerabinflash.h"
+#include "camerabinfocus.h"
+#include "camerabinimageprocessing.h"
+#include "camerabinlocks.h"
+#include "camerabincapturedestination.h"
+#include "camerabincapturebufferformat.h"
+#include "qgstreamerbushelper.h"
+#include "qgstreamervideorendererinterface.h"
+#include <qmediarecorder.h>
+#include <gst/interfaces/photography.h>
+#include <gst/gsttagsetter.h>
+#include <gst/gstversion.h>
+
+#include <QtCore/qdebug.h>
+#include <QCoreApplication>
+#include <QtCore/qmetaobject.h>
+#include <QtGui/qdesktopservices.h>
+
+#include <QtGui/qimage.h>
+
+//#define CAMERABIN_DEBUG 1
+#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
+
+#ifdef Q_WS_MAEMO_5
+#define FILENAME_PROPERTY "filename"
+#define MODE_PROPERTY "mode"
+#define MUTE_PROPERTY "mute"
+#define ZOOM_PROPERTY "zoom"
+#define IMAGE_PP_PROPERTY "imagepp"
+#define IMAGE_ENCODER_PROPERTY "imageenc"
+#define VIDEO_PP_PROPERTY "videopp"
+#define VIDEO_ENCODER_PROPERTY "videoenc"
+#define AUDIO_ENCODER_PROPERTY "audioenc"
+#define VIDEO_MUXER_PROPERTY "videomux"
+#define VIEWFINDER_SINK_PROPERTY "vfsink"
+#define VIDEO_SOURCE_PROPERTY "videosrc"
+#define AUDIO_SOURCE_PROPERTY "audiosrc"
+#define VIDEO_SOURCE_CAPS_PROPERTY "inputcaps"
+#define FILTER_CAPS_PROPERTY "filter-caps"
+#define PREVIEW_CAPS_PROPERTY "preview-caps"
+
+#define IMAGE_DONE_SIGNAL "img-done"
+#define CAPTURE_START "user-start"
+#define CAPTURE_STOP "user-stop"
+#define CAPTURE_PAUSE "user-pause"
+#define SET_VIDEO_RESOLUTION_FPS "user-res-fps"
+#define SET_IMAGE_RESOLUTION "user-image-res"
+
+#else
+
+#define FILENAME_PROPERTY "filename"
+#define MODE_PROPERTY "mode"
+#define MUTE_PROPERTY "mute"
+#define ZOOM_PROPERTY "zoom"
+#define IMAGE_PP_PROPERTY "image-post-processing"
+#define IMAGE_ENCODER_PROPERTY "image-encoder"
+#define VIDEO_PP_PROPERTY "video-post-processing"
+#define VIDEO_ENCODER_PROPERTY "video-encoder"
+#define AUDIO_ENCODER_PROPERTY "audio-encoder"
+#define VIDEO_MUXER_PROPERTY "video-muxer"
+#define VIEWFINDER_SINK_PROPERTY "viewfinder-sink"
+#define VIDEO_SOURCE_PROPERTY "video-source"
+#define AUDIO_SOURCE_PROPERTY "audio-source"
+#define VIDEO_SOURCE_CAPS_PROPERTY "video-source-caps"
+#define FILTER_CAPS_PROPERTY "filter-caps"
+#define PREVIEW_CAPS_PROPERTY "preview-caps"
+
+#define IMAGE_DONE_SIGNAL "image-done"
+#define CAPTURE_START "capture-start"
+#define CAPTURE_STOP "capture-stop"
+#define CAPTURE_PAUSE "capture-pause"
+#define SET_VIDEO_RESOLUTION_FPS "set-video-resolution-fps"
+#define SET_IMAGE_RESOLUTION "set-image-resolution"
+#endif
+
+#define CAMERABIN_IMAGE_MODE 0
+#define CAMERABIN_VIDEO_MODE 1
+
+#define gstRef(element) { gst_object_ref(GST_OBJECT(element)); gst_object_sink(GST_OBJECT(element)); }
+#define gstUnref(element) { if (element) { gst_object_unref(GST_OBJECT(element)); element = 0; } }
+
+#define PREVIEW_CAPS_4_3 \
+ "video/x-raw-rgb, width = (int) 640, height = (int) 480"
+
+#define VIEWFINDER_RESOLUTION_4x3 QSize(640, 480)
+#define VIEWFINDER_RESOLUTION_3x2 QSize(720, 480)
+#define VIEWFINDER_RESOLUTION_16x9 QSize(800, 450)
+
+//using GST_STATE_READY for QCamera::LoadedState
+//doesn't work reliably at least with some webcams.
+#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
+#define USE_READY_STATE_ON_LOADED
+#endif
+
+CameraBinSession::CameraBinSession(QObject *parent)
+ :QObject(parent),
+ m_state(QCamera::UnloadedState),
+ m_pendingState(QCamera::UnloadedState),
+ m_recordingActive(false),
+ m_pendingResolutionUpdate(false),
+ m_muted(false),
+ m_busy(false),
+ m_captureMode(QCamera::CaptureStillImage),
+ m_audioInputFactory(0),
+ m_videoInputFactory(0),
+ m_viewfinder(0),
+ m_viewfinderInterface(0),
+ m_pipeline(0),
+ m_videoSrc(0),
+ m_viewfinderElement(0),
+ m_viewfinderHasChanged(true),
+ m_videoInputHasChanged(true),
+ m_sourceCaps(0),
+ m_audioSrc(0),
+ m_audioConvert(0),
+ m_capsFilter(0),
+ m_fileSink(0),
+ m_audioEncoder(0),
+ m_muxer(0)
+{
+ m_pipeline = gst_element_factory_make("camerabin", "camerabin");
+ g_signal_connect(G_OBJECT(m_pipeline), "notify::idle", G_CALLBACK(updateBusyStatus), this);
+
+ gstRef(m_pipeline);
+
+ m_bus = gst_element_get_bus(m_pipeline);
+
+ m_busHelper = new QGstreamerBusHelper(m_bus, this);
+ m_busHelper->installSyncEventFilter(this);
+ connect(m_busHelper, SIGNAL(message(QGstreamerMessage)), SLOT(handleBusMessage(QGstreamerMessage)));
+ m_audioEncodeControl = new CameraBinAudioEncoder(this);
+ m_videoEncodeControl = new CameraBinVideoEncoder(this);
+ m_imageEncodeControl = new CameraBinImageEncoder(this);
+ m_recorderControl = new CameraBinRecorder(this);
+ m_mediaContainerControl = new CameraBinContainer(this);
+ m_cameraExposureControl = new CameraBinExposure(this);
+ m_cameraFlashControl = new CameraBinFlash(this);
+ m_cameraFocusControl = new CameraBinFocus(this);
+ m_imageProcessingControl = new CameraBinImageProcessing(this);
+ m_cameraLocksControl = new CameraBinLocks(this);
+ m_captureDestinationControl = new CameraBinCaptureDestination(this);
+ m_captureBufferFormatControl = new CameraBinCaptureBufferFormat(this);
+}
+
+CameraBinSession::~CameraBinSession()
+{
+ if (m_pipeline) {
+ if (m_viewfinderInterface)
+ m_viewfinderInterface->stopRenderer();
+
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+ gst_element_get_state(m_pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
+ gstUnref(m_pipeline);
+ gstUnref(m_viewfinderElement);
+ }
+}
+
+GstPhotography *CameraBinSession::photography()
+{
+ if (GST_IS_PHOTOGRAPHY(m_pipeline)) {
+ return GST_PHOTOGRAPHY(m_pipeline);
+ }
+
+ if (!m_videoSrc) {
+ m_videoSrc = buildVideoSrc();
+
+ if (m_videoSrc)
+ g_object_set(m_pipeline, VIDEO_SOURCE_PROPERTY, m_videoSrc, NULL);
+ else
+ g_object_get(m_pipeline, VIDEO_SOURCE_PROPERTY, &m_videoSrc, NULL);
+
+ updateVideoSourceCaps();
+ m_videoInputHasChanged = false;
+ }
+
+ if (m_videoSrc && GST_IS_PHOTOGRAPHY(m_videoSrc))
+ return GST_PHOTOGRAPHY(m_videoSrc);
+
+ return 0;
+}
+
+CameraBinSession::CameraRole CameraBinSession::cameraRole() const
+{
+#ifdef Q_WS_MAEMO_5
+ return m_inputDevice == QLatin1String("/dev/video1") ?
+ FrontCamera : BackCamera;
+#endif
+
+ return BackCamera;
+}
+
+bool CameraBinSession::setupCameraBin()
+{
+ if (m_captureMode == QCamera::CaptureStillImage) {
+ g_object_set(m_pipeline, MODE_PROPERTY, CAMERABIN_IMAGE_MODE, NULL);
+ }
+
+ if (m_captureMode == QCamera::CaptureVideo) {
+ g_object_set(m_pipeline, MODE_PROPERTY, CAMERABIN_VIDEO_MODE, NULL);
+
+ if (!m_recorderControl->findCodecs())
+ return false;
+
+ g_object_set(m_pipeline, VIDEO_ENCODER_PROPERTY, m_videoEncodeControl->createEncoder(), NULL);
+ g_object_set(m_pipeline, AUDIO_ENCODER_PROPERTY, m_audioEncodeControl->createEncoder(), NULL);
+ g_object_set(m_pipeline, VIDEO_MUXER_PROPERTY,
+ gst_element_factory_make(m_mediaContainerControl->formatElementName().constData(), NULL), NULL);
+ }
+
+ if (m_videoInputHasChanged) {
+ m_videoSrc = buildVideoSrc();
+
+ if (m_videoSrc)
+ g_object_set(m_pipeline, VIDEO_SOURCE_PROPERTY, m_videoSrc, NULL);
+ else
+ g_object_get(m_pipeline, VIDEO_SOURCE_PROPERTY, &m_videoSrc, NULL);
+
+ updateVideoSourceCaps();
+ m_videoInputHasChanged = false;
+ }
+
+
+ if (m_viewfinderHasChanged) {
+ if (m_viewfinderElement)
+ gst_object_unref(GST_OBJECT(m_viewfinderElement));
+
+ m_viewfinderElement = m_viewfinderInterface ? m_viewfinderInterface->videoSink() : 0;
+#if CAMERABIN_DEBUG
+ qDebug() << Q_FUNC_INFO << "Viewfinder changed, reconfigure.";
+#endif
+ m_viewfinderHasChanged = false;
+ if (!m_viewfinderElement) {
+ qWarning() << "Staring camera without viewfinder available";
+ m_viewfinderElement = gst_element_factory_make("fakesink", NULL);
+ }
+ gst_object_ref(GST_OBJECT(m_viewfinderElement));
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+ g_object_set(G_OBJECT(m_pipeline), VIEWFINDER_SINK_PROPERTY, m_viewfinderElement, NULL);
+ }
+
+ GstCaps *previewCaps = gst_caps_from_string(PREVIEW_CAPS_4_3);
+ g_object_set(G_OBJECT(m_pipeline), PREVIEW_CAPS_PROPERTY, previewCaps, NULL);
+ gst_caps_unref(previewCaps);
+
+ return true;
+}
+
+void CameraBinSession::updateVideoSourceCaps()
+{
+ if (m_sourceCaps) {
+ gst_caps_unref(m_sourceCaps);
+ m_sourceCaps = 0;
+ }
+
+ g_object_get(G_OBJECT(m_pipeline), VIDEO_SOURCE_CAPS_PROPERTY, &m_sourceCaps, NULL);
+}
+
+void CameraBinSession::setupCaptureResolution()
+{
+ if (m_captureMode == QCamera::CaptureStillImage) {
+ QSize resolution = m_imageEncodeControl->imageSettings().resolution();
+
+ //by default select the maximum supported resolution
+ if (resolution.isEmpty()) {
+ updateVideoSourceCaps();
+ bool continuous = false;
+ QList<QSize> resolutions = supportedResolutions(qMakePair<int,int>(0,0),
+ &continuous,
+ QCamera::CaptureStillImage);
+ if (!resolutions.isEmpty())
+ resolution = resolutions.last();
+ }
+
+ QString previewCapsString = PREVIEW_CAPS_4_3;
+ QSize viewfinderResolution = VIEWFINDER_RESOLUTION_4x3;
+
+ if (!resolution.isEmpty()) {
+#if CAMERABIN_DEBUG
+ qDebug() << Q_FUNC_INFO << "set image resolution" << resolution;
+#endif
+ g_signal_emit_by_name(G_OBJECT(m_pipeline), SET_IMAGE_RESOLUTION, resolution.width(), resolution.height(), NULL);
+
+ previewCapsString = QString("video/x-raw-rgb, width = (int) %1, height = (int) 480")
+ .arg(resolution.width()*480/resolution.height());
+
+ if (!resolution.isEmpty()) {
+ qreal aspectRatio = qreal(resolution.width()) / resolution.height();
+ if (aspectRatio < 1.4)
+ viewfinderResolution = VIEWFINDER_RESOLUTION_4x3;
+ else if (aspectRatio > 1.7)
+ viewfinderResolution = VIEWFINDER_RESOLUTION_16x9;
+ else
+ viewfinderResolution = VIEWFINDER_RESOLUTION_3x2;
+ }
+ }
+
+ GstCaps *previewCaps = gst_caps_from_string(previewCapsString.toLatin1());
+ g_object_set(G_OBJECT(m_pipeline), PREVIEW_CAPS_PROPERTY, previewCaps, NULL);
+ gst_caps_unref(previewCaps);
+
+ //on low res cameras the viewfinder resolution should not be bigger
+ //then capture resolution
+ if (viewfinderResolution.width() > resolution.width())
+ viewfinderResolution = resolution;
+
+#if CAMERABIN_DEBUG
+ qDebug() << Q_FUNC_INFO << "set viewfinder resolution" << viewfinderResolution;
+#endif
+ g_signal_emit_by_name(G_OBJECT(m_pipeline),
+ SET_VIDEO_RESOLUTION_FPS,
+ viewfinderResolution.width(),
+ viewfinderResolution.height(),
+ 0, // maximum framerate
+ 1, // framerate denom
+ NULL);
+ }
+
+ if (m_captureMode == QCamera::CaptureVideo) {
+ QSize resolution = m_videoEncodeControl->videoSettings().resolution();
+ qreal framerate = m_videoEncodeControl->videoSettings().frameRate();
+
+ if (resolution.isEmpty()) {
+ //select the hightest supported resolution
+
+ updateVideoSourceCaps();
+ bool continuous = false;
+ QList<QSize> resolutions = supportedResolutions(qMakePair<int,int>(0,0),
+ &continuous,
+ QCamera::CaptureVideo);
+ if (!resolutions.isEmpty())
+ resolution = resolutions.last();
+ }
+
+ if (!resolution.isEmpty() || framerate > 0) {
+#if CAMERABIN_DEBUG
+ qDebug() << Q_FUNC_INFO << "set video resolution" << resolution;
+#endif
+ g_signal_emit_by_name(G_OBJECT(m_pipeline),
+ SET_VIDEO_RESOLUTION_FPS,
+ resolution.width(),
+ resolution.height(),
+ 0, //framerate nom == max rate
+ 1, // framerate denom == max rate
+ NULL);
+ }
+ }
+}
+
+GstElement *CameraBinSession::buildVideoSrc()
+{
+ GstElement *videoSrc = 0;
+ if (m_videoInputFactory) {
+ videoSrc = m_videoInputFactory->buildElement();
+ } else {
+ QList<QByteArray> candidates;
+ candidates << "subdevsrc"
+ << "v4l2camsrc"
+ << "v4l2src"
+ << "autovideosrc";
+ QByteArray sourceElementName;
+
+ foreach(sourceElementName, candidates) {
+ videoSrc = gst_element_factory_make(sourceElementName.constData(), "camera_source");
+ if (videoSrc)
+ break;
+ }
+
+ if (videoSrc && !m_inputDevice.isEmpty()) {
+#if CAMERABIN_DEBUG
+ qDebug() << "set camera device" << m_inputDevice;
+#endif
+ if (sourceElementName == "subdevsrc") {
+ if (m_inputDevice == QLatin1String("secondary"))
+ g_object_set(G_OBJECT(videoSrc), "camera-device", 1, NULL);
+ else
+ g_object_set(G_OBJECT(videoSrc), "camera-device", 0, NULL);
+ } else {
+ g_object_set(G_OBJECT(videoSrc), "device", m_inputDevice.toLocal8Bit().constData(), NULL);
+ }
+ }
+ }
+
+ return videoSrc;
+}
+
+void CameraBinSession::captureImage(int requestId, const QString &fileName)
+{
+ QString actualFileName = fileName;
+ if (actualFileName.isEmpty())
+ actualFileName = generateFileName("img_", defaultDir(QCamera::CaptureStillImage), "jpg");
+
+ m_requestId = requestId;
+
+ g_object_set(G_OBJECT(m_pipeline), FILENAME_PROPERTY, actualFileName.toLocal8Bit().constData(), NULL);
+
+ g_signal_emit_by_name(G_OBJECT(m_pipeline), CAPTURE_START, NULL);
+
+ m_imageFileName = actualFileName;
+}
+
+void CameraBinSession::setCaptureMode(QCamera::CaptureMode mode)
+{
+ m_captureMode = mode;
+
+ switch (m_captureMode) {
+ case QCamera::CaptureStillImage:
+ g_object_set(m_pipeline, MODE_PROPERTY, CAMERABIN_IMAGE_MODE, NULL);
+ break;
+ case QCamera::CaptureVideo:
+ g_object_set(m_pipeline, MODE_PROPERTY, CAMERABIN_VIDEO_MODE, NULL);
+ break;
+ }
+}
+
+QUrl CameraBinSession::outputLocation() const
+{
+ //return the location service wrote data to, not one set by user, it can be empty.
+ return m_actualSink;
+}
+
+bool CameraBinSession::setOutputLocation(const QUrl& sink)
+{
+ m_sink = m_actualSink = sink;
+ return true;
+}
+
+QDir CameraBinSession::defaultDir(QCamera::CaptureMode mode) const
+{
+ QStringList dirCandidates;
+
+#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
+ dirCandidates << QLatin1String("/home/user/MyDocs/DCIM");
+ dirCandidates << QLatin1String("/home/user/MyDocs/");
+#endif
+
+ if (mode == QCamera::CaptureVideo) {
+ dirCandidates << QDesktopServices::storageLocation(QDesktopServices::MoviesLocation);
+ dirCandidates << QDir::home().filePath("Documents/Video");
+ dirCandidates << QDir::home().filePath("Documents/Videos");
+ } else {
+ dirCandidates << QDesktopServices::storageLocation(QDesktopServices::PicturesLocation);
+ dirCandidates << QDir::home().filePath("Documents/Photo");
+ dirCandidates << QDir::home().filePath("Documents/Photos");
+ dirCandidates << QDir::home().filePath("Documents/photo");
+ dirCandidates << QDir::home().filePath("Documents/photos");
+ dirCandidates << QDir::home().filePath("Documents/Images");
+ }
+
+ dirCandidates << QDir::home().filePath("Documents");
+ dirCandidates << QDir::home().filePath("My Documents");
+ dirCandidates << QDir::homePath();
+ dirCandidates << QDir::currentPath();
+ dirCandidates << QDir::tempPath();
+
+ foreach (const QString &path, dirCandidates) {
+ if (QFileInfo(path).isWritable())
+ return QDir(path);
+ }
+
+ return QDir();
+}
+
+QString CameraBinSession::generateFileName(const QString &prefix, const QDir &dir, const QString &ext) const
+{
+ int lastClip = 0;
+ foreach(QString fileName, dir.entryList(QStringList() << QString("%1*.%2").arg(prefix).arg(ext))) {
+ int imgNumber = fileName.mid(prefix.length(), fileName.size()-prefix.length()-ext.length()-1).toInt();
+ lastClip = qMax(lastClip, imgNumber);
+ }
+
+ QString name = QString("%1%2.%3").arg(prefix)
+ .arg(lastClip+1,
+ 4, //fieldWidth
+ 10,
+ QLatin1Char('0'))
+ .arg(ext);
+
+ return dir.absoluteFilePath(name);
+}
+
+void CameraBinSession::setDevice(const QString &device)
+{
+ if (m_inputDevice != device) {
+ m_inputDevice = device;
+ m_videoInputHasChanged = true;
+ }
+}
+
+void CameraBinSession::setAudioInput(QGstreamerElementFactory *audioInput)
+{
+ m_audioInputFactory = audioInput;
+}
+
+void CameraBinSession::setVideoInput(QGstreamerElementFactory *videoInput)
+{
+ m_videoInputFactory = videoInput;
+ m_videoInputHasChanged = true;
+}
+
+bool CameraBinSession::isReady() const
+{
+ //it's possible to use QCamera without any viewfinder attached
+ return !m_viewfinderInterface || m_viewfinderInterface->isReady();
+}
+
+void CameraBinSession::setViewfinder(QObject *viewfinder)
+{
+ if (m_viewfinderInterface)
+ m_viewfinderInterface->stopRenderer();
+
+ m_viewfinderInterface = qobject_cast<QGstreamerVideoRendererInterface*>(viewfinder);
+ if (!m_viewfinderInterface)
+ viewfinder = 0;
+
+ if (m_viewfinder != viewfinder) {
+ bool oldReady = isReady();
+
+ if (m_viewfinder) {
+ disconnect(m_viewfinder, SIGNAL(sinkChanged()),
+ this, SLOT(handleViewfinderChange()));
+ disconnect(m_viewfinder, SIGNAL(readyChanged(bool)),
+ this, SIGNAL(readyChanged(bool)));
+ }
+
+ m_viewfinder = viewfinder;
+ m_viewfinderHasChanged = true;
+
+ if (m_viewfinder) {
+ connect(m_viewfinder, SIGNAL(sinkChanged()),
+ this, SLOT(handleViewfinderChange()));
+ connect(m_viewfinder, SIGNAL(readyChanged(bool)),
+ this, SIGNAL(readyChanged(bool)));
+ }
+
+ emit viewfinderChanged();
+ if (oldReady != isReady())
+ emit readyChanged(isReady());
+ }
+}
+
+void CameraBinSession::handleViewfinderChange()
+{
+ //the viewfinder will be reloaded
+ //shortly when the pipeline is started
+ m_viewfinderHasChanged = true;
+ emit viewfinderChanged();
+}
+
+QCamera::State CameraBinSession::state() const
+{
+ return m_state;
+}
+
+void CameraBinSession::setState(QCamera::State newState)
+{
+ if (newState == m_pendingState)
+ return;
+
+ m_pendingState = newState;
+
+#if CAMERABIN_DEBUG
+ qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", newState);
+#endif
+
+ switch (newState) {
+ case QCamera::UnloadedState:
+ if (m_recordingActive)
+ stopVideoRecording();
+
+ if (m_viewfinderInterface)
+ m_viewfinderInterface->stopRenderer();
+
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+ m_state = newState;
+ if (m_busy)
+ emit busyChanged(m_busy = false);
+
+ emit stateChanged(m_state);
+ break;
+ case QCamera::LoadedState:
+ if (m_recordingActive)
+ stopVideoRecording();
+
+ if (m_videoInputHasChanged) {
+ if (m_viewfinderInterface)
+ m_viewfinderInterface->stopRenderer();
+
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+ m_videoSrc = buildVideoSrc();
+ g_object_set(m_pipeline, VIDEO_SOURCE_PROPERTY, m_videoSrc, NULL);
+ updateVideoSourceCaps();
+ m_videoInputHasChanged = false;
+ }
+#ifdef USE_READY_STATE_ON_LOADED
+ gst_element_set_state(m_pipeline, GST_STATE_READY);
+#else
+ m_state = QCamera::LoadedState;
+ if (m_viewfinderInterface)
+ m_viewfinderInterface->stopRenderer();
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+ emit stateChanged(m_state);
+#endif
+ break;
+ case QCamera::ActiveState:
+ if (setupCameraBin()) {
+ GstState binState = GST_STATE_NULL;
+ GstState pending = GST_STATE_NULL;
+ gst_element_get_state(m_pipeline, &binState, &pending, 0);
+
+ if (pending == GST_STATE_VOID_PENDING && binState == GST_STATE_READY) {
+ m_pendingResolutionUpdate = false;
+ setupCaptureResolution();
+ gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
+ } else {
+ m_pendingResolutionUpdate = true;
+ gst_element_set_state(m_pipeline, GST_STATE_READY);
+ }
+ }
+ }
+}
+
+bool CameraBinSession::isBusy() const
+{
+ return m_busy;
+}
+
+void CameraBinSession::updateBusyStatus(GObject *o, GParamSpec *p, gpointer d)
+{
+ Q_UNUSED(p);
+ CameraBinSession *session = reinterpret_cast<CameraBinSession *>(d);
+
+ bool idle = false;
+ g_object_get(o, "idle", &idle, NULL);
+ bool busy = !idle;
+
+ if (session->m_busy != busy) {
+ session->m_busy = busy;
+ QMetaObject::invokeMethod(session, "busyChanged",
+ Qt::QueuedConnection,
+ Q_ARG(bool, busy));
+ }
+}
+
+qint64 CameraBinSession::duration() const
+{
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 duration = 0;
+
+ if ( m_pipeline && gst_element_query_position(m_pipeline, &format, &duration))
+ return duration / 1000000;
+ else
+ return 0;
+}
+
+bool CameraBinSession::isMuted() const
+{
+ return m_muted;
+}
+
+void CameraBinSession::setMuted(bool muted)
+{
+ if (m_muted != muted) {
+ m_muted = muted;
+
+ if (m_pipeline)
+ g_object_set(G_OBJECT(m_pipeline), MUTE_PROPERTY, m_muted, NULL);
+ emit mutedChanged(m_muted);
+ }
+}
+
+void CameraBinSession::setCaptureDevice(const QString &deviceName)
+{
+ m_captureDevice = deviceName;
+}
+
+void CameraBinSession::setMetaData(const QMap<QByteArray, QVariant> &data)
+{
+ m_metaData = data;
+
+ if (m_pipeline) {
+ GstIterator *elements = gst_bin_iterate_all_by_interface(GST_BIN(m_pipeline), GST_TYPE_TAG_SETTER);
+ GstElement *element = 0;
+ while (gst_iterator_next(elements, (void**)&element) == GST_ITERATOR_OK) {
+ QMapIterator<QByteArray, QVariant> it(data);
+ while (it.hasNext()) {
+ it.next();
+ const QString tagName = it.key();
+ const QVariant tagValue = it.value();
+
+ switch(tagValue.type()) {
+ case QVariant::String:
+ gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+ GST_TAG_MERGE_REPLACE_ALL,
+ tagName.toUtf8().constData(),
+ tagValue.toString().toUtf8().constData(),
+ NULL);
+ break;
+ case QVariant::Int:
+ case QVariant::LongLong:
+ gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+ GST_TAG_MERGE_REPLACE_ALL,
+ tagName.toUtf8().constData(),
+ tagValue.toInt(),
+ NULL);
+ break;
+ case QVariant::Double:
+ gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+ GST_TAG_MERGE_REPLACE_ALL,
+ tagName.toUtf8().constData(),
+ tagValue.toDouble(),
+ NULL);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+}
+
+bool CameraBinSession::processSyncMessage(const QGstreamerMessage &message)
+{
+ GstMessage* gm = message.rawMessage();
+ const GstStructure *st;
+ const GValue *image;
+ GstBuffer *buffer = NULL;
+
+ if (gm && GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) {
+ if (m_captureMode == QCamera::CaptureStillImage &&
+ gst_structure_has_name(gm->structure, "preview-image")) {
+ st = gst_message_get_structure(gm);
+ if (gst_structure_has_field_typed(st, "buffer", GST_TYPE_BUFFER)) {
+ image = gst_structure_get_value(st, "buffer");
+ if (image) {
+ buffer = gst_value_get_buffer(image);
+
+ QImage img;
+
+ GstCaps *caps = gst_buffer_get_caps(buffer);
+ if (caps) {
+ GstStructure *structure = gst_caps_get_structure(caps, 0);
+ gint width = 0;
+ gint height = 0;
+
+ if (structure &&
+ gst_structure_get_int(structure, "width", &width) &&
+ gst_structure_get_int(structure, "height", &height) &&
+ width > 0 && height > 0) {
+ if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) {
+ QImage::Format format = QImage::Format_Invalid;
+ int bpp = 0;
+ gst_structure_get_int(structure, "bpp", &bpp);
+
+ if (bpp == 24)
+ format = QImage::Format_RGB888;
+ else if (bpp == 32)
+ format = QImage::Format_RGB32;
+
+ if (format != QImage::Format_Invalid) {
+ img = QImage((const uchar *)buffer->data, width, height, format);
+ img.bits(); //detach
+ }
+ }
+ }
+ gst_caps_unref(caps);
+
+ static int exposedSignalIndex = metaObject()->indexOfSignal("imageExposed(int)");
+ metaObject()->method(exposedSignalIndex).invoke(this,
+ Qt::QueuedConnection,
+ Q_ARG(int,m_requestId));
+
+ static int signalIndex = metaObject()->indexOfSignal("imageCaptured(int,QImage)");
+ metaObject()->method(signalIndex).invoke(this,
+ Qt::QueuedConnection,
+ Q_ARG(int,m_requestId),
+ Q_ARG(QImage,img));
+ }
+
+ }
+ return true;
+ }
+ }
+
+ if (gst_structure_has_name(gm->structure, "prepare-xwindow-id")) {
+ if (m_viewfinderInterface)
+ m_viewfinderInterface->precessNewStream();
+
+ return true;
+ }
+
+ if (gst_structure_has_name(gm->structure, GST_PHOTOGRAPHY_AUTOFOCUS_DONE))
+ m_cameraFocusControl->handleFocusMessage(gm);
+
+ if (m_viewfinderInterface && GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_viewfinderElement))
+ m_viewfinderInterface->handleSyncMessage(gm);
+ }
+
+ return false;
+}
+
+void CameraBinSession::handleBusMessage(const QGstreamerMessage &message)
+{
+ GstMessage* gm = message.rawMessage();
+
+ if (gm) {
+ if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ERROR) {
+ GError *err;
+ gchar *debug;
+ gst_message_parse_error (gm, &err, &debug);
+
+ QString message;
+
+ if (err && err->message) {
+ message = QString::fromUtf8(err->message);
+ qWarning() << "CameraBin error:" << message;
+ }
+
+ //only report error messager from camerabin
+ if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_pipeline)) {
+ if (message.isEmpty())
+ message = tr("Camera error");
+
+ emit error(int(QMediaRecorder::ResourceError), message);
+ }
+
+ if (err)
+ g_error_free (err);
+
+ if (debug)
+ g_free (debug);
+ }
+
+ if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_WARNING) {
+ GError *err;
+ gchar *debug;
+ gst_message_parse_warning (gm, &err, &debug);
+
+ if (err && err->message)
+ qWarning() << "CameraBin warning:" << QString::fromUtf8(err->message);
+
+ if (err)
+ g_error_free (err);
+ if (debug)
+ g_free (debug);
+ }
+
+ if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_pipeline)) {
+ switch (GST_MESSAGE_TYPE(gm)) {
+ case GST_MESSAGE_DURATION:
+ break;
+
+ case GST_MESSAGE_STATE_CHANGED:
+ {
+
+ GstState oldState;
+ GstState newState;
+ GstState pending;
+
+ gst_message_parse_state_changed(gm, &oldState, &newState, &pending);
+
+
+#if CAMERABIN_DEBUG
+ QStringList states;
+ states << "GST_STATE_VOID_PENDING" << "GST_STATE_NULL" << "GST_STATE_READY" << "GST_STATE_PAUSED" << "GST_STATE_PLAYING";
+
+
+ qDebug() << QString("state changed: old: %1 new: %2 pending: %3") \
+ .arg(states[oldState]) \
+ .arg(states[newState]) \
+ .arg(states[pending]);
+#endif
+
+ switch (newState) {
+ case GST_STATE_VOID_PENDING:
+ case GST_STATE_NULL:
+ if (m_state != QCamera::UnloadedState)
+ emit stateChanged(m_state = QCamera::UnloadedState);
+ break;
+ case GST_STATE_READY:
+ if (m_pendingResolutionUpdate) {
+ m_pendingResolutionUpdate = false;
+ setupCaptureResolution();
+ gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
+ }
+ if (m_state != QCamera::LoadedState)
+ emit stateChanged(m_state = QCamera::LoadedState);
+ break;
+ case GST_STATE_PAUSED:
+ case GST_STATE_PLAYING:
+ emit stateChanged(m_state = QCamera::ActiveState);
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ //qDebug() << "New session state:" << ENUM_NAME(CameraBinSession,"State",m_state);
+ }
+
+ if (m_viewfinderInterface && GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_viewfinderElement))
+ m_viewfinderInterface->handleBusMessage(gm);
+
+ emit busMessage(message);
+ }
+}
+
+void CameraBinSession::recordVideo()
+{
+ m_recordingActive = true;
+ m_actualSink = m_sink;
+ if (m_actualSink.isEmpty()) {
+ QString ext = m_mediaContainerControl->containerMimeType();
+ m_actualSink = generateFileName("clip_", defaultDir(QCamera::CaptureVideo), ext);
+ }
+
+ g_object_set(G_OBJECT(m_pipeline), FILENAME_PROPERTY, m_actualSink.toEncoded().constData(), NULL);
+
+ g_signal_emit_by_name(G_OBJECT(m_pipeline), CAPTURE_START, NULL);
+}
+
+void CameraBinSession::resumeVideoRecording()
+{
+ m_recordingActive = true;
+ g_signal_emit_by_name(G_OBJECT(m_pipeline), CAPTURE_START, NULL);
+}
+
+
+void CameraBinSession::pauseVideoRecording()
+{
+ g_signal_emit_by_name(G_OBJECT(m_pipeline), CAPTURE_PAUSE, NULL);
+}
+
+void CameraBinSession::stopVideoRecording()
+{
+ m_recordingActive = false;
+ g_signal_emit_by_name(G_OBJECT(m_pipeline), CAPTURE_STOP, NULL);
+}
+
+//internal, only used by CameraBinSession::supportedFrameRates.
+//recursively fills the list of framerates res from value data.
+static void readValue(const GValue *value, QList< QPair<int,int> > *res, bool *continuous)
+{
+ if (GST_VALUE_HOLDS_FRACTION(value)) {
+ int num = gst_value_get_fraction_numerator(value);
+ int denum = gst_value_get_fraction_denominator(value);
+
+ *res << QPair<int,int>(num, denum);
+ } else if (GST_VALUE_HOLDS_FRACTION_RANGE(value)) {
+ const GValue *rateValueMin = gst_value_get_fraction_range_min(value);
+ const GValue *rateValueMax = gst_value_get_fraction_range_max(value);
+
+ if (continuous)
+ *continuous = true;
+
+ readValue(rateValueMin, res, continuous);
+ readValue(rateValueMax, res, continuous);
+ } else if (GST_VALUE_HOLDS_LIST(value)) {
+ for (uint i=0; i<gst_value_list_get_size(value); i++) {
+ readValue(gst_value_list_get_value(value, i), res, continuous);
+ }
+ }
+}
+
+static bool rateLessThan(const QPair<int,int> &r1, const QPair<int,int> &r2)
+{
+ return r1.first*r2.second < r2.first*r1.second;
+}
+
+QList< QPair<int,int> > CameraBinSession::supportedFrameRates(const QSize &frameSize, bool *continuous) const
+{
+ QList< QPair<int,int> > res;
+
+ if (!m_sourceCaps)
+ return res;
+
+ GstCaps *caps = 0;
+
+ if (frameSize.isEmpty()) {
+ caps = gst_caps_copy(m_sourceCaps);
+ } else {
+ GstCaps *filter = gst_caps_new_full(
+ gst_structure_new(
+ "video/x-raw-rgb",
+ "width" , G_TYPE_INT , frameSize.width(),
+ "height" , G_TYPE_INT, frameSize.height(), NULL),
+ gst_structure_new(
+ "video/x-raw-yuv",
+ "width" , G_TYPE_INT, frameSize.width(),
+ "height" , G_TYPE_INT, frameSize.height(), NULL),
+ gst_structure_new(
+ "image/jpeg",
+ "width" , G_TYPE_INT, frameSize.width(),
+ "height" , G_TYPE_INT, frameSize.height(), NULL),
+ NULL);
+
+ caps = gst_caps_intersect(m_sourceCaps, filter);
+ gst_caps_unref(filter);
+ }
+
+ //simplify to the list of rates only:
+ gst_caps_make_writable(caps);
+ for (uint i=0; i<gst_caps_get_size(caps); i++) {
+ GstStructure *structure = gst_caps_get_structure(caps, i);
+ gst_structure_set_name(structure, "video/x-raw-yuv");
+ const GValue *oldRate = gst_structure_get_value(structure, "framerate");
+ GValue rate;
+ memset(&rate, 0, sizeof(rate));
+ g_value_init(&rate, G_VALUE_TYPE(oldRate));
+ g_value_copy(oldRate, &rate);
+ gst_structure_remove_all_fields(structure);
+ gst_structure_set_value(structure, "framerate", &rate);
+ }
+ gst_caps_do_simplify(caps);
+
+
+ for (uint i=0; i<gst_caps_get_size(caps); i++) {
+ GstStructure *structure = gst_caps_get_structure(caps, i);
+ const GValue *rateValue = gst_structure_get_value(structure, "framerate");
+ readValue(rateValue, &res, continuous);
+ }
+
+ qSort(res.begin(), res.end(), rateLessThan);
+
+#if CAMERABIN_DEBUG
+ qDebug() << "Supported rates:" << gst_caps_to_string(caps);
+ qDebug() << res;
+#endif
+
+ gst_caps_unref(caps);
+
+ return res;
+}
+
+//internal, only used by CameraBinSession::supportedResolutions
+//recursively find the supported resolutions range.
+static QPair<int,int> valueRange(const GValue *value, bool *continuous)
+{
+ int minValue = 0;
+ int maxValue = 0;
+
+ if (g_value_type_compatible(G_VALUE_TYPE(value), G_TYPE_INT)) {
+ minValue = maxValue = g_value_get_int(value);
+ } else if (GST_VALUE_HOLDS_INT_RANGE(value)) {
+ minValue = gst_value_get_int_range_min(value);
+ maxValue = gst_value_get_int_range_max(value);
+ *continuous = true;
+ } else if (GST_VALUE_HOLDS_LIST(value)) {
+ for (uint i=0; i<gst_value_list_get_size(value); i++) {
+ QPair<int,int> res = valueRange(gst_value_list_get_value(value, i), continuous);
+
+ if (res.first > 0 && minValue > 0)
+ minValue = qMin(minValue, res.first);
+ else //select non 0 valid value
+ minValue = qMax(minValue, res.first);
+
+ maxValue = qMax(maxValue, res.second);
+ }
+ }
+
+ return QPair<int,int>(minValue, maxValue);
+}
+
+static bool resolutionLessThan(const QSize &r1, const QSize &r2)
+{
+ return r1.width()*r1.height() < r2.width()*r2.height();
+}
+
+
+QList<QSize> CameraBinSession::supportedResolutions(QPair<int,int> rate,
+ bool *continuous,
+ QCamera::CaptureMode mode) const
+{
+ QList<QSize> res;
+
+ if (continuous)
+ *continuous = false;
+
+ if (!m_sourceCaps)
+ return res;
+
+#if CAMERABIN_DEBUG
+ qDebug() << "Source caps:" << gst_caps_to_string(m_sourceCaps);
+#endif
+
+ GstCaps *caps = 0;
+ bool isContinuous = false;
+
+ if (rate.first <= 0 || rate.second <= 0) {
+ caps = gst_caps_copy(m_sourceCaps);
+ } else {
+ GstCaps *filter = gst_caps_new_full(
+ gst_structure_new(
+ "video/x-raw-rgb",
+ "framerate" , GST_TYPE_FRACTION , rate.first, rate.second, NULL),
+ gst_structure_new(
+ "video/x-raw-yuv",
+ "framerate" , GST_TYPE_FRACTION , rate.first, rate.second, NULL),
+ gst_structure_new(
+ "image/jpeg",
+ "framerate" , GST_TYPE_FRACTION , rate.first, rate.second, NULL),
+ NULL);
+
+ caps = gst_caps_intersect(m_sourceCaps, filter);
+ gst_caps_unref(filter);
+ }
+
+ //simplify to the list of resolutions only:
+ gst_caps_make_writable(caps);
+ for (uint i=0; i<gst_caps_get_size(caps); i++) {
+ GstStructure *structure = gst_caps_get_structure(caps, i);
+ gst_structure_set_name(structure, "video/x-raw-yuv");
+ const GValue *oldW = gst_structure_get_value(structure, "width");
+ const GValue *oldH = gst_structure_get_value(structure, "height");
+ GValue w;
+ memset(&w, 0, sizeof(GValue));
+ GValue h;
+ memset(&h, 0, sizeof(GValue));
+ g_value_init(&w, G_VALUE_TYPE(oldW));
+ g_value_init(&h, G_VALUE_TYPE(oldH));
+ g_value_copy(oldW, &w);
+ g_value_copy(oldH, &h);
+ gst_structure_remove_all_fields(structure);
+ gst_structure_set_value(structure, "width", &w);
+ gst_structure_set_value(structure, "height", &h);
+ }
+ gst_caps_do_simplify(caps);
+
+ for (uint i=0; i<gst_caps_get_size(caps); i++) {
+ GstStructure *structure = gst_caps_get_structure(caps, i);
+ const GValue *wValue = gst_structure_get_value(structure, "width");
+ const GValue *hValue = gst_structure_get_value(structure, "height");
+
+ QPair<int,int> wRange = valueRange(wValue, &isContinuous);
+ QPair<int,int> hRange = valueRange(hValue, &isContinuous);
+
+ QSize minSize(wRange.first, hRange.first);
+ QSize maxSize(wRange.second, hRange.second);
+
+ if (!minSize.isEmpty())
+ res << minSize;
+
+ if (minSize != maxSize && !maxSize.isEmpty())
+ res << maxSize;
+ }
+
+
+ qSort(res.begin(), res.end(), resolutionLessThan);
+
+ //if the range is continuos, populate is with the common rates
+ if (isContinuous && res.size() >= 2) {
+ //fill the ragne with common value
+ static QList<QSize> commonSizes =
+ QList<QSize>() << QSize(128, 96)
+ << QSize(160,120)
+ << QSize(176, 144)
+ << QSize(320, 240)
+ << QSize(352, 288)
+ << QSize(640, 480)
+ << QSize(848, 480)
+ << QSize(854, 480)
+ << QSize(1024, 768)
+ << QSize(1280, 720) // HD 720
+ << QSize(1280, 1024)
+ << QSize(1600, 1200)
+ << QSize(1920, 1080) // HD
+ << QSize(1920, 1200)
+ << QSize(2048, 1536)
+ << QSize(2560, 1600)
+ << QSize(2580, 1936);
+ QSize minSize = res.first();
+ QSize maxSize = res.last();
+
+#ifdef Q_WS_MAEMO_5
+ if (mode == QCamera::CaptureVideo && cameraRole() == BackCamera)
+ maxSize = QSize(848, 480);
+ if (mode == QCamera::CaptureStillImage)
+ minSize = QSize(640, 480);
+#elif defined(Q_WS_MAEMO_6)
+ if (cameraRole() == FrontCamera && maxSize.width() > 640)
+ maxSize = QSize(640, 480);
+ else if (mode == QCamera::CaptureVideo && maxSize.width() > 1280)
+ maxSize = QSize(1280, 720);
+#else
+ Q_UNUSED(mode);
+#endif
+
+ res.clear();
+
+ foreach (const QSize &candidate, commonSizes) {
+ int w = candidate.width();
+ int h = candidate.height();
+
+ if (w > maxSize.width() && h > maxSize.height())
+ break;
+
+ if (w >= minSize.width() && h >= minSize.height() &&
+ w <= maxSize.width() && h <= maxSize.height())
+ res << candidate;
+ }
+
+ if (res.isEmpty() || res.first() != minSize)
+ res.prepend(minSize);
+
+ if (res.last() != maxSize)
+ res.append(maxSize);
+ }
+
+#if CAMERABIN_DEBUG
+ qDebug() << "Supported resolutions:" << gst_caps_to_string(caps);
+ qDebug() << res;
+#endif
+
+ gst_caps_unref(caps);
+
+ if (continuous)
+ *continuous = isContinuous;
+
+ return res;
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.h b/src/plugins/gstreamer/camerabin/camerabinsession.h
new file mode 100644
index 000000000..9597ea873
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinsession.h
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** 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$
+** 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 CAMERABINCAPTURESESSION_MAEMO_H
+#define CAMERABINCAPTURESESSION_MAEMO_H
+
+#include <qmediarecordercontrol.h>
+
+#include <QtCore/qurl.h>
+#include <QtCore/qdir.h>
+
+#include <gst/gst.h>
+#include <gst/interfaces/photography.h>
+
+#include "qgstreamerbushelper.h"
+#include "qcamera.h"
+
+
+class QGstreamerMessage;
+class QGstreamerBusHelper;
+class CameraBinAudioEncoder;
+class CameraBinVideoEncoder;
+class CameraBinImageEncoder;
+class CameraBinRecorder;
+class CameraBinContainer;
+class CameraBinExposure;
+class CameraBinFlash;
+class CameraBinFocus;
+class CameraBinImageProcessing;
+class CameraBinLocks;
+class CameraBinCaptureDestination;
+class CameraBinCaptureBufferFormat;
+class QGstreamerVideoRendererInterface;
+
+class QGstreamerElementFactory
+{
+public:
+ virtual GstElement *buildElement() = 0;
+};
+
+class CameraBinSession : public QObject, public QGstreamerSyncEventFilter
+{
+ Q_OBJECT
+ Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged)
+public:
+ enum CameraRole {
+ FrontCamera, // Secondary camera
+ BackCamera // Main photo camera
+ };
+
+ CameraBinSession(QObject *parent);
+ ~CameraBinSession();
+
+ GstPhotography *photography();
+ GstElement *cameraBin() { return m_pipeline; }
+
+ CameraRole cameraRole() const;
+
+ QList< QPair<int,int> > supportedFrameRates(const QSize &frameSize, bool *continuous) const;
+ QList<QSize> supportedResolutions( QPair<int,int> rate, bool *continuous, QCamera::CaptureMode mode) const;
+
+ QCamera::CaptureMode captureMode() { return m_captureMode; }
+ void setCaptureMode(QCamera::CaptureMode mode);
+
+ QUrl outputLocation() const;
+ bool setOutputLocation(const QUrl& sink);
+
+ QDir defaultDir(QCamera::CaptureMode mode) const;
+ QString generateFileName(const QString &prefix, const QDir &dir, const QString &ext) const;
+
+ CameraBinAudioEncoder *audioEncodeControl() const { return m_audioEncodeControl; }
+ CameraBinVideoEncoder *videoEncodeControl() const { return m_videoEncodeControl; }
+ CameraBinImageEncoder *imageEncodeControl() const { return m_imageEncodeControl; }
+ CameraBinExposure *cameraExposureControl() const { return m_cameraExposureControl; }
+ CameraBinFlash *cameraFlashControl() const { return m_cameraFlashControl; }
+ CameraBinFocus *cameraFocusControl() const { return m_cameraFocusControl; }
+ CameraBinImageProcessing *imageProcessingControl() const { return m_imageProcessingControl; }
+ CameraBinLocks *cameraLocksControl() const { return m_cameraLocksControl; }
+ CameraBinCaptureDestination *captureDestinationControl() const { return m_captureDestinationControl; }
+ CameraBinCaptureBufferFormat *captureBufferFormatControl() const { return m_captureBufferFormatControl; }
+
+
+ CameraBinRecorder *recorderControl() const { return m_recorderControl; }
+ CameraBinContainer *mediaContainerControl() const { return m_mediaContainerControl; }
+
+ QGstreamerElementFactory *audioInput() const { return m_audioInputFactory; }
+ void setAudioInput(QGstreamerElementFactory *audioInput);
+
+ QGstreamerElementFactory *videoInput() const { return m_videoInputFactory; }
+ void setVideoInput(QGstreamerElementFactory *videoInput);
+ bool isReady() const;
+
+ QObject *viewfinder() const { return m_viewfinder; }
+ void setViewfinder(QObject *viewfinder);
+
+ void captureImage(int requestId, const QString &fileName);
+
+ QCamera::State state() const;
+ bool isBusy() const;
+
+ qint64 duration() const;
+
+ void recordVideo();
+ void pauseVideoRecording();
+ void resumeVideoRecording();
+ void stopVideoRecording();
+
+ bool isMuted() const;
+
+ bool processSyncMessage(const QGstreamerMessage &message);
+
+signals:
+ void stateChanged(QCamera::State state);
+ void durationChanged(qint64 duration);
+ void error(int error, const QString &errorString);
+ void imageExposed(int requestId);
+ void imageCaptured(int requestId, const QImage &img);
+ void mutedChanged(bool);
+ void viewfinderChanged();
+ void readyChanged(bool);
+ void busyChanged(bool);
+ void busMessage(const QGstreamerMessage &message);
+
+public slots:
+ void setDevice(const QString &device);
+ void setState(QCamera::State);
+ void setCaptureDevice(const QString &deviceName);
+ void setMetaData(const QMap<QByteArray, QVariant>&);
+ void setMuted(bool);
+
+private slots:
+ void handleBusMessage(const QGstreamerMessage &message);
+ void handleViewfinderChange();
+
+private:
+ bool setupCameraBin();
+ void setupCaptureResolution();
+ void updateVideoSourceCaps();
+ GstElement *buildVideoSrc();
+ static void updateBusyStatus(GObject *o, GParamSpec *p, gpointer d);
+
+ QUrl m_sink;
+ QUrl m_actualSink;
+ bool m_recordingActive;
+ QString m_captureDevice;
+ QCamera::State m_state;
+ QCamera::State m_pendingState;
+ QString m_inputDevice;
+ bool m_pendingResolutionUpdate;
+ bool m_muted;
+ bool m_busy;
+
+ QCamera::CaptureMode m_captureMode;
+ QMap<QByteArray, QVariant> m_metaData;
+
+ QGstreamerElementFactory *m_audioInputFactory;
+ QGstreamerElementFactory *m_videoInputFactory;
+ QObject *m_viewfinder;
+ QGstreamerVideoRendererInterface *m_viewfinderInterface;
+
+ CameraBinAudioEncoder *m_audioEncodeControl;
+ CameraBinVideoEncoder *m_videoEncodeControl;
+ CameraBinImageEncoder *m_imageEncodeControl;
+ CameraBinRecorder *m_recorderControl;
+ CameraBinContainer *m_mediaContainerControl;
+ CameraBinExposure *m_cameraExposureControl;
+ CameraBinFlash *m_cameraFlashControl;
+ CameraBinFocus *m_cameraFocusControl;
+ CameraBinImageProcessing *m_imageProcessingControl;
+ CameraBinLocks *m_cameraLocksControl;
+ CameraBinCaptureDestination *m_captureDestinationControl;
+ CameraBinCaptureBufferFormat *m_captureBufferFormatControl;
+
+ QGstreamerBusHelper *m_busHelper;
+ GstBus* m_bus;
+ GstElement *m_pipeline;
+ GstElement *m_videoSrc;
+ GstElement *m_viewfinderElement;
+ bool m_viewfinderHasChanged;
+ bool m_videoInputHasChanged;
+
+ GstCaps *m_sourceCaps;
+
+ GstElement *m_audioSrc;
+ GstElement *m_audioConvert;
+ GstElement *m_capsFilter;
+ GstElement *m_fileSink;
+ GstElement *m_audioEncoder;
+ GstElement *m_muxer;
+
+public:
+ QString m_imageFileName;
+ int m_requestId;
+};
+
+#endif // CAMERABINCAPTURESESSION_MAEMO_H
diff --git a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp
new file mode 100644
index 000000000..b1809abcb
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.cpp
@@ -0,0 +1,346 @@
+/****************************************************************************
+**
+** 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$
+** 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 "camerabinvideoencoder.h"
+#include "camerabinsession.h"
+#include "camerabincontainer.h"
+
+#include <QtCore/qdebug.h>
+
+CameraBinVideoEncoder::CameraBinVideoEncoder(CameraBinSession *session)
+ :QVideoEncoderControl(session), m_session(session)
+{
+ QList<QByteArray> codecCandidates;
+#if defined(Q_WS_MAEMO_5)
+ codecCandidates << "video/mpeg4" << "video/h264" << "video/h263" << "video/theora"
+ << "video/mpeg2" << "video/mpeg1" << "video/mjpeg" << "video/VP8" << "video/h261";
+
+ m_elementNames["video/h264"] = "dsph264enc";
+ m_elementNames["video/mpeg4"] = "dspmp4venc";
+ m_elementNames["video/h263"] = "dsph263enc";
+ m_elementNames["video/theora"] = "theoraenc";
+ m_elementNames["video/mpeg2"] = "ffenc_mpeg2video";
+ m_elementNames["video/mpeg1"] = "ffenc_mpeg1video";
+ m_elementNames["video/mjpeg"] = "ffenc_mjpeg";
+ m_elementNames["video/VP8"] = "vp8enc";
+ m_elementNames["video/h261"] = "ffenc_h261";
+
+ m_codecOptions["video/mpeg4"] = QStringList() << "mode" << "keyframe-interval";
+#elif defined(Q_WS_MAEMO_6)
+ codecCandidates << "video/mpeg4" << "video/h264" << "video/h263";
+
+ m_elementNames["video/h264"] = "dsph264enc";
+ m_elementNames["video/mpeg4"] = "dsphdmp4venc";
+ m_elementNames["video/h263"] = "dsph263enc";
+
+ QStringList options = QStringList() << "mode" << "keyframe-interval" << "max-bitrate" << "intra-refresh";
+ m_codecOptions["video/h264"] = options;
+ m_codecOptions["video/mpeg4"] = options;
+ m_codecOptions["video/h263"] = options;
+#else
+ codecCandidates << "video/h264" << "video/xvid" << "video/mpeg4"
+ << "video/mpeg1" << "video/mpeg2" << "video/theora"
+ << "video/VP8" << "video/h261" << "video/mjpeg";
+
+ m_elementNames["video/h264"] = "x264enc";
+ m_elementNames["video/xvid"] = "xvidenc";
+ m_elementNames["video/mpeg4"] = "ffenc_mpeg4";
+ m_elementNames["video/mpeg1"] = "ffenc_mpeg1video";
+ m_elementNames["video/mpeg2"] = "ffenc_mpeg2video";
+ m_elementNames["video/theora"] = "theoraenc";
+ m_elementNames["video/mjpeg"] = "ffenc_mjpeg";
+ m_elementNames["video/VP8"] = "vp8enc";
+ m_elementNames["video/h261"] = "ffenc_h261";
+
+ m_codecOptions["video/h264"] = QStringList() << "quantizer";
+ m_codecOptions["video/xvid"] = QStringList() << "quantizer" << "profile";
+ m_codecOptions["video/mpeg4"] = QStringList() << "quantizer";
+ m_codecOptions["video/mpeg1"] = QStringList() << "quantizer";
+ m_codecOptions["video/mpeg2"] = QStringList() << "quantizer";
+ m_codecOptions["video/theora"] = QStringList();
+
+#endif
+
+ foreach( const QByteArray& codecName, codecCandidates ) {
+ QByteArray elementName = m_elementNames[codecName];
+ GstElementFactory *factory = gst_element_factory_find(elementName.constData());
+ if (factory) {
+ m_codecs.append(codecName);
+ const gchar *descr = gst_element_factory_get_description(factory);
+ m_codecDescriptions.insert(codecName, QString::fromUtf8(descr));
+
+ m_streamTypes.insert(codecName,
+ CameraBinContainer::supportedStreamTypes(factory, GST_PAD_SRC));
+
+ gst_object_unref(GST_OBJECT(factory));
+ }
+ }
+}
+
+CameraBinVideoEncoder::~CameraBinVideoEncoder()
+{
+}
+
+QList<QSize> CameraBinVideoEncoder::supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous) const
+{
+ if (continuous)
+ *continuous = false;
+
+ QPair<int,int> rate = rateAsRational(settings.frameRate());
+
+ //select the closest supported rational rate to settings.frameRate()
+
+ return m_session->supportedResolutions(rate, continuous, QCamera::CaptureVideo);
+}
+
+QList< qreal > CameraBinVideoEncoder::supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const
+{
+ if (continuous)
+ *continuous = false;
+
+ QList< qreal > res;
+ QPair<int,int> rate;
+
+ foreach(rate, m_session->supportedFrameRates(settings.resolution(), continuous)) {
+ if (rate.second > 0)
+ res << qreal(rate.first)/rate.second;
+ }
+
+ return res;
+}
+
+QStringList CameraBinVideoEncoder::supportedVideoCodecs() const
+{
+ return m_codecs;
+}
+
+QString CameraBinVideoEncoder::videoCodecDescription(const QString &codecName) const
+{
+ return m_codecDescriptions.value(codecName);
+}
+
+QStringList CameraBinVideoEncoder::supportedEncodingOptions(const QString &codec) const
+{
+ return m_codecOptions.value(codec);
+}
+
+QVariant CameraBinVideoEncoder::encodingOption(const QString &codec, const QString &name) const
+{
+ return m_options[codec].value(name);
+}
+
+void CameraBinVideoEncoder::setEncodingOption(
+ const QString &codec, const QString &name, const QVariant &value)
+{
+ m_options[codec][name] = value;
+}
+
+QVideoEncoderSettings CameraBinVideoEncoder::videoSettings() const
+{
+ return m_videoSettings;
+}
+
+void CameraBinVideoEncoder::setVideoSettings(const QVideoEncoderSettings &settings)
+{
+ m_videoSettings = settings;
+ m_userSettings = settings;
+ emit settingsChanged();
+}
+
+void CameraBinVideoEncoder::setActualVideoSettings(const QVideoEncoderSettings &settings)
+{
+ m_videoSettings = settings;
+}
+
+void CameraBinVideoEncoder::resetActualSettings()
+{
+ m_videoSettings = m_userSettings;
+}
+
+GstElement *CameraBinVideoEncoder::createEncoder()
+{
+ QString codec = m_videoSettings.codec();
+ QByteArray elementName = m_elementNames.value(codec);
+
+ GstElement *encoderElement = gst_element_factory_make( elementName.constData(), "video-encoder");
+
+ if (encoderElement) {
+ if (m_videoSettings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
+ QtMultimediaKit::EncodingQuality qualityValue = m_videoSettings.quality();
+
+ if (elementName == "x264enc") {
+ //constant quantizer mode
+ g_object_set(G_OBJECT(encoderElement), "pass", 4, NULL);
+ int qualityTable[] = {
+ 50, //VeryLow
+ 35, //Low
+ 21, //Normal
+ 15, //High
+ 8 //VeryHigh
+ };
+ g_object_set(G_OBJECT(encoderElement), "quantizer", qualityTable[qualityValue], NULL);
+ } else if (elementName == "xvidenc") {
+ //constant quantizer mode
+ g_object_set(G_OBJECT(encoderElement), "pass", 3, NULL);
+ int qualityTable[] = {
+ 32, //VeryLow
+ 12, //Low
+ 5, //Normal
+ 3, //High
+ 2 //VeryHigh
+ };
+ int quant = qualityTable[qualityValue];
+ g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL);
+ } else if (elementName == "ffenc_mpeg4" ||
+ elementName == "ffenc_mpeg1video" ||
+ elementName == "ffenc_mpeg2video" ) {
+ //constant quantizer mode
+ g_object_set(G_OBJECT(encoderElement), "pass", 2, NULL);
+ //quant from 1 to 30, default ~3
+ double qualityTable[] = {
+ 20, //VeryLow
+ 8.0, //Low
+ 3.0, //Normal
+ 2.5, //High
+ 2.0 //VeryHigh
+ };
+ double quant = qualityTable[qualityValue];
+ g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL);
+ } else if (elementName == "theoraenc") {
+ int qualityTable[] = {
+ 8, //VeryLow
+ 16, //Low
+ 32, //Normal
+ 45, //High
+ 60 //VeryHigh
+ };
+ //quality from 0 to 63
+ int quality = qualityTable[qualityValue];
+ g_object_set(G_OBJECT(encoderElement), "quality", quality, NULL);
+ } else if (elementName == "dsph264enc" ||
+ elementName == "dspmp4venc" ||
+ elementName == "dsphdmp4venc" ||
+ elementName == "dsph263enc") {
+ //only bitrate parameter is supported
+ int qualityTable[] = {
+ 1000000, //VeryLow
+ 2000000, //Low
+ 4000000, //Normal
+ 8000000, //High
+ 16000000 //VeryHigh
+ };
+ int bitrate = qualityTable[qualityValue];
+ g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
+ }
+ } else {
+ int bitrate = m_videoSettings.bitRate();
+ if (bitrate > 0) {
+ g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
+ }
+ }
+
+ QMap<QString,QVariant> options = m_options.value(codec);
+ QMapIterator<QString,QVariant> it(options);
+ while (it.hasNext()) {
+ it.next();
+ QString option = it.key();
+ QVariant value = it.value();
+
+ switch (value.type()) {
+ case QVariant::Int:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toInt(), NULL);
+ break;
+ case QVariant::Bool:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toBool(), NULL);
+ break;
+ case QVariant::Double:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toDouble(), NULL);
+ break;
+ case QVariant::String:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toString().toUtf8().constData(), NULL);
+ break;
+ default:
+ qWarning() << "unsupported option type:" << option << value;
+ break;
+ }
+
+ }
+ }
+
+ return encoderElement;
+}
+
+QPair<int,int> CameraBinVideoEncoder::rateAsRational(qreal frameRate) const
+{
+ if (frameRate > 0.001) {
+ //convert to rational number
+ QList<int> denumCandidates;
+ denumCandidates << 1 << 2 << 3 << 5 << 10 << 25 << 30 << 50 << 100 << 1001 << 1000;
+
+ qreal error = 1.0;
+ int num = 1;
+ int denum = 1;
+
+ foreach (int curDenum, denumCandidates) {
+ int curNum = qRound(frameRate*curDenum);
+ qreal curError = qAbs(qreal(curNum)/curDenum - frameRate);
+
+ if (curError < error) {
+ error = curError;
+ num = curNum;
+ denum = curDenum;
+ }
+
+ if (curError < 1e-8)
+ break;
+ }
+
+ return QPair<int,int>(num,denum);
+ }
+
+ return QPair<int,int>();
+}
+
+
+QSet<QString> CameraBinVideoEncoder::supportedStreamTypes(const QString &codecName) const
+{
+ return m_streamTypes.value(codecName);
+}
diff --git a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h
new file mode 100644
index 000000000..0dd9ffbad
--- /dev/null
+++ b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h
@@ -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$
+** 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 CAMERABINVIDEOENCODE_H
+#define CAMERABINVIDEOENCODE_H
+
+#include <qvideoencodercontrol.h>
+class CameraBinSession;
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qset.h>
+
+#include <gst/gst.h>
+
+QT_USE_NAMESPACE
+
+class CameraBinVideoEncoder : public QVideoEncoderControl
+{
+ Q_OBJECT
+public:
+ CameraBinVideoEncoder(CameraBinSession *session);
+ virtual ~CameraBinVideoEncoder();
+
+ QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings = QVideoEncoderSettings(),
+ bool *continuous = 0) const;
+
+ QList< qreal > supportedFrameRates(const QVideoEncoderSettings &settings = QVideoEncoderSettings(),
+ bool *continuous = 0) const;
+
+ QPair<int,int> rateAsRational(qreal) const;
+
+ QStringList supportedVideoCodecs() const;
+ QString videoCodecDescription(const QString &codecName) const;
+
+ QVideoEncoderSettings videoSettings() const;
+ void setVideoSettings(const QVideoEncoderSettings &settings);
+
+ QStringList supportedEncodingOptions(const QString &codec) const;
+ QVariant encodingOption(const QString &codec, const QString &name) const;
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
+
+ GstElement *createEncoder();
+
+ QSet<QString> supportedStreamTypes(const QString &codecName) const;
+
+ void setActualVideoSettings(const QVideoEncoderSettings&);
+ void resetActualSettings();
+
+Q_SIGNALS:
+ void settingsChanged();
+
+private:
+ CameraBinSession *m_session;
+
+ QStringList m_codecs;
+ QMap<QString,QString> m_codecDescriptions;
+ QMap<QString,QByteArray> m_elementNames;
+ QMap<QString,QStringList> m_codecOptions;
+
+ QVideoEncoderSettings m_videoSettings; // backend selected settings, using m_userSettings
+ QVideoEncoderSettings m_userSettings;
+
+ QMap<QString, QMap<QString, QVariant> > m_options;
+ QMap<QString, QSet<QString> > m_streamTypes;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/camerabuttonlistener_maemo.cpp b/src/plugins/gstreamer/camerabuttonlistener_maemo.cpp
new file mode 100644
index 000000000..c10156d7a
--- /dev/null
+++ b/src/plugins/gstreamer/camerabuttonlistener_maemo.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** 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 "camerabuttonlistener_maemo.h"
+
+#include <QtDBus/qdbusconnection.h>
+#include <QtDBus/qdbusinterface.h>
+
+#include <QtGui/qapplication.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qwidget.h>
+
+
+CameraButtonListener::CameraButtonListener(QObject *parent) :
+ QObject(parent),
+ m_focusPressed(false),
+ m_shutterPressed(false)
+{
+ QDBusConnection::systemBus().connect(
+ QString(),
+ "/org/freedesktop/Hal/devices/platform_cam_launch",
+ "org.freedesktop.Hal.Device",
+ "PropertyModified",
+ this,
+ SLOT(updateShuterButtonState()));
+
+ QDBusConnection::systemBus().connect(
+ QString(),
+ "/org/freedesktop/Hal/devices/platform_cam_focus",
+ "org.freedesktop.Hal.Device",
+ "PropertyModified",
+ this,
+ SLOT(updateFocusButtonState()));
+}
+
+
+CameraButtonListener::~CameraButtonListener()
+{
+}
+
+void CameraButtonListener::updateFocusButtonState()
+{
+ QDBusInterface propertyInterface("org.freedesktop.Hal",
+ "/org/freedesktop/Hal/devices/platform_cam_focus",
+ "org.freedesktop.Hal.Device",
+ QDBusConnection::systemBus());
+
+ bool pressed = propertyInterface.call("GetProperty", "button.state.value").arguments().at(0).toBool();
+
+ if (m_focusPressed != pressed) {
+ m_focusPressed = pressed;
+ QWidget *window = QApplication::focusWidget();
+
+ if (window) {
+ QApplication::postEvent(window,
+ new QKeyEvent(pressed ? QEvent::KeyPress : QEvent::KeyRelease,
+ 0x01100021, //Qt::Key_CameraFocus since Qt 4.7.0
+ Qt::NoModifier));
+ }
+ }
+}
+
+void CameraButtonListener::updateShuterButtonState()
+{
+ QDBusInterface propertyInterface("org.freedesktop.Hal",
+ "/org/freedesktop/Hal/devices/platform_cam_launch",
+ "org.freedesktop.Hal.Device",
+ QDBusConnection::systemBus());
+
+ bool pressed = propertyInterface.call("GetProperty", "button.state.value").arguments().at(0).toBool();
+
+ if (m_shutterPressed != pressed) {
+ m_shutterPressed = pressed;
+ QWidget *window = QApplication::focusWidget();
+
+ if (window) {
+ QApplication::postEvent(window,
+ new QKeyEvent(pressed ? QEvent::KeyPress : QEvent::KeyRelease,
+ 0x01100020, //Qt::Key_Camera since Qt 4.7.0
+ Qt::NoModifier));
+ }
+ }
+}
diff --git a/src/plugins/gstreamer/camerabuttonlistener_maemo.h b/src/plugins/gstreamer/camerabuttonlistener_maemo.h
new file mode 100644
index 000000000..a4d0153ad
--- /dev/null
+++ b/src/plugins/gstreamer/camerabuttonlistener_maemo.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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 CAMERABUTTONLISTENER_MAEMO_H
+#define CAMERABUTTONLISTENER_MAEMO_H
+
+#include <QObject>
+
+class CameraButtonListener : public QObject
+{
+ Q_OBJECT
+public:
+ CameraButtonListener(QObject *parent = 0);
+ virtual ~CameraButtonListener();
+
+private slots:
+ void updateFocusButtonState();
+ void updateShuterButtonState();
+
+private:
+ bool m_focusPressed;
+ bool m_shutterPressed;
+};
+
+#endif // CAMERABUTTONLISTENER_MAEMO_H
diff --git a/src/plugins/gstreamer/camerabuttonlistener_meego.cpp b/src/plugins/gstreamer/camerabuttonlistener_meego.cpp
new file mode 100644
index 000000000..8be24ba2a
--- /dev/null
+++ b/src/plugins/gstreamer/camerabuttonlistener_meego.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** 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 "camerabuttonlistener_meego.h"
+
+#include <QtGui/qapplication.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qwidget.h>
+#include <QtCore/qdebug.h>
+
+CameraButtonListener::CameraButtonListener(QObject *parent) :
+ QObject(parent),
+ m_focusPressed(false),
+ m_shutterPressed(false)
+{
+ m_keys = new MeeGo::QmKeys(this);
+ connect(m_keys, SIGNAL(keyEvent(MeeGo::QmKeys::Key, MeeGo::QmKeys::State)),
+ this, SLOT(handleQmKeyEvent(MeeGo::QmKeys::Key,MeeGo::QmKeys::State)));
+}
+
+CameraButtonListener::~CameraButtonListener()
+{
+}
+
+void CameraButtonListener::handleQmKeyEvent(MeeGo::QmKeys::Key key, MeeGo::QmKeys::State state)
+{
+ if (key == MeeGo::QmKeys::Camera) {
+ QWidget *window = QApplication::focusWidget();
+
+ bool focusPressed = (state == MeeGo::QmKeys::KeyHalfDown) ||
+ (state == MeeGo::QmKeys::KeyDown);
+
+ if (m_focusPressed != focusPressed) {
+ m_focusPressed = focusPressed;
+ if (window) {
+ QApplication::postEvent(window,
+ new QKeyEvent(focusPressed ? QEvent::KeyPress : QEvent::KeyRelease,
+ Qt::Key_CameraFocus,
+ Qt::NoModifier));
+ }
+ }
+
+ bool shutterPressed = (state == MeeGo::QmKeys::KeyDown);
+ if (m_shutterPressed != shutterPressed) {
+ m_shutterPressed = shutterPressed;
+ if (window) {
+ QApplication::postEvent(window,
+ new QKeyEvent(shutterPressed ? QEvent::KeyPress : QEvent::KeyRelease,
+ Qt::Key_Camera,
+ Qt::NoModifier));
+ }
+ }
+ }
+}
diff --git a/src/plugins/gstreamer/camerabuttonlistener_meego.h b/src/plugins/gstreamer/camerabuttonlistener_meego.h
new file mode 100644
index 000000000..88ca26788
--- /dev/null
+++ b/src/plugins/gstreamer/camerabuttonlistener_meego.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** 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 CAMERABUTTONLISTENER_MEEGO_H
+#define CAMERABUTTONLISTENER_MEEGO_H
+
+#include <QtCore/qobject.h>
+#include <qmsystem2/qmkeys.h>
+
+class CameraButtonListener : public QObject
+{
+ Q_OBJECT
+public:
+ CameraButtonListener(QObject *parent = 0);
+ ~CameraButtonListener();
+
+private slots:
+ void handleQmKeyEvent(MeeGo::QmKeys::Key key, MeeGo::QmKeys::State state);
+
+private:
+ MeeGo::QmKeys *m_keys;
+ bool m_focusPressed;
+ bool m_shutterPressed;
+};
+
+#endif // CAMERABUTTONLISTENER_MEEGO_H
diff --git a/src/plugins/gstreamer/gstreamer.pro b/src/plugins/gstreamer/gstreamer.pro
new file mode 100644
index 000000000..681fac4e2
--- /dev/null
+++ b/src/plugins/gstreamer/gstreamer.pro
@@ -0,0 +1,101 @@
+
+load(qt_module)
+
+TARGET = qgstengine
+QT += multimediakit-private network
+PLUGIN_TYPE=mediaservice
+
+load(qt_plugin)
+DESTDIR = $$QT.multimediakit.plugins/$${PLUGIN_TYPE}
+
+unix:contains(QT_CONFIG, alsa) {
+DEFINES += HAVE_ALSA
+LIBS += \
+ -lasound
+}
+
+CONFIG += link_pkgconfig
+
+PKGCONFIG += \
+ gstreamer-0.10 \
+ gstreamer-base-0.10 \
+ gstreamer-interfaces-0.10 \
+ gstreamer-audio-0.10 \
+ gstreamer-video-0.10
+
+maemo*:PKGCONFIG +=gstreamer-plugins-bad-0.10
+contains(gstreamer-appsrc_enabled, yes): PKGCONFIG += gstreamer-app-0.10
+
+maemo5 {
+ HEADERS += camerabuttonlistener_maemo.h
+ SOURCES += camerabuttonlistener_maemo.cpp
+
+ QT += dbus
+}
+
+maemo6 {
+ HEADERS += camerabuttonlistener_meego.h
+ SOURCES += camerabuttonlistener_meego.cpp
+
+ PKGCONFIG += qmsystem2 libresourceqt1
+
+ isEqual(QT_ARCH,armv6) {
+ HEADERS += qgstreamergltexturerenderer.h
+ SOURCES += qgstreamergltexturerenderer.cpp
+ QT += opengl
+ LIBS += -lEGL -lgstmeegointerfaces-0.10
+ }
+}
+
+# Input
+HEADERS += \
+ qgstreamermessage.h \
+ qgstreamerbushelper.h \
+ qgstreamervideorendererinterface.h \
+ qgstreamerserviceplugin.h \
+ qgstreameraudioinputendpointselector.h \
+ qgstreamervideorenderer.h \
+ qgstvideobuffer.h \
+ qvideosurfacegstsink.h \
+ qgstreamervideoinputdevicecontrol.h \
+ gstvideoconnector.h \
+ qabstractgstbufferpool.h \
+ qgstutils.h
+
+SOURCES += \
+ qgstreamermessage.cpp \
+ qgstreamerbushelper.cpp \
+ qgstreamervideorendererinterface.cpp \
+ qgstreamerserviceplugin.cpp \
+ qgstreameraudioinputendpointselector.cpp \
+ qgstreamervideorenderer.cpp \
+ qgstvideobuffer.cpp \
+ qvideosurfacegstsink.cpp \
+ qgstreamervideoinputdevicecontrol.cpp \
+ gstvideoconnector.c \
+ qgstutils.cpp
+
+
+!win32:!contains(QT_CONFIG,embedded):!mac:!symbian:!simulator:!contains(QT_CONFIG, qpa) {
+ LIBS += -lXv -lX11 -lXext
+
+ HEADERS += \
+ qgstreamervideooverlay.h \
+ qgstreamervideowindow.h \
+ qgstreamervideowidget.h \
+ qx11videosurface.h \
+ qgstxvimagebuffer.h
+
+ SOURCES += \
+ qgstreamervideooverlay.cpp \
+ qgstreamervideowindow.cpp \
+ qgstreamervideowidget.cpp \
+ qx11videosurface.cpp \
+ qgstxvimagebuffer.cpp
+}
+include(mediaplayer/mediaplayer.pri)
+include(mediacapture/mediacapture.pri)
+
+contains(gstreamer-photography_enabled, yes) {
+ include(camerabin/camerabin.pri)
+}
diff --git a/src/plugins/gstreamer/gstvideoconnector.c b/src/plugins/gstreamer/gstvideoconnector.c
new file mode 100644
index 000000000..55570873e
--- /dev/null
+++ b/src/plugins/gstreamer/gstvideoconnector.c
@@ -0,0 +1,421 @@
+/****************************************************************************
+**
+** 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$
+** 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 "gstvideoconnector.h"
+
+/* signals */
+enum
+{
+ SIGNAL_RESEND_NEW_SEGMENT,
+ SIGNAL_CONNECTION_FAILED,
+ LAST_SIGNAL
+};
+static guint gst_video_connector_signals[LAST_SIGNAL] = { 0 };
+
+
+GST_DEBUG_CATEGORY_STATIC (video_connector_debug);
+#define GST_CAT_DEFAULT video_connector_debug
+
+static GstStaticPadTemplate gst_video_connector_sink_factory =
+GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate gst_video_connector_src_factory =
+GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+#define _do_init(bla) \
+ GST_DEBUG_CATEGORY_INIT (video_connector_debug, \
+ "video-connector", 0, "An identity like element for reconnecting video stream");
+
+GST_BOILERPLATE_FULL (GstVideoConnector, gst_video_connector, GstElement,
+ GST_TYPE_ELEMENT, _do_init);
+
+static void gst_video_connector_dispose (GObject * object);
+static GstFlowReturn gst_video_connector_chain (GstPad * pad, GstBuffer * buf);
+static GstFlowReturn gst_video_connector_buffer_alloc (GstPad * pad,
+ guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
+static GstStateChangeReturn gst_video_connector_change_state (GstElement *
+ element, GstStateChange transition);
+static gboolean gst_video_connector_handle_sink_event (GstPad * pad,
+ GstEvent * event);
+static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer *buffer, guint * object);
+static void gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal);
+static gboolean gst_video_connector_setcaps (GstPad *pad, GstCaps *caps);
+static GstCaps *gst_video_connector_getcaps (GstPad * pad);
+static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps);
+
+static void
+gst_video_connector_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_set_details_simple (element_class, "Video Connector",
+ "Generic",
+ "An identity like element used for reconnecting video stream",
+ "Dmytro Poplavskiy <dmytro.poplavskiy@nokia.com>");
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_video_connector_sink_factory));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_video_connector_src_factory));
+}
+
+static void
+gst_video_connector_class_init (GstVideoConnectorClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->dispose = gst_video_connector_dispose;
+ gstelement_class->change_state = gst_video_connector_change_state;
+ klass->resend_new_segment = gst_video_connector_resend_new_segment;
+
+ gst_video_connector_signals[SIGNAL_RESEND_NEW_SEGMENT] =
+ g_signal_new ("resend-new-segment", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GstVideoConnectorClass, resend_new_segment), NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+ gst_video_connector_signals[SIGNAL_CONNECTION_FAILED] =
+ g_signal_new ("connection-failed", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+}
+
+static void
+gst_video_connector_init (GstVideoConnector *element,
+ GstVideoConnectorClass *g_class)
+{
+ element->sinkpad =
+ gst_pad_new_from_static_template (&gst_video_connector_sink_factory,
+ "sink");
+ gst_pad_set_chain_function(element->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_video_connector_chain));
+ gst_pad_set_event_function(element->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_video_connector_handle_sink_event));
+ gst_pad_set_bufferalloc_function(element->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_video_connector_buffer_alloc));
+ gst_pad_set_setcaps_function(element->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_video_connector_setcaps));
+ gst_pad_set_getcaps_function(element->sinkpad,
+ GST_DEBUG_FUNCPTR(gst_video_connector_getcaps));
+ gst_pad_set_acceptcaps_function(element->sinkpad,
+ GST_DEBUG_FUNCPTR(gst_video_connector_acceptcaps));
+
+ gst_element_add_pad (GST_ELEMENT (element), element->sinkpad);
+
+ element->srcpad =
+ gst_pad_new_from_static_template (&gst_video_connector_src_factory,
+ "src");
+ gst_pad_add_buffer_probe(element->srcpad,
+ G_CALLBACK(gst_video_connector_new_buffer_probe), element);
+ gst_element_add_pad (GST_ELEMENT (element), element->srcpad);
+
+ element->relinked = FALSE;
+ element->failedSignalEmited = FALSE;
+ gst_segment_init (&element->segment, GST_FORMAT_TIME);
+ element->latest_buffer = NULL;
+}
+
+static void
+gst_video_connector_reset (GstVideoConnector * element)
+{
+ element->relinked = FALSE;
+ element->failedSignalEmited = FALSE;
+ if (element->latest_buffer != NULL) {
+ gst_buffer_unref (element->latest_buffer);
+ element->latest_buffer = NULL;
+ }
+ gst_segment_init (&element->segment, GST_FORMAT_UNDEFINED);
+}
+
+static void
+gst_video_connector_dispose (GObject * object)
+{
+ GstVideoConnector *element = GST_VIDEO_CONNECTOR (object);
+
+ gst_video_connector_reset (element);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static GstFlowReturn
+gst_video_connector_buffer_alloc (GstPad * pad, guint64 offset, guint size,
+ GstCaps * caps, GstBuffer ** buf)
+{
+ GstVideoConnector *element;
+ GstFlowReturn res = GST_FLOW_OK;
+ element = GST_VIDEO_CONNECTOR (GST_PAD_PARENT (pad));
+
+ if (!buf)
+ return GST_FLOW_ERROR;
+ *buf = NULL;
+
+ GST_OBJECT_LOCK (element);
+ gst_object_ref(element->srcpad);
+ GST_OBJECT_UNLOCK (element);
+
+ res = gst_pad_alloc_buffer(element->srcpad, offset, size, caps, buf);
+ gst_object_unref (element->srcpad);
+
+ GST_DEBUG_OBJECT (element, "buffer alloc finished: %s", gst_flow_get_name (res));
+
+ return res;
+}
+
+static gboolean
+gst_video_connector_setcaps (GstPad *pad, GstCaps *caps)
+{
+ GstVideoConnector *element;
+ element = GST_VIDEO_CONNECTOR (GST_PAD_PARENT (pad));
+
+ /* forward-negotiate */
+ gboolean res = gst_pad_set_caps(element->srcpad, caps);
+
+ GST_DEBUG_OBJECT(element, "gst_video_connector_setcaps %s %i", gst_caps_to_string(caps), res);
+
+ if (!res) {
+ //if set_caps failed, emit "connection-failed" signal
+ //so colorspace transformation elemnt can be inserted
+ GST_INFO_OBJECT(element, "gst_video_connector_setcaps failed, emit connection-failed signal");
+ g_signal_emit(G_OBJECT(element), gst_video_connector_signals[SIGNAL_CONNECTION_FAILED], 0);
+
+ return gst_pad_set_caps(element->srcpad, caps);
+ }
+
+ return TRUE;
+}
+
+static GstCaps *gst_video_connector_getcaps (GstPad * pad)
+{
+ GstVideoConnector *element;
+ element = GST_VIDEO_CONNECTOR (GST_PAD_PARENT (pad));
+
+#if (GST_VERSION_MICRO > 25)
+ GstCaps *caps = gst_pad_peer_get_caps_reffed(element->srcpad);
+#else
+ GstCaps *caps = gst_pad_peer_get_caps(element->srcpad);
+#endif
+
+ if (!caps)
+ caps = gst_caps_new_any();
+
+ return caps;
+}
+
+static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps)
+{
+ GstVideoConnector *element;
+ element = GST_VIDEO_CONNECTOR (GST_PAD_PARENT (pad));
+
+ return gst_pad_peer_accept_caps(element->srcpad, caps);
+}
+
+static void
+gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal)
+{
+ GST_INFO_OBJECT(element, "New segment requested, failed signal enabled: %i", emitFailedSignal);
+ GstVideoConnector *connector = GST_VIDEO_CONNECTOR(element);
+ connector->relinked = TRUE;
+ if (emitFailedSignal)
+ connector->failedSignalEmited = FALSE;
+}
+
+
+static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer *buffer, guint * object)
+{
+ GstVideoConnector *element = GST_VIDEO_CONNECTOR (object);
+
+ /*
+ If relinking is requested, the current buffer should be rejected and
+ the new segment + previous buffer should be pushed first
+ */
+
+ if (element->relinked)
+ GST_LOG_OBJECT(element, "rejected buffer because of new segment request");
+
+ return !element->relinked;
+}
+
+
+static GstFlowReturn
+gst_video_connector_chain (GstPad * pad, GstBuffer * buf)
+{
+ GstFlowReturn res;
+ GstVideoConnector *element;
+
+ element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad));
+
+ do {
+ /*
+ Resend the segment message and last buffer to preroll the new sink.
+ Sinks can be changed multiple times while paused,
+ while loop allows to send the segment message and preroll
+ all of them with the same buffer.
+ */
+ while (element->relinked) {
+ element->relinked = FALSE;
+
+ gint64 pos = element->segment.last_stop;
+
+ if (element->latest_buffer && GST_BUFFER_TIMESTAMP_IS_VALID(element->latest_buffer)) {
+ pos = GST_BUFFER_TIMESTAMP (element->latest_buffer);
+ }
+
+ //push a new segment and last buffer
+ GstEvent *ev = gst_event_new_new_segment (TRUE,
+ element->segment.rate,
+ element->segment.format,
+ pos, //start
+ element->segment.stop,
+ pos);
+
+ GST_DEBUG_OBJECT (element, "Pushing new segment event");
+ if (!gst_pad_push_event (element->srcpad, ev)) {
+ GST_WARNING_OBJECT (element,
+ "Newsegment handling failed in %" GST_PTR_FORMAT,
+ element->srcpad);
+ }
+
+ if (element->latest_buffer) {
+ GST_DEBUG_OBJECT (element, "Pushing latest buffer...");
+ gst_buffer_ref(element->latest_buffer);
+ gst_pad_push(element->srcpad, element->latest_buffer);
+ }
+ }
+
+ gst_buffer_ref(buf);
+
+ //it's possible video sink is changed during gst_pad_push blocked by
+ //pad lock, in this case ( element->relinked == TRUE )
+ //the buffer should be rejected by the buffer probe and
+ //the new segment + prev buffer should be sent before
+
+ GST_LOG_OBJECT (element, "Pushing buffer...");
+ res = gst_pad_push (element->srcpad, buf);
+ GST_LOG_OBJECT (element, "Pushed buffer: %s", gst_flow_get_name (res));
+
+ //if gst_pad_push failed give the service another chance,
+ //it may still work with the colorspace element added
+ if (!element->failedSignalEmited && res == GST_FLOW_NOT_NEGOTIATED) {
+ element->failedSignalEmited = TRUE;
+ GST_INFO_OBJECT(element, "gst_pad_push failed, emit connection-failed signal");
+ g_signal_emit(G_OBJECT(element), gst_video_connector_signals[SIGNAL_CONNECTION_FAILED], 0);
+ }
+
+ } while (element->relinked);
+
+
+ if (element->latest_buffer) {
+ gst_buffer_unref (element->latest_buffer);
+ element->latest_buffer = NULL;
+ }
+
+ //don't save the last video buffer on maemo6 because of buffers shortage
+ //with omapxvsink
+#ifndef Q_WS_MAEMO_6
+ element->latest_buffer = gst_buffer_ref(buf);
+#endif
+
+ gst_buffer_unref(buf);
+ gst_object_unref (element);
+
+ return res;
+}
+
+static GstStateChangeReturn
+gst_video_connector_change_state (GstElement * element,
+ GstStateChange transition)
+{
+ GstVideoConnector *connector;
+ GstStateChangeReturn result;
+
+ connector = GST_VIDEO_CONNECTOR(element);
+ result = GST_ELEMENT_CLASS (parent_class)->change_state(element, transition);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ gst_video_connector_reset (connector);
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ connector->relinked = FALSE;
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+static gboolean
+gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event)
+{
+ if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
+ GstVideoConnector *element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad));
+
+ gboolean update;
+ GstFormat format;
+ gdouble rate, arate;
+ gint64 start, stop, time;
+
+ gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
+ &start, &stop, &time);
+
+ GST_LOG_OBJECT (element,
+ "NEWSEGMENT update %d, rate %lf, applied rate %lf, "
+ "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
+ G_GINT64_FORMAT, update, rate, arate, format, start, stop, time);
+
+ gst_segment_set_newsegment_full (&element->segment, update,
+ rate, arate, format, start, stop, time);
+
+ gst_object_unref (element);
+ }
+
+ return gst_pad_event_default (pad, event);
+}
diff --git a/src/plugins/gstreamer/gstvideoconnector.h b/src/plugins/gstreamer/gstvideoconnector.h
new file mode 100644
index 000000000..00d057e06
--- /dev/null
+++ b/src/plugins/gstreamer/gstvideoconnector.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QGSTVIDEOCONNECTOR_H
+#define QGSTVIDEOCONNECTOR_H
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VIDEO_CONNECTOR \
+ (gst_video_connector_get_type())
+#define GST_VIDEO_CONNECTOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VIDEO_CONNECTOR, GstVideoConnector))
+#define GST_VIDEO_CONNECTOR_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VIDEO_CONNECTOR, GstVideoConnectorClass))
+#define GST_IS_VIDEO_CONNECTOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VIDEO_CONNECTOR))
+#define GST_IS_VIDEO_CONNECTOR_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VIDEO_CONNECTOR))
+
+typedef struct _GstVideoConnector GstVideoConnector;
+typedef struct _GstVideoConnectorClass GstVideoConnectorClass;
+
+struct _GstVideoConnector {
+ GstElement element;
+
+ GstPad *srcpad;
+ GstPad *sinkpad;
+
+ gboolean relinked;
+ gboolean failedSignalEmited;
+ GstSegment segment;
+ GstBuffer *latest_buffer;
+};
+
+struct _GstVideoConnectorClass {
+ GstElementClass parent_class;
+
+ /* action signal to resend new segment */
+ void (*resend_new_segment) (GstElement * element, gboolean emitFailedSignal);
+};
+
+GType gst_video_connector_get_type (void);
+
+G_END_DECLS
+
+#endif
+
diff --git a/src/plugins/gstreamer/mediacapture/mediacapture.pri b/src/plugins/gstreamer/mediacapture/mediacapture.pri
new file mode 100644
index 000000000..b7f7794f9
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/mediacapture.pri
@@ -0,0 +1,27 @@
+INCLUDEPATH += $$PWD
+
+DEFINES += QMEDIA_GSTREAMER_CAPTURE
+
+HEADERS += $$PWD/qgstreamercaptureservice.h \
+ $$PWD/qgstreamercapturesession.h \
+ $$PWD/qgstreameraudioencode.h \
+ $$PWD/qgstreamervideoencode.h \
+ $$PWD/qgstreamerrecordercontrol.h \
+ $$PWD/qgstreamermediacontainercontrol.h \
+ $$PWD/qgstreamercameracontrol.h \
+ $$PWD/qgstreamerv4l2input.h \
+ $$PWD/qgstreamercapturemetadatacontrol.h \
+ $$PWD/qgstreamerimagecapturecontrol.h \
+ $$PWD/qgstreamerimageencode.h
+
+SOURCES += $$PWD/qgstreamercaptureservice.cpp \
+ $$PWD/qgstreamercapturesession.cpp \
+ $$PWD/qgstreameraudioencode.cpp \
+ $$PWD/qgstreamervideoencode.cpp \
+ $$PWD/qgstreamerrecordercontrol.cpp \
+ $$PWD/qgstreamermediacontainercontrol.cpp \
+ $$PWD/qgstreamercameracontrol.cpp \
+ $$PWD/qgstreamerv4l2input.cpp \
+ $$PWD/qgstreamercapturemetadatacontrol.cpp \
+ $$PWD/qgstreamerimagecapturecontrol.cpp \
+ $$PWD/qgstreamerimageencode.cpp
diff --git a/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp
new file mode 100644
index 000000000..e548393eb
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp
@@ -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$
+** 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 "qgstreameraudioencode.h"
+#include "qgstreamercapturesession.h"
+#include "qgstreamermediacontainercontrol.h"
+
+#include <QtCore/qdebug.h>
+
+#include <math.h>
+
+QGstreamerAudioEncode::QGstreamerAudioEncode(QObject *parent)
+ :QAudioEncoderControl(parent)
+{
+ QList<QByteArray> codecCandidates;
+
+#if defined(Q_WS_MAEMO_5)
+ codecCandidates << "audio/PCM"; //<< "audio/AMR" << "audio/AMR-WB" << "audio/speex";
+#elif defined(Q_WS_MAEMO_6)
+ codecCandidates << "audio/AAC" << "audio/mpeg" << "audio/vorbis" << "audio/speex" << "audio/GSM"
+ << "audio/PCM" << "audio/AMR" << "audio/AMR-WB" << "audio/FLAC";
+#else
+ codecCandidates << "audio/mpeg" << "audio/vorbis" << "audio/speex" << "audio/GSM"
+ << "audio/PCM" << "audio/AMR" << "audio/AMR-WB" << "audio/FLAC";
+#endif
+
+#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
+ m_elementNames["audio/AMR"] = "nokiaamrnbenc";
+ m_elementNames["audio/AMR-WB"] = "nokiaamrwbenc";
+ m_elementNames["audio/AAC"] = "nokiaaacenc";
+#else
+ m_elementNames["audio/mpeg"] = "lamemp3enc";
+ m_elementNames["audio/AMR"] = "amrnbenc";
+ m_elementNames["audio/AMR-WB"] = "amrwbenc";
+#endif
+
+ m_elementNames["audio/vorbis"] = "vorbisenc";
+ m_elementNames["audio/speex"] = "speexenc";
+ m_elementNames["audio/PCM"] = "audioresample";
+ m_elementNames["audio/FLAC"] = "flacenc";
+ m_elementNames["audio/GSM"] = "gsmenc";
+
+ m_codecOptions["audio/vorbis"] = QStringList() << "min-bitrate" << "max-bitrate";
+ m_codecOptions["audio/mpeg"] = QStringList() << "mode";
+ m_codecOptions["audio/speex"] = QStringList() << "mode" << "vbr" << "vad" << "dtx";
+ m_codecOptions["audio/GSM"] = QStringList();
+ m_codecOptions["audio/PCM"] = QStringList();
+ m_codecOptions["audio/AMR"] = QStringList();
+ m_codecOptions["audio/AMR-WB"] = QStringList();
+
+ foreach( const QByteArray& codecName, codecCandidates ) {
+ QByteArray elementName = m_elementNames[codecName];
+ GstElementFactory *factory = gst_element_factory_find(elementName.constData());
+
+ if (factory) {
+ m_codecs.append(codecName);
+ const gchar *descr = gst_element_factory_get_description(factory);
+
+ if (codecName == QByteArray("audio/PCM"))
+ m_codecDescriptions.insert(codecName, tr("Raw PCM audio"));
+ else
+ m_codecDescriptions.insert(codecName, QString::fromUtf8(descr));
+
+ m_streamTypes.insert(codecName,
+ QGstreamerMediaContainerControl::supportedStreamTypes(factory, GST_PAD_SRC));
+
+ gst_object_unref(GST_OBJECT(factory));
+ }
+ }
+
+ //if (!m_codecs.isEmpty())
+ // m_audioSettings.setCodec(m_codecs[0]);
+}
+
+QGstreamerAudioEncode::~QGstreamerAudioEncode()
+{
+}
+
+QStringList QGstreamerAudioEncode::supportedAudioCodecs() const
+{
+ return m_codecs;
+}
+
+QString QGstreamerAudioEncode::codecDescription(const QString &codecName) const
+{
+ return m_codecDescriptions.value(codecName);
+}
+
+QStringList QGstreamerAudioEncode::supportedEncodingOptions(const QString &codec) const
+{
+ return m_codecOptions.value(codec);
+}
+
+QVariant QGstreamerAudioEncode::encodingOption(
+ const QString &codec, const QString &name) const
+{
+ return m_options[codec].value(name);
+}
+
+void QGstreamerAudioEncode::setEncodingOption(
+ const QString &codec, const QString &name, const QVariant &value)
+{
+ m_options[codec][name] = value;
+}
+
+QList<int> QGstreamerAudioEncode::supportedSampleRates(const QAudioEncoderSettings &, bool *) const
+{
+ //TODO check element caps to find actual values
+
+ return QList<int>();
+}
+
+QAudioEncoderSettings QGstreamerAudioEncode::audioSettings() const
+{
+ return m_audioSettings;
+}
+
+void QGstreamerAudioEncode::setAudioSettings(const QAudioEncoderSettings &settings)
+{
+ m_audioSettings = settings;
+}
+
+
+GstElement *QGstreamerAudioEncode::createEncoder()
+{
+ QString codec = m_audioSettings.codec();
+ GstElement *encoderElement = gst_element_factory_make(m_elementNames.value(codec).constData(), NULL);
+ if (!encoderElement)
+ return 0;
+
+ GstBin * encoderBin = GST_BIN(gst_bin_new("audio-encoder-bin"));
+
+ GstElement *capsFilter = gst_element_factory_make("capsfilter", NULL);
+
+ gst_bin_add(encoderBin, capsFilter);
+ gst_bin_add(encoderBin, encoderElement);
+ gst_element_link(capsFilter, encoderElement);
+
+ // add ghostpads
+ GstPad *pad = gst_element_get_static_pad(capsFilter, "sink");
+ gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("sink", pad));
+ gst_object_unref(GST_OBJECT(pad));
+
+ pad = gst_element_get_static_pad(encoderElement, "src");
+ gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("src", pad));
+ gst_object_unref(GST_OBJECT(pad));
+
+ if (m_audioSettings.sampleRate() > 0 || m_audioSettings.channelCount() > 0) {
+ GstCaps *caps = gst_caps_new_empty();
+ GstStructure *structure = gst_structure_new("audio/x-raw-int", NULL);
+
+ if (m_audioSettings.sampleRate() > 0)
+ gst_structure_set(structure, "rate", G_TYPE_INT, m_audioSettings.sampleRate(), NULL );
+
+ if (m_audioSettings.channelCount() > 0)
+ gst_structure_set(structure, "channels", G_TYPE_INT, m_audioSettings.channelCount(), NULL );
+
+ gst_caps_append_structure(caps,structure);
+
+ //qDebug() << "set caps filter:" << gst_caps_to_string(caps);
+
+ g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
+ }
+
+ if (encoderElement) {
+ if (m_audioSettings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
+ QtMultimediaKit::EncodingQuality qualityValue = m_audioSettings.quality();
+
+ if (codec == QLatin1String("audio/vorbis")) {
+ double qualityTable[] = {
+ 0.1, //VeryLow
+ 0.3, //Low
+ 0.5, //Normal
+ 0.7, //High
+ 1.0 //VeryHigh
+ };
+ g_object_set(G_OBJECT(encoderElement), "quality", qualityTable[qualityValue], NULL);
+ } else if (codec == QLatin1String("audio/mpeg")) {
+ g_object_set(G_OBJECT(encoderElement), "target", 0, NULL); //constant quality mode
+ qreal quality[] = {
+ 1, //VeryLow
+ 3, //Low
+ 5, //Normal
+ 7, //High
+ 9 //VeryHigh
+ };
+ g_object_set(G_OBJECT(encoderElement), "quality", quality[qualityValue], NULL);
+ } else if (codec == QLatin1String("audio/speex")) {
+ //0-10 range with default 8
+ double qualityTable[] = {
+ 2, //VeryLow
+ 5, //Low
+ 8, //Normal
+ 9, //High
+ 10 //VeryHigh
+ };
+ g_object_set(G_OBJECT(encoderElement), "quality", qualityTable[qualityValue], NULL);
+ } else if (codec.startsWith("audio/AMR")) {
+ int band[] = {
+ 0, //VeryLow
+ 2, //Low
+ 4, //Normal
+ 6, //High
+ 7 //VeryHigh
+ };
+
+ g_object_set(G_OBJECT(encoderElement), "band-mode", band[qualityValue], NULL);
+ }
+ } else {
+ int bitrate = m_audioSettings.bitRate();
+ if (bitrate > 0) {
+ if (codec == QLatin1String("audio/mpeg")) {
+ g_object_set(G_OBJECT(encoderElement), "target", 1, NULL); //constant bitrate mode
+ }
+ g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
+ }
+ }
+
+ QMap<QString, QVariant> options = m_options.value(codec);
+ QMapIterator<QString,QVariant> it(options);
+ while (it.hasNext()) {
+ it.next();
+ QString option = it.key();
+ QVariant value = it.value();
+
+ switch (value.type()) {
+ case QVariant::Int:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toInt(), NULL);
+ break;
+ case QVariant::Bool:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toBool(), NULL);
+ break;
+ case QVariant::Double:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toDouble(), NULL);
+ break;
+ case QVariant::String:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toString().toUtf8().constData(), NULL);
+ break;
+ default:
+ qWarning() << "unsupported option type:" << option << value;
+ break;
+ }
+
+ }
+ }
+
+ return GST_ELEMENT(encoderBin);
+}
+
+
+QSet<QString> QGstreamerAudioEncode::supportedStreamTypes(const QString &codecName) const
+{
+ return m_streamTypes.value(codecName);
+}
diff --git a/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.h b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.h
new file mode 100644
index 000000000..e2c48234d
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.h
@@ -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$
+** 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 QGSTREAMERAUDIOENCODE_H
+#define QGSTREAMERAUDIOENCODE_H
+
+#include <qaudioencodercontrol.h>
+class QGstreamerCaptureSession;
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qset.h>
+
+#include <gst/gst.h>
+
+#include <qaudioformat.h>
+
+QT_USE_NAMESPACE
+
+class QGstreamerAudioEncode : public QAudioEncoderControl
+{
+ Q_OBJECT
+public:
+ QGstreamerAudioEncode(QObject *parent);
+ virtual ~QGstreamerAudioEncode();
+
+ QStringList supportedAudioCodecs() const;
+ QString codecDescription(const QString &codecName) const;
+
+ QStringList supportedEncodingOptions(const QString &codec) const;
+ QVariant encodingOption(const QString &codec, const QString &name) const;
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
+
+ QList<int> supportedSampleRates(const QAudioEncoderSettings &settings = QAudioEncoderSettings(),
+ bool *isContinuous = 0) const;
+ QList<int> supportedChannelCounts(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const;
+ QList<int> supportedSampleSizes(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const;
+
+ QAudioEncoderSettings audioSettings() const;
+ void setAudioSettings(const QAudioEncoderSettings&);
+
+ GstElement *createEncoder();
+
+ QSet<QString> supportedStreamTypes(const QString &codecName) const;
+
+private:
+ QStringList m_codecs;
+ QMap<QString,QByteArray> m_elementNames;
+ QMap<QString,QString> m_codecDescriptions;
+ QMap<QString,QStringList> m_codecOptions;
+
+ QMap<QString, QMap<QString, QVariant> > m_options;
+
+ QMap<QString, QSet<QString> > m_streamTypes;
+
+ QAudioEncoderSettings m_audioSettings;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.cpp
new file mode 100644
index 000000000..927a827dd
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.cpp
@@ -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$
+**
+****************************************************************************/
+
+#include "qgstreamercameracontrol.h"
+#include "qgstreamerimageencode.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+
+
+QGstreamerCameraControl::QGstreamerCameraControl(QGstreamerCaptureSession *session)
+ :QCameraControl(session),
+ m_captureMode(QCamera::CaptureStillImage),
+ m_session(session),
+ m_state(QCamera::UnloadedState),
+ m_status(QCamera::UnloadedStatus),
+ m_reloadPending(false)
+
+{
+ connect(m_session, SIGNAL(stateChanged(QGstreamerCaptureSession::State)),
+ this, SLOT(updateStatus()));
+
+ connect(m_session->imageEncodeControl(), SIGNAL(settingsChanged()),
+ SLOT(reloadLater()));
+ connect(m_session, SIGNAL(viewfinderChanged()),
+ SLOT(reloadLater()));
+ connect(m_session, SIGNAL(readyChanged(bool)),
+ SLOT(reloadLater()));
+}
+
+QGstreamerCameraControl::~QGstreamerCameraControl()
+{
+}
+
+void QGstreamerCameraControl::setCaptureMode(QCamera::CaptureMode mode)
+{
+ if (m_captureMode == mode)
+ return;
+
+ switch (mode) {
+ case QCamera::CaptureStillImage:
+ m_session->setCaptureMode(QGstreamerCaptureSession::Image);
+ break;
+ case QCamera::CaptureVideo:
+ m_session->setCaptureMode(QGstreamerCaptureSession::AudioAndVideo);
+ break;
+ }
+
+ emit captureModeChanged(mode);
+ updateStatus();
+ reloadLater();
+}
+
+void QGstreamerCameraControl::setState(QCamera::State state)
+{
+ if (m_state == state)
+ return;
+
+ m_state = state;
+ switch (state) {
+ case QCamera::UnloadedState:
+ case QCamera::LoadedState:
+ m_session->setState(QGstreamerCaptureSession::StoppedState);
+ break;
+ case QCamera::ActiveState:
+ //postpone changing to Active if the session is nor ready yet
+ if (m_session->isReady()) {
+ m_session->setState(QGstreamerCaptureSession::PreviewState);
+ } else {
+#ifdef CAMEABIN_DEBUG
+ qDebug() << "Camera session is not ready yet, postpone activating";
+#endif
+ }
+ break;
+ default:
+ emit error(QCamera::NotSupportedFeatureError, tr("State not supported."));
+ }
+
+ updateStatus();
+ emit stateChanged(m_state);
+}
+
+QCamera::State QGstreamerCameraControl::state() const
+{
+ return m_state;
+}
+
+void QGstreamerCameraControl::updateStatus()
+{
+ QCamera::Status oldStatus = m_status;
+
+ switch (m_state) {
+ case QCamera::UnloadedState:
+ m_status = QCamera::UnloadedStatus;
+ break;
+ case QCamera::LoadedState:
+ m_status = QCamera::LoadedStatus;
+ break;
+ case QCamera::ActiveState:
+ if (m_session->state() == QGstreamerCaptureSession::StoppedState)
+ m_status = QCamera::StartingStatus;
+ else
+ m_status = QCamera::ActiveStatus;
+ break;
+ }
+
+ if (oldStatus != m_status) {
+ //qDebug() << "Status changed:" << m_status;
+ emit statusChanged(m_status);
+ }
+}
+
+void QGstreamerCameraControl::reloadLater()
+{
+ //qDebug() << "reload pipeline requested";
+ if (!m_reloadPending && m_state == QCamera::ActiveState) {
+ m_reloadPending = true;
+ m_session->setState(QGstreamerCaptureSession::StoppedState);
+ QMetaObject::invokeMethod(this, "reloadPipeline", Qt::QueuedConnection);
+ }
+}
+
+void QGstreamerCameraControl::reloadPipeline()
+{
+ //qDebug() << "reload pipeline";
+ if (m_reloadPending) {
+ m_reloadPending = false;
+ if (m_state == QCamera::ActiveState && m_session->isReady()) {
+ m_session->setState(QGstreamerCaptureSession::PreviewState);
+ }
+ }
+}
+
+bool QGstreamerCameraControl::canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const
+{
+ Q_UNUSED(status);
+
+ switch (changeType) {
+ case QCameraControl::CaptureMode:
+ case QCameraControl::ImageEncodingSettings:
+ case QCameraControl::VideoEncodingSettings:
+ case QCameraControl::Viewfinder:
+ return true;
+ default:
+ return false;
+ }
+}
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.h b/src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.h
new file mode 100644
index 000000000..c07ffcd19
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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 QGSTREAMERCAMERACONTROL_H
+#define QGSTREAMERCAMERACONTROL_H
+
+#include <QHash>
+#include <qcameracontrol.h>
+#include "qgstreamercapturesession.h"
+
+QT_USE_NAMESPACE
+QT_USE_NAMESPACE
+
+class QGstreamerCameraControl : public QCameraControl
+{
+ Q_OBJECT
+public:
+ QGstreamerCameraControl( QGstreamerCaptureSession *session );
+ virtual ~QGstreamerCameraControl();
+
+ bool isValid() const { return true; }
+
+ QCamera::State state() const;
+ void setState(QCamera::State state);
+
+ QCamera::Status status() const { return m_status; }
+
+ QCamera::CaptureMode captureMode() const { return m_captureMode; }
+ void setCaptureMode(QCamera::CaptureMode mode);
+
+ bool isCaptureModeSupported(QCamera::CaptureMode mode) const
+ {
+ return mode == QCamera::CaptureStillImage || mode == QCamera::CaptureVideo;
+ }
+
+ QCamera::LockTypes supportedLocks() const
+ {
+ return QCamera::NoLock;
+ }
+
+ bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const;
+
+public slots:
+ void reloadLater();
+
+private slots:
+ void updateStatus();
+ void reloadPipeline();
+
+
+private:
+ QCamera::CaptureMode m_captureMode;
+ QGstreamerCaptureSession *m_session;
+ QCamera::State m_state;
+ QCamera::Status m_status;
+ bool m_reloadPending;
+};
+
+#endif // QGSTREAMERCAMERACONTROL_H
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp
new file mode 100644
index 000000000..b0e589dc8
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamercapturemetadatacontrol.h"
+
+#include <gst/gst.h>
+#include <gst/gstversion.h>
+
+struct QGstreamerMetaDataKeyLookup
+{
+ QtMultimediaKit::MetaData key;
+ const char *token;
+};
+
+static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] =
+{
+ { QtMultimediaKit::Title, GST_TAG_TITLE },
+ //{ QtMultimediaKit::SubTitle, 0 },
+ //{ QtMultimediaKit::Author, 0 },
+ { QtMultimediaKit::Comment, GST_TAG_COMMENT },
+ { QtMultimediaKit::Description, GST_TAG_DESCRIPTION },
+ //{ QtMultimediaKit::Category, 0 },
+ { QtMultimediaKit::Genre, GST_TAG_GENRE },
+ //{ QtMultimediaKit::Year, 0 },
+ //{ QtMultimediaKit::UserRating, 0 },
+
+ { QtMultimediaKit::Language, GST_TAG_LANGUAGE_CODE },
+
+ { QtMultimediaKit::Publisher, GST_TAG_ORGANIZATION },
+ { QtMultimediaKit::Copyright, GST_TAG_COPYRIGHT },
+ //{ QtMultimediaKit::ParentalRating, 0 },
+ //{ QtMultimediaKit::RatingOrganisation, 0 },
+
+ // Media
+ //{ QtMultimediaKit::Size, 0 },
+ //{ QtMultimediaKit::MediaType, 0 },
+ { QtMultimediaKit::Duration, GST_TAG_DURATION },
+
+ // Audio
+ { QtMultimediaKit::AudioBitRate, GST_TAG_BITRATE },
+ { QtMultimediaKit::AudioCodec, GST_TAG_AUDIO_CODEC },
+ //{ QtMultimediaKit::ChannelCount, 0 },
+ //{ QtMultimediaKit::SampleRate, 0 },
+
+ // Music
+ { QtMultimediaKit::AlbumTitle, GST_TAG_ALBUM },
+ { QtMultimediaKit::AlbumArtist, GST_TAG_ARTIST},
+ { QtMultimediaKit::ContributingArtist, GST_TAG_PERFORMER },
+#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
+ { QtMultimediaKit::Composer, GST_TAG_COMPOSER },
+#endif
+ //{ QtMultimediaKit::Conductor, 0 },
+ //{ QtMultimediaKit::Lyrics, 0 },
+ //{ QtMultimediaKit::Mood, 0 },
+ { QtMultimediaKit::TrackNumber, GST_TAG_TRACK_NUMBER },
+
+ //{ QtMultimediaKit::CoverArtUrlSmall, 0 },
+ //{ QtMultimediaKit::CoverArtUrlLarge, 0 },
+
+ // Image/Video
+ //{ QtMultimediaKit::Resolution, 0 },
+ //{ QtMultimediaKit::PixelAspectRatio, 0 },
+
+ // Video
+ //{ QtMultimediaKit::VideoFrameRate, 0 },
+ //{ QtMultimediaKit::VideoBitRate, 0 },
+ { QtMultimediaKit::VideoCodec, GST_TAG_VIDEO_CODEC },
+
+ //{ QtMultimediaKit::PosterUrl, 0 },
+
+ // Movie
+ //{ QtMultimediaKit::ChapterNumber, 0 },
+ //{ QtMultimediaKit::Director, 0 },
+ { QtMultimediaKit::LeadPerformer, GST_TAG_PERFORMER },
+ //{ QtMultimediaKit::Writer, 0 },
+
+ // Photos
+ //{ QtMultimediaKit::CameraManufacturer, 0 },
+ //{ QtMultimediaKit::CameraModel, 0 },
+ //{ QtMultimediaKit::Event, 0 },
+ //{ QtMultimediaKit::Subject, 0 }
+};
+
+QGstreamerCaptureMetaDataControl::QGstreamerCaptureMetaDataControl(QObject *parent)
+ :QMetaDataWriterControl(parent)
+{
+}
+
+QVariant QGstreamerCaptureMetaDataControl::metaData(QtMultimediaKit::MetaData key) const
+{
+ static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
+
+ for (int i = 0; i < count; ++i) {
+ if (qt_gstreamerMetaDataKeys[i].key == key) {
+ const char *name = qt_gstreamerMetaDataKeys[i].token;
+
+ return m_values.value(QByteArray::fromRawData(name, qstrlen(name)));
+ }
+ }
+ return QVariant();
+}
+
+void QGstreamerCaptureMetaDataControl::setMetaData(QtMultimediaKit::MetaData key, const QVariant &value)
+{
+ static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
+
+ for (int i = 0; i < count; ++i) {
+ if (qt_gstreamerMetaDataKeys[i].key == key) {
+ const char *name = qt_gstreamerMetaDataKeys[i].token;
+
+ m_values.insert(QByteArray::fromRawData(name, qstrlen(name)), value);
+
+ emit QMetaDataWriterControl::metaDataChanged();
+ emit metaDataChanged(m_values);
+
+ return;
+ }
+ }
+}
+
+QList<QtMultimediaKit::MetaData> QGstreamerCaptureMetaDataControl::availableMetaData() const
+{
+ static QMap<QByteArray, QtMultimediaKit::MetaData> keysMap;
+ if (keysMap.isEmpty()) {
+ const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
+ for (int i = 0; i < count; ++i) {
+ keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key;
+ }
+ }
+
+ QList<QtMultimediaKit::MetaData> res;
+ foreach (const QByteArray &key, m_values.keys()) {
+ QtMultimediaKit::MetaData tag = keysMap.value(key, QtMultimediaKit::MetaData(-1));
+ if (tag != -1)
+ res.append(tag);
+ }
+
+ return res;
+}
+
+QVariant QGstreamerCaptureMetaDataControl::extendedMetaData(QString const &name) const
+{
+ return m_values.value(name.toLatin1());
+}
+
+void QGstreamerCaptureMetaDataControl::setExtendedMetaData(QString const &name, QVariant const &value)
+{
+ m_values.insert(name.toLatin1(), value);
+ emit QMetaDataWriterControl::metaDataChanged();
+ emit metaDataChanged(m_values);
+}
+
+QStringList QGstreamerCaptureMetaDataControl::availableExtendedMetaData() const
+{
+ QStringList res;
+ foreach (const QByteArray &key, m_values.keys())
+ res.append(QString(key));
+
+ return res;
+}
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.h b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.h
new file mode 100644
index 000000000..e859da486
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERCAPTUREMETADATACONTROL_H
+#define QGSTREAMERCAPTUREMETADATACONTROL_H
+
+#include <qmetadatawritercontrol.h>
+
+QT_USE_NAMESPACE
+
+class QGstreamerCaptureMetaDataControl : public QMetaDataWriterControl
+{
+ Q_OBJECT
+public:
+ QGstreamerCaptureMetaDataControl(QObject *parent);
+ virtual ~QGstreamerCaptureMetaDataControl() {};
+
+
+ bool isMetaDataAvailable() const { return true; }
+ bool isWritable() const { return true; }
+
+ QVariant metaData(QtMultimediaKit::MetaData key) const;
+ void setMetaData(QtMultimediaKit::MetaData key, const QVariant &value);
+ QList<QtMultimediaKit::MetaData> availableMetaData() const;
+
+ QVariant extendedMetaData(QString const &name) const;
+ void setExtendedMetaData(QString const &name, QVariant const &value);
+ QStringList availableExtendedMetaData() const;
+
+Q_SIGNALS:
+ void metaDataChanged(const QMap<QByteArray, QVariant>&);
+
+private:
+ QMap<QByteArray, QVariant> m_values;
+};
+
+#endif // QGSTREAMERCAPTUREMETADATACONTROL_H
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp
new file mode 100644
index 000000000..97310d199
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamercaptureservice.h"
+#include "qgstreamercapturesession.h"
+#include "qgstreamerrecordercontrol.h"
+#include "qgstreamermediacontainercontrol.h"
+#include "qgstreameraudioencode.h"
+#include "qgstreamervideoencode.h"
+#include "qgstreamerimageencode.h"
+#include "qgstreamerbushelper.h"
+#include "qgstreamercameracontrol.h"
+#include "qgstreamerv4l2input.h"
+#include "qgstreamercapturemetadatacontrol.h"
+
+#include "qgstreameraudioinputendpointselector.h"
+#include "qgstreamervideoinputdevicecontrol.h"
+#include "qgstreamerimagecapturecontrol.h"
+
+#include "qgstreamervideooverlay.h"
+#include "qgstreamervideorenderer.h"
+
+#include "qgstreamervideowidget.h"
+
+#include <qmediaserviceprovider.h>
+
+
+QGstreamerCaptureService::QGstreamerCaptureService(const QString &service, QObject *parent):
+ QMediaService(parent)
+{
+ m_captureSession = 0;
+ m_cameraControl = 0;
+ m_metaDataControl = 0;
+
+ m_videoInput = 0;
+ m_audioInputEndpointSelector = 0;
+ m_videoInputDevice = 0;
+
+ m_videoOutput = 0;
+ m_videoRenderer = 0;
+ m_videoWindow = 0;
+ m_videoWidgetControl = 0;
+ m_imageCaptureControl = 0;
+
+ if (service == Q_MEDIASERVICE_AUDIOSOURCE) {
+ m_captureSession = new QGstreamerCaptureSession(QGstreamerCaptureSession::Audio, this);
+ }
+
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ m_captureSession = new QGstreamerCaptureSession(QGstreamerCaptureSession::AudioAndVideo, this);
+ m_cameraControl = new QGstreamerCameraControl(m_captureSession);
+ m_videoInput = new QGstreamerV4L2Input(this);
+ m_captureSession->setVideoInput(m_videoInput);
+ m_videoInputDevice = new QGstreamerVideoInputDeviceControl(this);
+
+ connect(m_videoInputDevice, SIGNAL(selectedDeviceChanged(QString)),
+ m_videoInput, SLOT(setDevice(QString)));
+
+ if (m_videoInputDevice->deviceCount())
+ m_videoInput->setDevice(m_videoInputDevice->deviceName(m_videoInputDevice->selectedDevice()));
+
+ m_videoRenderer = new QGstreamerVideoRenderer(this);
+
+#if defined(Q_WS_X11) && !defined(QT_NO_XVIDEO)
+ m_videoWindow = new QGstreamerVideoOverlay(this);
+ m_videoWidgetControl = new QGstreamerVideoWidgetControl(this);
+#endif
+ m_imageCaptureControl = new QGstreamerImageCaptureControl(m_captureSession);
+ }
+
+ m_audioInputEndpointSelector = new QGstreamerAudioInputEndpointSelector(this);
+ connect(m_audioInputEndpointSelector, SIGNAL(activeEndpointChanged(QString)), m_captureSession, SLOT(setCaptureDevice(QString)));
+
+ if (m_captureSession && m_audioInputEndpointSelector->availableEndpoints().size() > 0)
+ m_captureSession->setCaptureDevice(m_audioInputEndpointSelector->defaultEndpoint());
+
+ m_metaDataControl = new QGstreamerCaptureMetaDataControl(this);
+ connect(m_metaDataControl, SIGNAL(metaDataChanged(QMap<QByteArray,QVariant>)),
+ m_captureSession, SLOT(setMetaData(QMap<QByteArray,QVariant>)));
+}
+
+QGstreamerCaptureService::~QGstreamerCaptureService()
+{
+}
+
+QMediaControl *QGstreamerCaptureService::requestControl(const char *name)
+{
+ if (!m_captureSession)
+ return 0;
+
+ if (qstrcmp(name,QAudioEndpointSelector_iid) == 0)
+ return m_audioInputEndpointSelector;
+
+ if (qstrcmp(name,QVideoDeviceControl_iid) == 0)
+ return m_videoInputDevice;
+
+ if (qstrcmp(name,QMediaRecorderControl_iid) == 0)
+ return m_captureSession->recorderControl();
+
+ if (qstrcmp(name,QAudioEncoderControl_iid) == 0)
+ return m_captureSession->audioEncodeControl();
+
+ if (qstrcmp(name,QVideoEncoderControl_iid) == 0)
+ return m_captureSession->videoEncodeControl();
+
+ if (qstrcmp(name,QImageEncoderControl_iid) == 0)
+ return m_captureSession->imageEncodeControl();
+
+
+ if (qstrcmp(name,QMediaContainerControl_iid) == 0)
+ return m_captureSession->mediaContainerControl();
+
+ if (qstrcmp(name,QCameraControl_iid) == 0)
+ return m_cameraControl;
+
+ if (qstrcmp(name,QMetaDataWriterControl_iid) == 0)
+ return m_metaDataControl;
+
+ if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
+ return m_imageCaptureControl;
+
+ if (!m_videoOutput) {
+ if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+ m_videoOutput = m_videoRenderer;
+ m_captureSession->setVideoPreview(m_videoRenderer);
+ } else if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
+ m_videoOutput = m_videoWindow;
+ m_captureSession->setVideoPreview(m_videoWindow);
+ } else if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
+ m_captureSession->setVideoPreview(m_videoWidgetControl);
+ m_videoOutput = m_videoWidgetControl;
+ }
+
+ if (m_videoOutput)
+ return m_videoOutput;
+ }
+
+ return 0;
+}
+
+void QGstreamerCaptureService::releaseControl(QMediaControl *control)
+{
+ if (control && control == m_videoOutput) {
+ m_videoOutput = 0;
+ m_captureSession->setVideoPreview(0);
+ }
+}
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h
new file mode 100644
index 000000000..09b275c35
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h
@@ -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$
+** 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 QGSTREAMERCAPTURESERVICE_H
+#define QGSTREAMERCAPTURESERVICE_H
+
+#include <qmediaservice.h>
+#include <qmediacontrol.h>
+
+#include <gst/gst.h>
+QT_BEGIN_NAMESPACE
+class QAudioEndpointSelector;
+class QVideoDeviceControl;
+QT_END_NAMESPACE
+
+class QGstreamerCaptureSession;
+class QGstreamerCameraControl;
+class QGstreamerMessage;
+class QGstreamerBusHelper;
+class QGstreamerVideoRenderer;
+class QGstreamerVideoOverlay;
+class QGstreamerVideoWidgetControl;
+class QGstreamerElementFactory;
+class QGstreamerCaptureMetaDataControl;
+class QGstreamerImageCaptureControl;
+class QGstreamerV4L2Input;
+
+class QGstreamerCaptureService : public QMediaService
+{
+ Q_OBJECT
+
+public:
+ QGstreamerCaptureService(const QString &service, QObject *parent = 0);
+ virtual ~QGstreamerCaptureService();
+
+ QMediaControl *requestControl(const char *name);
+ void releaseControl(QMediaControl *);
+
+private:
+ void setAudioPreview(GstElement*);
+
+ QGstreamerCaptureSession *m_captureSession;
+ QGstreamerCameraControl *m_cameraControl;
+ QGstreamerV4L2Input *m_videoInput;
+ QGstreamerCaptureMetaDataControl *m_metaDataControl;
+
+ QAudioEndpointSelector *m_audioInputEndpointSelector;
+ QVideoDeviceControl *m_videoInputDevice;
+
+ QMediaControl *m_videoOutput;
+
+ QGstreamerVideoRenderer *m_videoRenderer;
+ QMediaControl *m_videoWindow;
+ QMediaControl *m_videoWidgetControl;
+ QGstreamerImageCaptureControl *m_imageCaptureControl;
+};
+
+#endif // QGSTREAMERCAPTURESERVICE_H
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
new file mode 100644
index 000000000..f8e73c7af
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp
@@ -0,0 +1,1051 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamercapturesession.h"
+#include "qgstreamerrecordercontrol.h"
+#include "qgstreamermediacontainercontrol.h"
+#include "qgstreamervideorendererinterface.h"
+#include "qgstreameraudioencode.h"
+#include "qgstreamervideoencode.h"
+#include "qgstreamerimageencode.h"
+#include "qgstreamerbushelper.h"
+#include <qmediarecorder.h>
+
+#include <gst/gsttagsetter.h>
+#include <gst/gstversion.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qset.h>
+#include <QCoreApplication>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qfile.h>
+
+#include <QtGui/qimage.h>
+
+#define gstRef(element) { gst_object_ref(GST_OBJECT(element)); gst_object_sink(GST_OBJECT(element)); }
+#define gstUnref(element) { if (element) { gst_object_unref(GST_OBJECT(element)); element = 0; } }
+
+QGstreamerCaptureSession::QGstreamerCaptureSession(QGstreamerCaptureSession::CaptureMode captureMode, QObject *parent)
+ :QObject(parent),
+ m_state(StoppedState),
+ m_pendingState(StoppedState),
+ m_waitingForEos(false),
+ m_pipelineMode(EmptyPipeline),
+ m_captureMode(captureMode),
+ m_audioInputFactory(0),
+ m_audioPreviewFactory(0),
+ m_videoInputFactory(0),
+ m_viewfinder(0),
+ m_viewfinderInterface(0),
+ m_audioSrc(0),
+ m_audioTee(0),
+ m_audioPreviewQueue(0),
+ m_audioPreview(0),
+ m_audioVolume(0),
+ m_muted(false),
+ m_videoSrc(0),
+ m_videoTee(0),
+ m_videoPreviewQueue(0),
+ m_videoPreview(0),
+ m_imageCaptureBin(0),
+ m_encodeBin(0),
+ m_passImage(false),
+ m_passPrerollImage(false)
+{
+ m_pipeline = gst_pipeline_new("media-capture-pipeline");
+ gstRef(m_pipeline);
+
+ m_bus = gst_element_get_bus(m_pipeline);
+ m_busHelper = new QGstreamerBusHelper(m_bus, this);
+ m_busHelper->installSyncEventFilter(this);
+ connect(m_busHelper, SIGNAL(message(QGstreamerMessage)), SLOT(busMessage(QGstreamerMessage)));
+ m_audioEncodeControl = new QGstreamerAudioEncode(this);
+ m_videoEncodeControl = new QGstreamerVideoEncode(this);
+ m_imageEncodeControl = new QGstreamerImageEncode(this);
+ m_recorderControl = new QGstreamerRecorderControl(this);
+ m_mediaContainerControl = new QGstreamerMediaContainerControl(this);
+
+ setState(StoppedState);
+}
+
+QGstreamerCaptureSession::~QGstreamerCaptureSession()
+{
+ setState(StoppedState);
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+ gst_object_unref(GST_OBJECT(m_pipeline));
+}
+
+void QGstreamerCaptureSession::setCaptureMode(CaptureMode mode)
+{
+ m_captureMode = mode;
+}
+
+GstElement *QGstreamerCaptureSession::buildEncodeBin()
+{
+ GstElement *encodeBin = gst_bin_new("encode-bin");
+
+ GstElement *muxer = gst_element_factory_make( m_mediaContainerControl->formatElementName().constData(), "muxer");
+ if (!muxer) {
+ qWarning() << "Could not create a media muxer element:" << m_mediaContainerControl->formatElementName();
+ gst_object_unref(encodeBin);
+ return 0;
+ }
+
+ GstElement *fileSink = gst_element_factory_make("filesink", "filesink");
+ g_object_set(G_OBJECT(fileSink), "location", m_sink.toString().toLocal8Bit().constData(), NULL);
+ gst_bin_add_many(GST_BIN(encodeBin), muxer, fileSink, NULL);
+
+ if (!gst_element_link(muxer, fileSink)) {
+ gst_object_unref(encodeBin);
+ return 0;
+ }
+
+ if (m_captureMode & Audio) {
+ GstElement *audioConvert = gst_element_factory_make("audioconvert", "audioconvert");
+ GstElement *audioQueue = gst_element_factory_make("queue", "audio-encode-queue");
+ m_audioVolume = gst_element_factory_make("volume", "volume");
+ gst_bin_add_many(GST_BIN(encodeBin), audioConvert, audioQueue, m_audioVolume, NULL);
+
+ GstElement *audioEncoder = m_audioEncodeControl->createEncoder();
+ if (!audioEncoder) {
+ gst_object_unref(encodeBin);
+ qWarning() << "Could not create an audio encoder element:" << m_audioEncodeControl->audioSettings().codec();
+ return 0;
+ }
+
+ gst_bin_add(GST_BIN(encodeBin), audioEncoder);
+
+ if (!gst_element_link_many(audioConvert, audioQueue, m_audioVolume, audioEncoder, muxer, NULL)) {
+ gst_object_unref(encodeBin);
+ return 0;
+ }
+
+ g_object_set(G_OBJECT(m_audioVolume), "volume", (m_muted ? 0.0 : 1.0), NULL);
+
+ // add ghostpads
+ GstPad *pad = gst_element_get_static_pad(audioConvert, "sink");
+ gst_element_add_pad(GST_ELEMENT(encodeBin), gst_ghost_pad_new("audiosink", pad));
+ gst_object_unref(GST_OBJECT(pad));
+ }
+
+ if (m_captureMode & Video) {
+ GstElement *videoQueue = gst_element_factory_make("queue", "video-encode-queue");
+ GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-encoder");
+ GstElement *videoscale = gst_element_factory_make("videoscale","videoscale-encoder");
+ gst_bin_add_many(GST_BIN(encodeBin), videoQueue, colorspace, videoscale, NULL);
+
+ GstElement *videoEncoder = m_videoEncodeControl->createEncoder();
+ if (!videoEncoder) {
+ gst_object_unref(encodeBin);
+ qWarning() << "Could not create a video encoder element:" << m_videoEncodeControl->videoSettings().codec();
+ return 0;
+ }
+
+ gst_bin_add(GST_BIN(encodeBin), videoEncoder);
+
+ if (!gst_element_link_many(videoQueue, colorspace, videoscale, videoEncoder, muxer, NULL)) {
+ gst_object_unref(encodeBin);
+ return 0;
+ }
+
+ // add ghostpads
+ GstPad *pad = gst_element_get_static_pad(videoQueue, "sink");
+ gst_element_add_pad(GST_ELEMENT(encodeBin), gst_ghost_pad_new("videosink", pad));
+ gst_object_unref(GST_OBJECT(pad));
+ }
+
+ return encodeBin;
+}
+
+GstElement *QGstreamerCaptureSession::buildAudioSrc()
+{
+ GstElement *audioSrc = 0;
+ if (m_audioInputFactory)
+ audioSrc = m_audioInputFactory->buildElement();
+ else {
+
+#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
+ audioSrc = gst_element_factory_make("pulsesrc", "audio_src");
+#elif defined(QT_QWS_N810)
+ audioSrc = gst_element_factory_make("dsppcmsrc", "audio_src");
+#else
+ QString elementName = "alsasrc";
+ QString device;
+
+ if (m_captureDevice.startsWith("alsa:")) {
+ device = m_captureDevice.mid(QString("alsa:").length());
+ } else if (m_captureDevice.startsWith("oss:")) {
+ elementName = "osssrc";
+ device = m_captureDevice.mid(QString("oss:").length());
+ } else if (m_captureDevice.startsWith("pulseaudio:")) {
+ elementName = "pulsesrc";
+ } else {
+ elementName = "autoaudiosrc";
+ }
+
+ audioSrc = gst_element_factory_make(elementName.toAscii().constData(), "audio_src");
+ if (audioSrc && !device.isEmpty())
+ g_object_set(G_OBJECT(audioSrc), "device", device.toLocal8Bit().constData(), NULL);
+#endif
+ }
+
+ if (!audioSrc) {
+ emit error(int(QMediaRecorder::ResourceError), tr("Could not create an audio source element"));
+ audioSrc = gst_element_factory_make("fakesrc", NULL);
+ }
+
+ return audioSrc;
+}
+
+GstElement *QGstreamerCaptureSession::buildAudioPreview()
+{
+ GstElement *previewElement = 0;
+
+ if (m_audioPreviewFactory) {
+ previewElement = m_audioPreviewFactory->buildElement();
+ } else {
+
+
+#if 1
+ previewElement = gst_element_factory_make("fakesink", "audio-preview");
+#else
+ GstElement *bin = gst_bin_new("audio-preview-bin");
+ GstElement *visual = gst_element_factory_make("libvisual_lv_scope", "audio-preview");
+ GstElement *sink = gst_element_factory_make("ximagesink", NULL);
+ gst_bin_add_many(GST_BIN(bin), visual, sink, NULL);
+ gst_element_link_many(visual,sink, NULL);
+
+
+ // add ghostpads
+ GstPad *pad = gst_element_get_static_pad(visual, "sink");
+ Q_ASSERT(pad);
+ gst_element_add_pad(GST_ELEMENT(bin), gst_ghost_pad_new("audiosink", pad));
+ gst_object_unref(GST_OBJECT(pad));
+
+ previewElement = bin;
+#endif
+ }
+
+ return previewElement;
+}
+
+GstElement *QGstreamerCaptureSession::buildVideoSrc()
+{
+ GstElement *videoSrc = 0;
+ if (m_videoInputFactory) {
+ videoSrc = m_videoInputFactory->buildElement();
+ } else {
+ videoSrc = gst_element_factory_make("videotestsrc", "video_test_src");
+ //videoSrc = gst_element_factory_make("v4l2src", "video_test_src");
+ }
+
+ return videoSrc;
+}
+
+GstElement *QGstreamerCaptureSession::buildVideoPreview()
+{
+ GstElement *previewElement = 0;
+
+ if (m_viewfinderInterface) {
+ GstElement *bin = gst_bin_new("video-preview-bin");
+ GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-preview");
+ GstElement *capsFilter = gst_element_factory_make("capsfilter", "capsfilter-video-preview");
+ GstElement *preview = m_viewfinderInterface->videoSink();
+
+ gst_bin_add_many(GST_BIN(bin), colorspace, capsFilter, preview, NULL);
+ gst_element_link(colorspace,capsFilter);
+ gst_element_link(capsFilter,preview);
+
+ QSize resolution;
+ qreal frameRate = 0;
+
+ if (m_captureMode & Video) {
+ QVideoEncoderSettings videoSettings = m_videoEncodeControl->videoSettings();
+ resolution = videoSettings.resolution();
+ frameRate = videoSettings.frameRate();
+ } else if (m_captureMode & Image) {
+ resolution = m_imageEncodeControl->imageSettings().resolution();
+ }
+
+ if (!resolution.isEmpty() || frameRate > 0.001) {
+ GstCaps *caps = gst_caps_new_empty();
+ QStringList structureTypes;
+ structureTypes << "video/x-raw-yuv" << "video/x-raw-rgb";
+
+ foreach(const QString &structureType, structureTypes) {
+ GstStructure *structure = gst_structure_new(structureType.toAscii().constData(), NULL);
+
+ if (!resolution.isEmpty()) {
+ gst_structure_set(structure, "width", G_TYPE_INT, resolution.width(), NULL);
+ gst_structure_set(structure, "height", G_TYPE_INT, resolution.height(), NULL);
+ }
+
+ if (frameRate > 0.001) {
+ QPair<int,int> rate = m_videoEncodeControl->rateAsRational();
+
+ //qDebug() << "frame rate:" << num << denum;
+
+ gst_structure_set(structure, "framerate", GST_TYPE_FRACTION, rate.first, rate.second, NULL);
+ }
+
+ gst_caps_append_structure(caps,structure);
+ }
+
+ //qDebug() << "set video preview caps filter:" << gst_caps_to_string(caps);
+
+ g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
+
+ }
+
+ // add ghostpads
+ GstPad *pad = gst_element_get_static_pad(colorspace, "sink");
+ Q_ASSERT(pad);
+ gst_element_add_pad(GST_ELEMENT(bin), gst_ghost_pad_new("videosink", pad));
+ gst_object_unref(GST_OBJECT(pad));
+
+ previewElement = bin;
+ } else {
+#if 1
+ previewElement = gst_element_factory_make("fakesink", "video-preview");
+#else
+ GstElement *bin = gst_bin_new("video-preview-bin");
+ GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-preview");
+ GstElement *preview = gst_element_factory_make("ximagesink", "video-preview");
+ gst_bin_add_many(GST_BIN(bin), colorspace, preview, NULL);
+ gst_element_link(colorspace,preview);
+
+ // add ghostpads
+ GstPad *pad = gst_element_get_static_pad(colorspace, "sink");
+ Q_ASSERT(pad);
+ gst_element_add_pad(GST_ELEMENT(bin), gst_ghost_pad_new("videosink", pad));
+ gst_object_unref(GST_OBJECT(pad));
+
+ previewElement = bin;
+#endif
+ }
+
+ return previewElement;
+}
+
+
+static gboolean passImageFilter(GstElement *element,
+ GstBuffer *buffer,
+ void *appdata)
+{
+ Q_UNUSED(element);
+ Q_UNUSED(buffer);
+
+ QGstreamerCaptureSession *session = (QGstreamerCaptureSession *)appdata;
+ if (session->m_passImage || session->m_passPrerollImage) {
+ session->m_passImage = false;
+
+ if (session->m_passPrerollImage) {
+ session->m_passPrerollImage = false;
+ return TRUE;
+ }
+ session->m_passPrerollImage = false;
+
+ QImage img;
+
+ GstCaps *caps = gst_buffer_get_caps(buffer);
+ if (caps) {
+ GstStructure *structure = gst_caps_get_structure (caps, 0);
+ gint width = 0;
+ gint height = 0;
+
+ if (structure &&
+ gst_structure_get_int(structure, "width", &width) &&
+ gst_structure_get_int(structure, "height", &height) &&
+ width > 0 && height > 0) {
+ if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) {
+ guint32 fourcc = 0;
+ gst_structure_get_fourcc(structure, "format", &fourcc);
+
+ if (fourcc == GST_MAKE_FOURCC('I','4','2','0')) {
+ img = QImage(width/2, height/2, QImage::Format_RGB32);
+
+ const uchar *data = (const uchar *)buffer->data;
+
+ for (int y=0; y<height; y+=2) {
+ const uchar *yLine = data + y*width;
+ const uchar *uLine = data + width*height + y*width/4;
+ const uchar *vLine = data + width*height*5/4 + y*width/4;
+
+ for (int x=0; x<width; x+=2) {
+ const qreal Y = 1.164*(yLine[x]-16);
+ const int U = uLine[x/2]-128;
+ const int V = vLine[x/2]-128;
+
+ int b = qBound(0, int(Y + 2.018*U), 255);
+ int g = qBound(0, int(Y - 0.813*V - 0.391*U), 255);
+ int r = qBound(0, int(Y + 1.596*V), 255);
+
+ img.setPixel(x/2,y/2,qRgb(r,g,b));
+ }
+ }
+ }
+
+ } else if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) {
+ QImage::Format format = QImage::Format_Invalid;
+ int bpp = 0;
+ gst_structure_get_int(structure, "bpp", &bpp);
+
+ if (bpp == 24)
+ format = QImage::Format_RGB888;
+ else if (bpp == 32)
+ format = QImage::Format_RGB32;
+
+ if (format != QImage::Format_Invalid) {
+ img = QImage((const uchar *)buffer->data,
+ width,
+ height,
+ format);
+ img.bits(); //detach
+ }
+ }
+ }
+ gst_caps_unref(caps);
+ }
+
+ static int exposedSignalIndex = session->metaObject()->indexOfSignal("imageExposed(int)");
+ session->metaObject()->method(exposedSignalIndex).invoke(session,
+ Qt::QueuedConnection,
+ Q_ARG(int,session->m_imageRequestId));
+
+ static int capturedSignalIndex = session->metaObject()->indexOfSignal("imageCaptured(int,QImage)");
+ session->metaObject()->method(capturedSignalIndex).invoke(session,
+ Qt::QueuedConnection,
+ Q_ARG(int,session->m_imageRequestId),
+ Q_ARG(QImage,img));
+
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static gboolean saveImageFilter(GstElement *element,
+ GstBuffer *buffer,
+ GstPad *pad,
+ void *appdata)
+{
+ Q_UNUSED(element);
+ Q_UNUSED(pad);
+ QGstreamerCaptureSession *session = (QGstreamerCaptureSession *)appdata;
+
+ QString fileName = session->m_imageFileName;
+
+ if (!fileName.isEmpty()) {
+ QFile f(fileName);
+ if (f.open(QFile::WriteOnly)) {
+ f.write((const char *)buffer->data, buffer->size);
+ f.close();
+
+ static int signalIndex = session->metaObject()->indexOfSignal("imageSaved(int,QString)");
+ session->metaObject()->method(signalIndex).invoke(session,
+ Qt::QueuedConnection,
+ Q_ARG(int,session->m_imageRequestId),
+ Q_ARG(QString,fileName));
+ }
+ }
+
+ return TRUE;
+}
+
+GstElement *QGstreamerCaptureSession::buildImageCapture()
+{
+ GstElement *bin = gst_bin_new("image-capture-bin");
+ GstElement *queue = gst_element_factory_make("queue", "queue-image-capture");
+ GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-image-capture");
+ GstElement *encoder = gst_element_factory_make("jpegenc", "image-encoder");
+ GstElement *sink = gst_element_factory_make("fakesink","sink-image-capture");
+
+ GstPad *pad = gst_element_get_static_pad(queue, "src");
+ Q_ASSERT(pad);
+ gst_pad_add_buffer_probe(pad, G_CALLBACK(passImageFilter), this);
+
+ g_object_set(G_OBJECT(sink), "signal-handoffs", TRUE, NULL);
+ g_signal_connect(G_OBJECT(sink), "handoff",
+ G_CALLBACK(saveImageFilter), this);
+
+ gst_bin_add_many(GST_BIN(bin), queue, colorspace, encoder, sink, NULL);
+ gst_element_link_many(queue, colorspace, encoder, sink, NULL);
+
+ // add ghostpads
+ pad = gst_element_get_static_pad(queue, "sink");
+ Q_ASSERT(pad);
+ gst_element_add_pad(GST_ELEMENT(bin), gst_ghost_pad_new("imagesink", pad));
+ gst_object_unref(GST_OBJECT(pad));
+
+ m_passImage = false;
+ m_passPrerollImage = true;
+ m_imageFileName = QString();
+
+ return bin;
+}
+
+void QGstreamerCaptureSession::captureImage(int requestId, const QString &fileName)
+{
+ m_imageRequestId = requestId;
+ m_imageFileName = fileName;
+ m_passImage = true;
+}
+
+
+#define REMOVE_ELEMENT(element) { if (element) {gst_bin_remove(GST_BIN(m_pipeline), element); element = 0;} }
+
+bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMode newMode)
+{
+ REMOVE_ELEMENT(m_audioSrc);
+ REMOVE_ELEMENT(m_audioPreview);
+ REMOVE_ELEMENT(m_audioPreviewQueue);
+ REMOVE_ELEMENT(m_audioTee);
+ REMOVE_ELEMENT(m_videoSrc);
+ REMOVE_ELEMENT(m_videoPreview);
+ REMOVE_ELEMENT(m_videoPreviewQueue);
+ REMOVE_ELEMENT(m_videoTee);
+ REMOVE_ELEMENT(m_encodeBin);
+ REMOVE_ELEMENT(m_imageCaptureBin);
+ m_audioVolume = 0;
+
+ bool ok = true;
+
+ switch (newMode) {
+ case EmptyPipeline:
+ break;
+ case PreviewPipeline:
+ if (m_captureMode & Audio) {
+ m_audioSrc = buildAudioSrc();
+ m_audioPreview = buildAudioPreview();
+
+ ok &= m_audioSrc && m_audioPreview;
+
+ if (ok) {
+ gst_bin_add_many(GST_BIN(m_pipeline), m_audioSrc, m_audioPreview, NULL);
+ ok &= gst_element_link(m_audioSrc, m_audioPreview);
+ }
+ }
+ if (m_captureMode & Video || m_captureMode & Image) {
+ m_videoSrc = buildVideoSrc();
+ m_videoTee = gst_element_factory_make("tee", "video-preview-tee");
+ m_videoPreviewQueue = gst_element_factory_make("queue", "video-preview-queue");
+ m_videoPreview = buildVideoPreview();
+ m_imageCaptureBin = buildImageCapture();
+
+ ok &= m_videoSrc && m_videoTee && m_videoPreviewQueue && m_videoPreview && m_imageCaptureBin;
+
+ if (ok) {
+ gst_bin_add_many(GST_BIN(m_pipeline), m_videoSrc, m_videoTee,
+ m_videoPreviewQueue, m_videoPreview,
+ m_imageCaptureBin, NULL);
+
+ ok &= gst_element_link(m_videoSrc, m_videoTee);
+ ok &= gst_element_link(m_videoTee, m_videoPreviewQueue);
+ ok &= gst_element_link(m_videoPreviewQueue, m_videoPreview);
+ ok &= gst_element_link(m_videoTee, m_imageCaptureBin);
+ }
+ }
+ break;
+ case RecordingPipeline:
+ m_encodeBin = buildEncodeBin();
+ gst_bin_add(GST_BIN(m_pipeline), m_encodeBin);
+
+ if (m_captureMode & Audio) {
+ m_audioSrc = buildAudioSrc();
+ ok &= m_audioSrc != 0;
+
+ gst_bin_add(GST_BIN(m_pipeline), m_audioSrc);
+ ok &= gst_element_link(m_audioSrc, m_encodeBin);
+ }
+
+ if (m_captureMode & Video) {
+ m_videoSrc = buildVideoSrc();
+ ok &= m_videoSrc != 0;
+
+ gst_bin_add(GST_BIN(m_pipeline), m_videoSrc);
+ ok &= gst_element_link(m_videoSrc, m_encodeBin);
+ }
+
+ if (!m_metaData.isEmpty())
+ setMetaData(m_metaData);
+
+ break;
+ case PreviewAndRecordingPipeline:
+ m_encodeBin = buildEncodeBin();
+ if (m_encodeBin)
+ gst_bin_add(GST_BIN(m_pipeline), m_encodeBin);
+
+ ok &= m_encodeBin != 0;
+
+ if (ok && m_captureMode & Audio) {
+ m_audioSrc = buildAudioSrc();
+ m_audioPreview = buildAudioPreview();
+ m_audioTee = gst_element_factory_make("tee", NULL);
+ m_audioPreviewQueue = gst_element_factory_make("queue", NULL);
+
+ ok &= m_audioSrc && m_audioPreview && m_audioTee && m_audioPreviewQueue;
+
+ if (ok) {
+ gst_bin_add_many(GST_BIN(m_pipeline), m_audioSrc, m_audioTee,
+ m_audioPreviewQueue, m_audioPreview, NULL);
+ ok &= gst_element_link(m_audioSrc, m_audioTee);
+ ok &= gst_element_link(m_audioTee, m_audioPreviewQueue);
+ ok &= gst_element_link(m_audioPreviewQueue, m_audioPreview);
+ ok &= gst_element_link(m_audioTee, m_encodeBin);
+ }
+ }
+
+ if (ok && (m_captureMode & Video || m_captureMode & Image)) {
+ m_videoSrc = buildVideoSrc();
+ m_videoPreview = buildVideoPreview();
+ m_videoTee = gst_element_factory_make("tee", NULL);
+ m_videoPreviewQueue = gst_element_factory_make("queue", NULL);
+
+ ok &= m_videoSrc && m_videoPreview && m_videoTee && m_videoPreviewQueue;
+
+ if (ok) {
+ gst_bin_add_many(GST_BIN(m_pipeline), m_videoSrc, m_videoTee,
+ m_videoPreviewQueue, m_videoPreview, NULL);
+ ok &= gst_element_link(m_videoSrc, m_videoTee);
+ ok &= gst_element_link(m_videoTee, m_videoPreviewQueue);
+ ok &= gst_element_link(m_videoPreviewQueue, m_videoPreview);
+ }
+
+ if (ok && (m_captureMode & Video))
+ ok &= gst_element_link(m_videoTee, m_encodeBin);
+ }
+
+ if (!m_metaData.isEmpty())
+ setMetaData(m_metaData);
+
+
+ break;
+ }
+
+ if (!ok) {
+ emit error(int(QMediaRecorder::FormatError),tr("Failed to build media capture pipeline."));
+ }
+
+ dumpGraph( QString("rebuild_graph_%1_%2").arg(m_pipelineMode).arg(newMode) );
+ if (m_encodeBin) {
+ QString fileName = QString("rebuild_graph_encode_%1_%2").arg(m_pipelineMode).arg(newMode);
+#if !(GST_DISABLE_GST_DEBUG) && (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
+ _gst_debug_bin_to_dot_file(GST_BIN(m_encodeBin), GST_DEBUG_GRAPH_SHOW_ALL, fileName.toAscii());
+#endif
+ }
+
+ if (ok) {
+ m_pipelineMode = newMode;
+ } else {
+ m_pipelineMode = EmptyPipeline;
+
+ REMOVE_ELEMENT(m_audioSrc);
+ REMOVE_ELEMENT(m_audioPreview);
+ REMOVE_ELEMENT(m_audioPreviewQueue);
+ REMOVE_ELEMENT(m_audioTee);
+ REMOVE_ELEMENT(m_videoSrc);
+ REMOVE_ELEMENT(m_videoPreview);
+ REMOVE_ELEMENT(m_videoPreviewQueue);
+ REMOVE_ELEMENT(m_videoTee);
+ REMOVE_ELEMENT(m_encodeBin);
+ }
+
+ return ok;
+}
+
+void QGstreamerCaptureSession::dumpGraph(const QString &fileName)
+{
+#if !(GST_DISABLE_GST_DEBUG) && (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
+ _gst_debug_bin_to_dot_file(GST_BIN(m_pipeline),
+ GstDebugGraphDetails(/*GST_DEBUG_GRAPH_SHOW_ALL |*/ GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES),
+ fileName.toAscii());
+#endif
+}
+
+QUrl QGstreamerCaptureSession::outputLocation() const
+{
+ return m_sink;
+}
+
+bool QGstreamerCaptureSession::setOutputLocation(const QUrl& sink)
+{
+ m_sink = sink;
+ return true;
+}
+
+void QGstreamerCaptureSession::setAudioInput(QGstreamerElementFactory *audioInput)
+{
+ m_audioInputFactory = audioInput;
+}
+
+void QGstreamerCaptureSession::setAudioPreview(QGstreamerElementFactory *audioPreview)
+{
+ m_audioPreviewFactory = audioPreview;
+}
+
+void QGstreamerCaptureSession::setVideoInput(QGstreamerVideoInput *videoInput)
+{
+ m_videoInputFactory = videoInput;
+}
+
+void QGstreamerCaptureSession::setVideoPreview(QObject *viewfinder)
+{
+ m_viewfinderInterface = qobject_cast<QGstreamerVideoRendererInterface*>(viewfinder);
+ if (!m_viewfinderInterface)
+ viewfinder = 0;
+
+ if (m_viewfinder != viewfinder) {
+ bool oldReady = isReady();
+
+ if (m_viewfinder) {
+ disconnect(m_viewfinder, SIGNAL(sinkChanged()),
+ this, SIGNAL(viewfinderChanged()));
+ disconnect(m_viewfinder, SIGNAL(readyChanged(bool)),
+ this, SIGNAL(readyChanged(bool)));
+ }
+
+ m_viewfinder = viewfinder;
+ //m_viewfinderHasChanged = true;
+
+ if (m_viewfinder) {
+ connect(m_viewfinder, SIGNAL(sinkChanged()),
+ this, SIGNAL(viewfinderChanged()));
+ connect(m_viewfinder, SIGNAL(readyChanged(bool)),
+ this, SIGNAL(readyChanged(bool)));
+ }
+
+ emit viewfinderChanged();
+ if (oldReady != isReady())
+ emit readyChanged(isReady());
+ }
+}
+
+bool QGstreamerCaptureSession::isReady() const
+{
+ return m_viewfinderInterface != 0 && m_viewfinderInterface->isReady();
+}
+
+QGstreamerCaptureSession::State QGstreamerCaptureSession::state() const
+{
+ return m_state;
+}
+
+void QGstreamerCaptureSession::waitForStopped()
+{
+ GstState state = GST_STATE_PLAYING;
+ gst_element_get_state(m_pipeline, &state, 0, 0);
+
+ while (state != GST_STATE_NULL) {
+ qApp->processEvents();
+ gst_element_get_state(m_pipeline, &state, 0, 0);
+ }
+}
+
+void QGstreamerCaptureSession::setState(QGstreamerCaptureSession::State newState)
+{
+ if (newState == m_pendingState && !m_waitingForEos)
+ return;
+
+ m_pendingState = newState;
+
+ PipelineMode newMode = EmptyPipeline;
+
+ switch (newState) {
+ case PausedState:
+ case RecordingState:
+ newMode = PreviewAndRecordingPipeline;
+ break;
+ case PreviewState:
+ newMode = PreviewPipeline;
+ break;
+ case StoppedState:
+ newMode = EmptyPipeline;
+ break;
+ }
+
+ if (newMode != m_pipelineMode) {
+ if (m_pipelineMode == PreviewAndRecordingPipeline) {
+ if (!m_waitingForEos) {
+ m_waitingForEos = true;
+ //qDebug() << "Waiting for EOS";
+ //with live sources it's necessary to send EOS even to pipeline
+ //before going to STOPPED state
+ gst_element_send_event(m_pipeline, gst_event_new_eos());
+ // Unless gstreamer is in GST_STATE_PLAYING our EOS message will not be received.
+ gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
+
+ return;
+ } else {
+ m_waitingForEos = false;
+ //qDebug() << "EOS received";
+ }
+ }
+
+ //select suitable default codecs/containers, if necessary
+ m_recorderControl->applySettings();
+
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+
+ //It would be better to do this async. but
+ //gstreamer doesn't notify about pipeline went to NULL state
+ waitForStopped();
+ if (!rebuildGraph(newMode)) {
+ m_pendingState = StoppedState;
+ m_state = StoppedState;
+ emit stateChanged(StoppedState);
+
+ return;
+ }
+ }
+
+ switch (newState) {
+ case PausedState:
+ gst_element_set_state(m_pipeline, GST_STATE_PAUSED);
+ break;
+ case RecordingState:
+ case PreviewState:
+ gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
+ break;
+ case StoppedState:
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+ }
+
+ //we have to do it here, since gstreamer will not emit bus messages any more
+ if (newState == StoppedState) {
+ m_state = StoppedState;
+ emit stateChanged(StoppedState);
+ }
+}
+
+
+qint64 QGstreamerCaptureSession::duration() const
+{
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 duration = 0;
+
+ if ( m_encodeBin && gst_element_query_position(m_encodeBin, &format, &duration))
+ return duration / 1000000;
+ else
+ return 0;
+}
+
+void QGstreamerCaptureSession::setCaptureDevice(const QString &deviceName)
+{
+ m_captureDevice = deviceName;
+}
+
+void QGstreamerCaptureSession::setMetaData(const QMap<QByteArray, QVariant> &data)
+{
+ //qDebug() << "QGstreamerCaptureSession::setMetaData" << data;
+ m_metaData = data;
+
+ if (m_encodeBin) {
+ GstIterator *elements = gst_bin_iterate_all_by_interface(GST_BIN(m_encodeBin), GST_TYPE_TAG_SETTER);
+ GstElement *element = 0;
+ while (gst_iterator_next(elements, (void**)&element) == GST_ITERATOR_OK) {
+ //qDebug() << "found element with tag setter interface:" << gst_element_get_name(element);
+ QMapIterator<QByteArray, QVariant> it(data);
+ while (it.hasNext()) {
+ it.next();
+ const QString tagName = it.key();
+ const QVariant tagValue = it.value();
+
+
+ switch(tagValue.type()) {
+ case QVariant::String:
+ gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+ GST_TAG_MERGE_REPLACE_ALL,
+ tagName.toUtf8().constData(),
+ tagValue.toString().toUtf8().constData(),
+ NULL);
+ break;
+ case QVariant::Int:
+ case QVariant::LongLong:
+ gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+ GST_TAG_MERGE_REPLACE_ALL,
+ tagName.toUtf8().constData(),
+ tagValue.toInt(),
+ NULL);
+ break;
+ case QVariant::Double:
+ gst_tag_setter_add_tags(GST_TAG_SETTER(element),
+ GST_TAG_MERGE_REPLACE_ALL,
+ tagName.toUtf8().constData(),
+ tagValue.toDouble(),
+ NULL);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ }
+ }
+}
+
+bool QGstreamerCaptureSession::processSyncMessage(const QGstreamerMessage &message)
+{
+ GstMessage* gm = message.rawMessage();
+
+ if (gm && GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) {
+ if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoPreview))
+ m_viewfinderInterface->handleSyncMessage(gm);
+
+ if (gst_structure_has_name(gm->structure, "prepare-xwindow-id")) {
+ if (m_audioPreviewFactory)
+ m_audioPreviewFactory->prepareWinId();
+
+ if (m_viewfinderInterface)
+ m_viewfinderInterface->precessNewStream();
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void QGstreamerCaptureSession::busMessage(const QGstreamerMessage &message)
+{
+ GstMessage* gm = message.rawMessage();
+
+ if (gm) {
+ if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ERROR) {
+ GError *err;
+ gchar *debug;
+ gst_message_parse_error (gm, &err, &debug);
+ emit error(int(QMediaRecorder::ResourceError),QString::fromUtf8(err->message));
+ g_error_free (err);
+ g_free (debug);
+ }
+
+ if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_pipeline)) {
+ switch (GST_MESSAGE_TYPE(gm)) {
+ case GST_MESSAGE_DURATION:
+ break;
+
+ case GST_MESSAGE_EOS:
+ if (m_waitingForEos)
+ setState(m_pendingState);
+ break;
+
+ case GST_MESSAGE_STATE_CHANGED:
+ {
+
+ GstState oldState;
+ GstState newState;
+ GstState pending;
+
+ gst_message_parse_state_changed(gm, &oldState, &newState, &pending);
+
+ QStringList states;
+ states << "GST_STATE_VOID_PENDING" << "GST_STATE_NULL" << "GST_STATE_READY" << "GST_STATE_PAUSED" << "GST_STATE_PLAYING";
+
+ /*
+ qDebug() << QString("state changed: old: %1 new: %2 pending: %3") \
+ .arg(states[oldState]) \
+ .arg(states[newState]) \
+ .arg(states[pending]);
+
+ #define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
+
+ qDebug() << "Current session state:" << ENUM_NAME(QGstreamerCaptureSession,"State",m_state);
+ qDebug() << "Pending session state:" << ENUM_NAME(QGstreamerCaptureSession,"State",m_pendingState);
+ */
+
+ switch (newState) {
+ case GST_STATE_VOID_PENDING:
+ case GST_STATE_NULL:
+ case GST_STATE_READY:
+ if (m_state != StoppedState && m_pendingState == StoppedState) {
+ emit stateChanged(m_state = StoppedState);
+ dumpGraph("stopped");
+ }
+ break;
+ case GST_STATE_PAUSED:
+ if (m_state != PausedState && m_pendingState == PausedState)
+ emit stateChanged(m_state = PausedState);
+ dumpGraph("paused");
+
+ if (m_pipelineMode == RecordingPipeline && !m_metaData.isEmpty())
+ setMetaData(m_metaData);
+ break;
+ case GST_STATE_PLAYING:
+ {
+ if ((m_pendingState == PreviewState || m_pendingState == RecordingState) &&
+ m_state != m_pendingState)
+ {
+ m_state = m_pendingState;
+ emit stateChanged(m_state);
+ }
+
+ if (m_pipelineMode == PreviewPipeline)
+ dumpGraph("preview");
+ else
+ dumpGraph("recording");
+ }
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ //qDebug() << "New session state:" << ENUM_NAME(QGstreamerCaptureSession,"State",m_state);
+ }
+
+ if (m_videoPreview && m_viewfinderInterface &&
+ GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoPreview))
+ m_viewfinderInterface->handleBusMessage(gm);
+ }
+}
+
+void QGstreamerCaptureSession::setMuted(bool muted)
+{
+ if (m_muted != muted) {
+ m_muted = muted;
+ if (m_audioVolume)
+ g_object_set(G_OBJECT(m_audioVolume), "volume", (m_muted ? 0.0 : 1.0), NULL);
+ emit mutedChanged(muted);
+ }
+}
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h
new file mode 100644
index 000000000..f04a49be2
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERCAPTURESESSION_H
+#define QGSTREAMERCAPTURESESSION_H
+
+#include <qmediarecordercontrol.h>
+#include <qmediarecorder.h>
+
+#include <QtCore/qurl.h>
+
+#include <gst/gst.h>
+
+#include "qgstreamerbushelper.h"
+
+QT_USE_NAMESPACE
+
+class QGstreamerMessage;
+class QGstreamerBusHelper;
+class QGstreamerAudioEncode;
+class QGstreamerVideoEncode;
+class QGstreamerImageEncode;
+class QGstreamerRecorderControl;
+class QGstreamerMediaContainerControl;
+class QGstreamerVideoRendererInterface;
+
+class QGstreamerElementFactory
+{
+public:
+ virtual GstElement *buildElement() = 0;
+ virtual void prepareWinId() {}
+};
+
+class QGstreamerVideoInput : public QGstreamerElementFactory
+{
+public:
+ virtual QList<qreal> supportedFrameRates(const QSize &frameSize = QSize()) const = 0;
+ virtual QList<QSize> supportedResolutions(qreal frameRate = -1) const = 0;
+};
+
+class QGstreamerCaptureSession : public QObject, public QGstreamerSyncEventFilter
+{
+ Q_OBJECT
+ Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged)
+ Q_ENUMS(State)
+ Q_ENUMS(CaptureMode)
+public:
+ enum CaptureMode { Audio = 1, Video = 2, Image=4, AudioAndVideo = Audio | Video };
+ enum State { StoppedState, PreviewState, PausedState, RecordingState };
+
+ QGstreamerCaptureSession(CaptureMode captureMode, QObject *parent);
+ ~QGstreamerCaptureSession();
+
+ CaptureMode captureMode() const { return m_captureMode; }
+ void setCaptureMode(CaptureMode);
+
+ QUrl outputLocation() const;
+ bool setOutputLocation(const QUrl& sink);
+
+ QGstreamerAudioEncode *audioEncodeControl() const { return m_audioEncodeControl; }
+ QGstreamerVideoEncode *videoEncodeControl() const { return m_videoEncodeControl; }
+ QGstreamerImageEncode *imageEncodeControl() const { return m_imageEncodeControl; }
+
+ QGstreamerRecorderControl *recorderControl() const { return m_recorderControl; }
+ QGstreamerMediaContainerControl *mediaContainerControl() const { return m_mediaContainerControl; }
+
+ QGstreamerElementFactory *audioInput() const { return m_audioInputFactory; }
+ void setAudioInput(QGstreamerElementFactory *audioInput);
+
+ QGstreamerElementFactory *audioPreview() const { return m_audioPreviewFactory; }
+ void setAudioPreview(QGstreamerElementFactory *audioPreview);
+
+ QGstreamerVideoInput *videoInput() const { return m_videoInputFactory; }
+ void setVideoInput(QGstreamerVideoInput *videoInput);
+
+ QObject *videoPreview() const { return m_viewfinder; }
+ void setVideoPreview(QObject *viewfinder);
+
+ void captureImage(int requestId, const QString &fileName);
+
+ State state() const;
+ qint64 duration() const;
+ bool isMuted() const { return m_muted; }
+
+ bool isReady() const;
+
+ bool processSyncMessage(const QGstreamerMessage &message);
+
+signals:
+ void stateChanged(QGstreamerCaptureSession::State state);
+ void durationChanged(qint64 duration);
+ void error(int error, const QString &errorString);
+ void imageExposed(int requestId);
+ void imageCaptured(int requestId, const QImage &img);
+ void imageSaved(int requestId, const QString &path);
+ void mutedChanged(bool);
+ void readyChanged(bool);
+ void viewfinderChanged();
+
+public slots:
+ void setState(QGstreamerCaptureSession::State);
+ void setCaptureDevice(const QString &deviceName);
+
+ void dumpGraph(const QString &fileName);
+
+ void setMetaData(const QMap<QByteArray, QVariant>&);
+ void setMuted(bool);
+
+private slots:
+ void busMessage(const QGstreamerMessage &message);
+
+private:
+ enum PipelineMode { EmptyPipeline, PreviewPipeline, RecordingPipeline, PreviewAndRecordingPipeline };
+
+ GstElement *buildEncodeBin();
+ GstElement *buildAudioSrc();
+ GstElement *buildAudioPreview();
+ GstElement *buildVideoSrc();
+ GstElement *buildVideoPreview();
+ GstElement *buildImageCapture();
+
+ void waitForStopped();
+ bool rebuildGraph(QGstreamerCaptureSession::PipelineMode newMode);
+
+ QUrl m_sink;
+ QString m_captureDevice;
+ State m_state;
+ State m_pendingState;
+ bool m_waitingForEos;
+ PipelineMode m_pipelineMode;
+ QGstreamerCaptureSession::CaptureMode m_captureMode;
+ QMap<QByteArray, QVariant> m_metaData;
+
+ QGstreamerElementFactory *m_audioInputFactory;
+ QGstreamerElementFactory *m_audioPreviewFactory;
+ QGstreamerVideoInput *m_videoInputFactory;
+ QObject *m_viewfinder;
+ QGstreamerVideoRendererInterface *m_viewfinderInterface;
+
+ QGstreamerAudioEncode *m_audioEncodeControl;
+ QGstreamerVideoEncode *m_videoEncodeControl;
+ QGstreamerImageEncode *m_imageEncodeControl;
+ QGstreamerRecorderControl *m_recorderControl;
+ QGstreamerMediaContainerControl *m_mediaContainerControl;
+
+ QGstreamerBusHelper *m_busHelper;
+ GstBus* m_bus;
+ GstElement *m_pipeline;
+
+ GstElement *m_audioSrc;
+ GstElement *m_audioTee;
+ GstElement *m_audioPreviewQueue;
+ GstElement *m_audioPreview;
+ GstElement *m_audioVolume;
+ bool m_muted;
+
+ GstElement *m_videoSrc;
+ GstElement *m_videoTee;
+ GstElement *m_videoPreviewQueue;
+ GstElement *m_videoPreview;
+
+ GstElement *m_imageCaptureBin;
+
+ GstElement *m_encodeBin;
+
+public:
+ bool m_passImage;
+ bool m_passPrerollImage;
+ QString m_imageFileName;
+ int m_imageRequestId;
+};
+
+#endif // QGSTREAMERCAPTURESESSION_H
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerimagecapturecontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamerimagecapturecontrol.cpp
new file mode 100644
index 000000000..99c3b1665
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamerimagecapturecontrol.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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 "qgstreamerimagecapturecontrol.h"
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+
+QGstreamerImageCaptureControl::QGstreamerImageCaptureControl(QGstreamerCaptureSession *session)
+ :QCameraImageCaptureControl(session), m_session(session), m_ready(false), m_lastId(0)
+{
+ connect(m_session, SIGNAL(stateChanged(QGstreamerCaptureSession::State)), SLOT(updateState()));
+ connect(m_session, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int)));
+ connect(m_session, SIGNAL(imageCaptured(int,QImage)), this, SIGNAL(imageCaptured(int,QImage)));
+ connect(m_session, SIGNAL(imageSaved(int,QString)), this, SIGNAL(imageSaved(int,QString)));
+}
+
+QGstreamerImageCaptureControl::~QGstreamerImageCaptureControl()
+{
+}
+
+bool QGstreamerImageCaptureControl::isReadyForCapture() const
+{
+ return m_ready;
+}
+
+int QGstreamerImageCaptureControl::capture(const QString &fileName)
+{
+ QString path = fileName;
+ if (path.isEmpty()) {
+ int lastImage = 0;
+ QDir outputDir = QDir::currentPath();
+ foreach(QString fileName, outputDir.entryList(QStringList() << "img_*.jpg")) {
+ int imgNumber = fileName.mid(4, fileName.size()-8).toInt();
+ lastImage = qMax(lastImage, imgNumber);
+ }
+
+ path = QString("img_%1.jpg").arg(lastImage+1,
+ 4, //fieldWidth
+ 10,
+ QLatin1Char('0'));
+ }
+ m_lastId++;
+
+ m_session->captureImage(m_lastId, path);
+
+ return m_lastId;
+}
+
+void QGstreamerImageCaptureControl::cancelCapture()
+{
+
+}
+
+void QGstreamerImageCaptureControl::updateState()
+{
+ bool ready = m_session->state() == QGstreamerCaptureSession::PreviewState;
+ if (m_ready != ready) {
+ emit readyForCaptureChanged(m_ready = ready);
+ }
+}
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerimagecapturecontrol.h b/src/plugins/gstreamer/mediacapture/qgstreamerimagecapturecontrol.h
new file mode 100644
index 000000000..898162440
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamerimagecapturecontrol.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** 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 QGSTREAMERIMAGECAPTURECONTROL_H
+#define QGSTREAMERIMAGECAPTURECONTROL_H
+
+#include <qcameraimagecapturecontrol.h>
+#include "qgstreamercapturesession.h"
+QT_USE_NAMESPACE
+
+class QGstreamerImageCaptureControl : public QCameraImageCaptureControl
+{
+ Q_OBJECT
+public:
+ QGstreamerImageCaptureControl(QGstreamerCaptureSession *session);
+ virtual ~QGstreamerImageCaptureControl();
+
+ QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; }
+ void setDriveMode(QCameraImageCapture::DriveMode) {}
+
+ bool isReadyForCapture() const;
+ int capture(const QString &fileName);
+ void cancelCapture();
+
+private slots:
+ void updateState();
+
+private:
+ QGstreamerCaptureSession *m_session;
+ bool m_ready;
+ int m_lastId;
+};
+
+#endif // QGSTREAMERCAPTURECORNTROL_H
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerimageencode.cpp b/src/plugins/gstreamer/mediacapture/qgstreamerimageencode.cpp
new file mode 100644
index 000000000..5aef97794
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamerimageencode.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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 "qgstreamerimageencode.h"
+#include "qgstreamercapturesession.h"
+
+#include <QtCore/qdebug.h>
+
+#include <math.h>
+
+QGstreamerImageEncode::QGstreamerImageEncode(QGstreamerCaptureSession *session)
+ :QImageEncoderControl(session), m_session(session)
+{
+}
+
+QGstreamerImageEncode::~QGstreamerImageEncode()
+{
+}
+
+QList<QSize> QGstreamerImageEncode::supportedResolutions(const QImageEncoderSettings &, bool *continuous) const
+{
+ if (continuous)
+ *continuous = m_session->videoInput() != 0;
+
+ return m_session->videoInput() ? m_session->videoInput()->supportedResolutions() : QList<QSize>();
+}
+
+QStringList QGstreamerImageEncode::supportedImageCodecs() const
+{
+ return QStringList() << "jpeg";
+}
+
+QString QGstreamerImageEncode::imageCodecDescription(const QString &codecName) const
+{
+ if (codecName == "jpeg")
+ return tr("JPEG image encoder");
+
+ return QString();
+}
+
+QImageEncoderSettings QGstreamerImageEncode::imageSettings() const
+{
+ return m_settings;
+}
+
+void QGstreamerImageEncode::setImageSettings(const QImageEncoderSettings &settings)
+{
+ if (m_settings != settings) {
+ m_settings = settings;
+ emit settingsChanged();
+ }
+}
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerimageencode.h b/src/plugins/gstreamer/mediacapture/qgstreamerimageencode.h
new file mode 100644
index 000000000..b66ba75f8
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamerimageencode.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** 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 QGSTREAMERIMAGEENCODE_H
+#define QGSTREAMERIMAGEENCODE_H
+
+class QGstreamerCaptureSession;
+
+#include <qimageencodercontrol.h>
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+
+#include <gst/gst.h>
+QT_USE_NAMESPACE
+
+class QGstreamerImageEncode : public QImageEncoderControl
+{
+ Q_OBJECT
+public:
+ QGstreamerImageEncode(QGstreamerCaptureSession *session);
+ virtual ~QGstreamerImageEncode();
+
+ QList<QSize> supportedResolutions(const QImageEncoderSettings &settings = QImageEncoderSettings(),
+ bool *continuous = 0) const;
+
+ QStringList supportedImageCodecs() const;
+ QString imageCodecDescription(const QString &codecName) const;
+
+ QImageEncoderSettings imageSettings() const;
+ void setImageSettings(const QImageEncoderSettings &settings);
+
+Q_SIGNALS:
+ void settingsChanged();
+
+private:
+ QImageEncoderSettings m_settings;
+
+ QGstreamerCaptureSession *m_session;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.cpp
new file mode 100644
index 000000000..34c43e3ac
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamermediacontainercontrol.h"
+
+
+#include <QtCore/qdebug.h>
+
+QGstreamerMediaContainerControl::QGstreamerMediaContainerControl(QObject *parent)
+ :QMediaContainerControl(parent)
+{
+ QList<QByteArray> formatCandidates;
+ formatCandidates << "matroska" << "ogg" << "mp4" << "wav" << "quicktime" << "avi" << "3gpp";
+ formatCandidates << "flv" << "amr" << "asf" << "dv" << "gif";
+ formatCandidates << "mpeg" << "vob" << "mpegts" << "3g2" << "3gp";
+ formatCandidates << "raw";
+
+ m_elementNames["matroska"] = "matroskamux";
+ m_elementNames["ogg"] = "oggmux";
+ m_elementNames["mp4"] = "ffmux_mp4";
+ m_elementNames["quicktime"] = "ffmux_mov";
+ m_elementNames["avi"] = "avimux";
+ m_elementNames["3gpp"] = "gppmux";
+ m_elementNames["flv"] = "flvmux";
+ m_elementNames["wav"] = "wavenc";
+ m_elementNames["amr"] = "ffmux_amr";
+ m_elementNames["asf"] = "ffmux_asf";
+ m_elementNames["dv"] = "ffmux_dv";
+ m_elementNames["gif"] = "ffmux_gif";
+ m_elementNames["mpeg"] = "ffmux_mpeg";
+ m_elementNames["vob"] = "ffmux_vob";
+ m_elementNames["mpegts"] = "ffmux_mpegts";
+ m_elementNames["3g2"] = "ffmux_3g2";
+ m_elementNames["3gp"] = "ffmux_3gp";
+ m_elementNames["raw"] = "identity";
+
+ m_containerExtensions["matroska"] = "mkv";
+ m_containerExtensions["quicktime"] = "mov";
+ m_containerExtensions["mpegts"] = "m2t";
+ m_containerExtensions["mpeg"] = "mpg";
+
+ QSet<QString> allTypes;
+
+ foreach( const QByteArray& formatName, formatCandidates ) {
+ QByteArray elementName = m_elementNames[formatName];
+ GstElementFactory *factory = gst_element_factory_find(elementName.constData());
+ if (factory) {
+ m_supportedContainers.append(formatName);
+ const gchar *descr = gst_element_factory_get_description(factory);
+ m_containerDescriptions.insert(formatName, QString::fromUtf8(descr));
+
+
+ if (formatName == QByteArray("raw")) {
+ m_streamTypes.insert(formatName, allTypes);
+ } else {
+ QSet<QString> types = supportedStreamTypes(factory, GST_PAD_SINK);
+ m_streamTypes.insert(formatName, types);
+ allTypes.unite(types);
+ }
+
+ gst_object_unref(GST_OBJECT(factory));
+ }
+ }
+
+ //if (!m_supportedContainers.isEmpty())
+ // setContainerMimeType(m_supportedContainers[0]);
+}
+
+QSet<QString> QGstreamerMediaContainerControl::supportedStreamTypes(GstElementFactory *factory, GstPadDirection direction)
+{
+ QSet<QString> types;
+ const GList *pads = gst_element_factory_get_static_pad_templates(factory);
+ for (const GList *pad = pads; pad; pad = g_list_next(pad)) {
+ GstStaticPadTemplate *templ = (GstStaticPadTemplate*)pad->data;
+ if (templ->direction == direction) {
+ GstCaps *caps = gst_static_caps_get(&templ->static_caps);
+ for (uint i=0; i<gst_caps_get_size(caps); i++) {
+ GstStructure *structure = gst_caps_get_structure(caps, i);
+ types.insert( QString::fromUtf8(gst_structure_get_name(structure)) );
+ }
+ gst_caps_unref(caps);
+ }
+ }
+
+ return types;
+}
+
+
+QSet<QString> QGstreamerMediaContainerControl::supportedStreamTypes(const QString &container) const
+{
+ return m_streamTypes.value(container);
+}
+
+QString QGstreamerMediaContainerControl::containerExtension() const
+{
+ return m_containerExtensions.value(m_format, m_format);
+}
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.h b/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.h
new file mode 100644
index 000000000..57e0a5bf1
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERMEDIACONTAINERCONTROL_H
+#define QGSTREAMERMEDIACONTAINERCONTROL_H
+
+#include <qmediacontainercontrol.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qset.h>
+
+#include <gst/gst.h>
+
+QT_USE_NAMESPACE
+
+class QGstreamerMediaContainerControl : public QMediaContainerControl
+{
+Q_OBJECT
+public:
+ QGstreamerMediaContainerControl(QObject *parent);
+ virtual ~QGstreamerMediaContainerControl() {};
+
+ virtual QStringList supportedContainers() const { return m_supportedContainers; }
+ virtual QString containerMimeType() const { return m_format; }
+ virtual void setContainerMimeType(const QString &formatMimeType) { m_format = formatMimeType; }
+
+ virtual QString containerDescription(const QString &formatMimeType) const { return m_containerDescriptions.value(formatMimeType); }
+
+ QByteArray formatElementName() const { return m_elementNames.value(containerMimeType()); }
+
+ QSet<QString> supportedStreamTypes(const QString &container) const;
+
+ static QSet<QString> supportedStreamTypes(GstElementFactory *factory, GstPadDirection direction);
+
+ QString containerExtension() const;
+
+private:
+ QString m_format;
+ QStringList m_supportedContainers;
+ QMap<QString,QByteArray> m_elementNames;
+ QMap<QString, QString> m_containerDescriptions;
+ QMap<QString, QString> m_containerExtensions;
+ QMap<QString, QSet<QString> > m_streamTypes;
+};
+
+#endif // QGSTREAMERMEDIACONTAINERCONTROL_H
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp
new file mode 100644
index 000000000..24b28dead
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamerrecordercontrol.h"
+#include "qgstreameraudioencode.h"
+#include "qgstreamervideoencode.h"
+#include "qgstreamermediacontainercontrol.h"
+#include <QtCore/QDebug>
+
+QGstreamerRecorderControl::QGstreamerRecorderControl(QGstreamerCaptureSession *session)
+ :QMediaRecorderControl(session), m_session(session), m_state(QMediaRecorder::StoppedState)
+{
+ connect(m_session, SIGNAL(stateChanged(QGstreamerCaptureSession::State)), SLOT(updateState()));
+ connect(m_session, SIGNAL(error(int,QString)), SIGNAL(error(int,QString)));
+ connect(m_session, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged(qint64)));
+ connect(m_session, SIGNAL(mutedChanged(bool)), SIGNAL(mutedChanged(bool)));
+ m_hasPreviewState = m_session->captureMode() != QGstreamerCaptureSession::Audio;
+}
+
+QGstreamerRecorderControl::~QGstreamerRecorderControl()
+{
+}
+
+QUrl QGstreamerRecorderControl::outputLocation() const
+{
+ return m_session->outputLocation();
+}
+
+bool QGstreamerRecorderControl::setOutputLocation(const QUrl &sink)
+{
+ m_outputLocation = sink;
+ m_session->setOutputLocation(sink);
+ return true;
+}
+
+
+QMediaRecorder::State QGstreamerRecorderControl::state() const
+{
+ switch ( m_session->state() ) {
+ case QGstreamerCaptureSession::RecordingState:
+ return QMediaRecorder::RecordingState;
+ case QGstreamerCaptureSession::PausedState:
+ return QMediaRecorder::PausedState;
+ case QGstreamerCaptureSession::PreviewState:
+ case QGstreamerCaptureSession::StoppedState:
+ return QMediaRecorder::StoppedState;
+ }
+
+ return QMediaRecorder::StoppedState;
+
+}
+
+void QGstreamerRecorderControl::updateState()
+{
+ QMediaRecorder::State newState = state();
+ if (m_state != newState) {
+ m_state = newState;
+ emit stateChanged(m_state);
+ }
+}
+
+qint64 QGstreamerRecorderControl::duration() const
+{
+ return m_session->duration();
+}
+
+void QGstreamerRecorderControl::record()
+{
+ if (m_outputLocation.isEmpty()) {
+ QString container = m_session->mediaContainerControl()->containerExtension();
+ if (container.isEmpty())
+ container = "raw";
+
+ m_session->setOutputLocation(QUrl(generateFileName(defaultDir(), container)));
+ }
+
+ m_session->dumpGraph("before-record");
+ if (!m_hasPreviewState || m_session->state() != QGstreamerCaptureSession::StoppedState) {
+ m_session->setState(QGstreamerCaptureSession::RecordingState);
+ } else
+ emit error(QMediaRecorder::ResourceError, tr("Service has not been started"));
+
+ m_session->dumpGraph("after-record");
+}
+
+void QGstreamerRecorderControl::pause()
+{
+ m_session->dumpGraph("before-pause");
+ if (!m_hasPreviewState || m_session->state() != QGstreamerCaptureSession::StoppedState) {
+ m_session->setState(QGstreamerCaptureSession::PausedState);
+ } else
+ emit error(QMediaRecorder::ResourceError, tr("Service has not been started"));
+}
+
+void QGstreamerRecorderControl::stop()
+{
+ if (!m_hasPreviewState) {
+ m_session->setState(QGstreamerCaptureSession::StoppedState);
+ } else {
+ if (m_session->state() != QGstreamerCaptureSession::StoppedState)
+ m_session->setState(QGstreamerCaptureSession::PreviewState);
+ }
+}
+
+void QGstreamerRecorderControl::applySettings()
+{
+ //Check the codecs are compatible with container,
+ //and choose the compatible codecs/container if omitted
+ QGstreamerAudioEncode *audioEncodeControl = m_session->audioEncodeControl();
+ QGstreamerVideoEncode *videoEncodeControl = m_session->videoEncodeControl();
+ QGstreamerMediaContainerControl *mediaContainerControl = m_session->mediaContainerControl();
+
+ bool needAudio = m_session->captureMode() & QGstreamerCaptureSession::Audio;
+ bool needVideo = m_session->captureMode() & QGstreamerCaptureSession::Video;
+
+ QStringList containerCandidates;
+ if (mediaContainerControl->containerMimeType().isEmpty())
+ containerCandidates = mediaContainerControl->supportedContainers();
+ else
+ containerCandidates << mediaContainerControl->containerMimeType();
+
+
+ QStringList audioCandidates;
+ if (needAudio) {
+ QAudioEncoderSettings audioSettings = audioEncodeControl->audioSettings();
+ if (audioSettings.codec().isEmpty())
+ audioCandidates = audioEncodeControl->supportedAudioCodecs();
+ else
+ audioCandidates << audioSettings.codec();
+ }
+
+ QStringList videoCandidates;
+ if (needVideo) {
+ QVideoEncoderSettings videoSettings = videoEncodeControl->videoSettings();
+ if (videoSettings.codec().isEmpty())
+ videoCandidates = videoEncodeControl->supportedVideoCodecs();
+ else
+ videoCandidates << videoSettings.codec();
+ }
+
+ QString container;
+ QString audioCodec;
+ QString videoCodec;
+
+ foreach (const QString &containerCandidate, containerCandidates) {
+ QSet<QString> supportedTypes = mediaContainerControl->supportedStreamTypes(containerCandidate);
+
+ audioCodec.clear();
+ videoCodec.clear();
+
+ if (needAudio) {
+ bool found = false;
+ foreach (const QString &audioCandidate, audioCandidates) {
+ QSet<QString> audioTypes = audioEncodeControl->supportedStreamTypes(audioCandidate);
+ if (!audioTypes.intersect(supportedTypes).isEmpty()) {
+ found = true;
+ audioCodec = audioCandidate;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+ }
+
+ if (needVideo) {
+ bool found = false;
+ foreach (const QString &videoCandidate, videoCandidates) {
+ QSet<QString> videoTypes = videoEncodeControl->supportedStreamTypes(videoCandidate);
+ if (!videoTypes.intersect(supportedTypes).isEmpty()) {
+ found = true;
+ videoCodec = videoCandidate;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+ }
+
+ container = containerCandidate;
+ break;
+ }
+
+ if (container.isEmpty()) {
+ emit error(QMediaRecorder::FormatError, tr("Not compatible codecs and container format."));
+ } else {
+ mediaContainerControl->setContainerMimeType(container);
+
+ if (needAudio) {
+ QAudioEncoderSettings audioSettings = audioEncodeControl->audioSettings();
+ audioSettings.setCodec(audioCodec);
+ audioEncodeControl->setAudioSettings(audioSettings);
+ }
+
+ if (needVideo) {
+ QVideoEncoderSettings videoSettings = videoEncodeControl->videoSettings();
+ videoSettings.setCodec(videoCodec);
+ videoEncodeControl->setVideoSettings(videoSettings);
+ }
+ }
+}
+
+
+bool QGstreamerRecorderControl::isMuted() const
+{
+ return m_session->isMuted();
+}
+
+void QGstreamerRecorderControl::setMuted(bool muted)
+{
+ m_session->setMuted(muted);
+}
+
+QDir QGstreamerRecorderControl::defaultDir() const
+{
+ QStringList dirCandidates;
+
+#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
+ dirCandidates << QLatin1String("/home/user/MyDocs");
+#endif
+
+ dirCandidates << QDir::home().filePath("Documents");
+ dirCandidates << QDir::home().filePath("My Documents");
+ dirCandidates << QDir::homePath();
+ dirCandidates << QDir::currentPath();
+ dirCandidates << QDir::tempPath();
+
+ foreach (const QString &path, dirCandidates) {
+ QDir dir(path);
+ if (dir.exists() && QFileInfo(path).isWritable())
+ return dir;
+ }
+
+ return QDir();
+}
+
+QString QGstreamerRecorderControl::generateFileName(const QDir &dir, const QString &ext) const
+{
+
+ int lastClip = 0;
+ foreach(QString fileName, dir.entryList(QStringList() << QString("clip_*.%1").arg(ext))) {
+ int imgNumber = fileName.mid(5, fileName.size()-6-ext.length()).toInt();
+ lastClip = qMax(lastClip, imgNumber);
+ }
+
+ QString name = QString("clip_%1.%2").arg(lastClip+1,
+ 4, //fieldWidth
+ 10,
+ QLatin1Char('0')).arg(ext);
+
+ return dir.absoluteFilePath(name);
+}
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.h b/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.h
new file mode 100644
index 000000000..c252f1543
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QGSTREAMERRECORDERCONTROL_H
+#define QGSTREAMERRECORDERCONTROL_H
+
+#include <QtCore/QDir>
+
+#include <qmediarecordercontrol.h>
+#include "qgstreamercapturesession.h"
+
+QT_USE_NAMESPACE
+
+class QGstreamerRecorderControl : public QMediaRecorderControl
+{
+ Q_OBJECT
+
+public:
+ QGstreamerRecorderControl(QGstreamerCaptureSession *session);
+ virtual ~QGstreamerRecorderControl();
+
+ QUrl outputLocation() const;
+ bool setOutputLocation(const QUrl &sink);
+
+ QMediaRecorder::State state() const;
+
+ qint64 duration() const;
+
+ bool isMuted() const;
+
+ void applySettings();
+
+public slots:
+ void record();
+ void pause();
+ void stop();
+ void setMuted(bool);
+
+private slots:
+ void updateState();
+
+private:
+ QDir defaultDir() const;
+ QString generateFileName(const QDir &dir, const QString &ext) const;
+
+ QUrl m_outputLocation;
+ QGstreamerCaptureSession *m_session;
+ QMediaRecorder::State m_state;
+ bool m_hasPreviewState;
+};
+
+#endif // QGSTREAMERCAPTURECORNTROL_H
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.cpp b/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.cpp
new file mode 100644
index 000000000..70907b2dd
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.cpp
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamerv4l2input.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+
+#include <linux/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <linux/videodev2.h>
+
+QT_BEGIN_NAMESPACE
+static inline uint qHash(const QSize& key) { return uint(key.width()*256+key.height()); }
+
+static bool operator<(const QSize &s1, const QSize s2)
+{
+ return s1.width()*s1.height() < s2.width()*s2.height();
+}
+QT_END_NAMESPACE
+
+QGstreamerV4L2Input::QGstreamerV4L2Input(QObject *parent)
+ :QObject(parent)
+{
+}
+
+QGstreamerV4L2Input::~QGstreamerV4L2Input()
+{
+}
+
+GstElement *QGstreamerV4L2Input::buildElement()
+{
+#ifndef Q_WS_MAEMO_5
+ GstElement *camera = gst_element_factory_make("v4l2src", "camera_source");
+#else
+ GstElement *camera = gst_element_factory_make("v4l2camsrc", "camera_source");
+#endif
+ if (camera && !m_device.isEmpty() )
+ g_object_set(G_OBJECT(camera), "device", m_device.constData(), NULL);
+
+ return camera;
+}
+
+void QGstreamerV4L2Input::setDevice(const QByteArray &newDevice)
+{
+ if (m_device != newDevice) {
+ m_device = newDevice;
+ updateSupportedResolutions(newDevice);
+ }
+}
+
+void QGstreamerV4L2Input::setDevice(const QString &device)
+{
+ setDevice(QFile::encodeName(device));
+}
+
+void QGstreamerV4L2Input::updateSupportedResolutions(const QByteArray &device)
+{
+ m_frameRates.clear();
+ m_resolutions.clear();
+ m_ratesByResolution.clear();
+
+ QSet<QSize> allResolutions;
+ QSet<int> allFrameRates;
+
+ QFile f(device);
+
+ if (!f.open(QFile::ReadOnly))
+ return;
+
+ int fd = f.handle();
+
+ //get the list of formats:
+ QList<quint32> supportedFormats;
+
+ {
+ v4l2_fmtdesc fmt;
+ memset(&fmt, 0, sizeof(v4l2_fmtdesc));
+
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ int sanity = 0;
+
+ for (fmt.index = 0;; fmt.index++) {
+ if (sanity++ > 8)
+ break;
+ if( ::ioctl(fd, VIDIOC_ENUM_FMT, &fmt) == -1) {
+ if(errno == EINVAL)
+ break;
+ }
+ supportedFormats.append(fmt.pixelformat);
+ }
+ }
+
+ QList<QSize> commonSizes;
+ commonSizes << QSize(128, 96)
+ <<QSize(160,120)
+ <<QSize(176, 144)
+ <<QSize(320, 240)
+ <<QSize(352, 288)
+ <<QSize(640, 480)
+ <<QSize(1024, 768)
+ <<QSize(1280, 1024)
+ <<QSize(1600, 1200)
+ <<QSize(1920, 1200)
+ <<QSize(2048, 1536)
+ <<QSize(2560, 1600)
+ <<QSize(2580, 1936);
+
+ QList<int> commonRates;
+ commonRates << 05*1000 << 75*1000 << 10*1000 << 15*1000 << 20*1000
+ << 24*1000 << 25*1000 << 30*1000 << 50*1000 << 60*1000;
+
+
+ //get the list of resolutions:
+
+ foreach (quint32 format, supportedFormats) {
+ struct v4l2_frmsizeenum formatSize;
+ memset(&formatSize, 0, sizeof(formatSize));
+ formatSize.pixel_format = format;
+
+ QList<QSize> sizeList;
+
+ if (0) {
+ char formatStr[5];
+ memcpy(formatStr, &format, 4);
+ formatStr[4] = 0;
+ //qDebug() << "trying format" << formatStr;
+ }
+
+ for (int i=0;;i++) {
+ formatSize.index = i;
+ if (ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &formatSize) < 0)
+ break;
+
+ if (formatSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+ sizeList.append(QSize(formatSize.discrete.width, formatSize.discrete.height));
+ } else {
+
+ foreach (const QSize& candidate, commonSizes) {
+ if (candidate.width() <= (int)formatSize.stepwise.max_width &&
+ candidate.height() >= (int)formatSize.stepwise.min_width &&
+ candidate.width() % formatSize.stepwise.step_width == 0 &&
+ candidate.height() <= (int)formatSize.stepwise.max_height &&
+ candidate.height() >= (int)formatSize.stepwise.min_height &&
+ candidate.height() % formatSize.stepwise.step_height == 0) {
+ sizeList.append(candidate);
+ }
+ }
+
+ if (!sizeList.contains(QSize(formatSize.stepwise.min_width, formatSize.stepwise.min_height)))
+ sizeList.prepend(QSize(formatSize.stepwise.min_width, formatSize.stepwise.min_height));
+
+ if (!sizeList.contains(QSize(formatSize.stepwise.max_width, formatSize.stepwise.max_height)))
+ sizeList.append(QSize(formatSize.stepwise.max_width, formatSize.stepwise.max_height));
+
+ break; //stepwise values are returned only for index 0
+ }
+
+ }
+
+ //and frameRates for each resolution.
+
+ foreach (const QSize &s, sizeList) {
+ allResolutions.insert(s);
+
+ struct v4l2_frmivalenum formatInterval;
+ memset(&formatInterval, 0, sizeof(formatInterval));
+ formatInterval.pixel_format = format;
+ formatInterval.width = s.width();
+ formatInterval.height = s.height();
+
+ QList<int> frameRates; //in 1/1000 of fps
+
+ for (int i=0; ; i++) {
+ formatInterval.index = i;
+
+ if (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &formatInterval) < 0)
+ break;
+
+ if (formatInterval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
+ //converts seconds to fps*1000
+ if (formatInterval.discrete.numerator)
+ frameRates.append(qRound(formatInterval.discrete.denominator*1000.0 / formatInterval.discrete.numerator));
+ } else {
+ if (formatInterval.stepwise.min.numerator == 0 ||
+ formatInterval.stepwise.max.numerator == 0) {
+ qWarning() << "received invalid frame interval";
+ break;
+ }
+
+
+ int minRate = qRound(formatInterval.stepwise.min.denominator*1000.0 /
+ formatInterval.stepwise.min.numerator);
+
+ int maxRate = qRound(formatInterval.stepwise.max.denominator*1000.0 /
+ formatInterval.stepwise.max.numerator);
+
+
+ foreach (int candidate, commonRates) {
+ if (candidate >= minRate && candidate <= maxRate)
+ frameRates.append(candidate);
+ }
+
+ if (!frameRates.contains(minRate))
+ frameRates.prepend(minRate);
+
+ if (!frameRates.contains(maxRate))
+ frameRates.append(maxRate);
+
+ break; //stepwise values are returned only for index 0
+ }
+ }
+ allFrameRates.unite(frameRates.toSet());
+ m_ratesByResolution[s].unite(frameRates.toSet());
+ }
+ }
+
+ f.close();
+
+ foreach(int rate, allFrameRates) {
+ m_frameRates.append(rate/1000.0);
+ }
+
+ qSort(m_frameRates);
+
+ m_resolutions = allResolutions.toList();
+ qSort(m_resolutions);
+
+ //qDebug() << "frame rates:" << m_frameRates;
+ //qDebug() << "resolutions:" << m_resolutions;
+}
+
+
+QList<qreal> QGstreamerV4L2Input::supportedFrameRates(const QSize &frameSize) const
+{
+ if (frameSize.isEmpty())
+ return m_frameRates;
+ else {
+ QList<qreal> res;
+ foreach(int rate, m_ratesByResolution[frameSize]) {
+ res.append(rate/1000.0);
+ }
+ return res;
+ }
+}
+
+QList<QSize> QGstreamerV4L2Input::supportedResolutions(qreal frameRate) const
+{
+ Q_UNUSED(frameRate);
+ return m_resolutions;
+}
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.h b/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.h
new file mode 100644
index 000000000..5dbdd5453
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERV4L2INPUT_H
+#define QGSTREAMERV4L2INPUT_H
+
+#include <QtCore/qhash.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qsize.h>
+#include "qgstreamercapturesession.h"
+
+QT_USE_NAMESPACE
+
+class QGstreamerV4L2Input : public QObject, public QGstreamerVideoInput
+{
+ Q_OBJECT
+public:
+ QGstreamerV4L2Input(QObject *parent = 0);
+ virtual ~QGstreamerV4L2Input();
+
+ GstElement *buildElement();
+
+ QList<qreal> supportedFrameRates(const QSize &frameSize = QSize()) const;
+ QList<QSize> supportedResolutions(qreal frameRate = -1) const;
+
+ QByteArray device() const;
+
+public slots:
+ void setDevice(const QByteArray &device);
+ void setDevice(const QString &device);
+
+private:
+ void updateSupportedResolutions(const QByteArray &device);
+
+ QList<qreal> m_frameRates;
+ QList<QSize> m_resolutions;
+
+ QHash<QSize, QSet<int> > m_ratesByResolution;
+
+ QByteArray m_device;
+};
+
+#endif // QGSTREAMERV4L2INPUT_H
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp b/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp
new file mode 100644
index 000000000..a491f14ae
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp
@@ -0,0 +1,331 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamervideoencode.h"
+#include "qgstreamercapturesession.h"
+#include "qgstreamermediacontainercontrol.h"
+
+#include <QtCore/qdebug.h>
+
+#include <math.h>
+
+QGstreamerVideoEncode::QGstreamerVideoEncode(QGstreamerCaptureSession *session)
+ :QVideoEncoderControl(session), m_session(session)
+{
+ QList<QByteArray> codecCandidates;
+ codecCandidates << "video/h264" << "video/xvid" << "video/mpeg4" << "video/mpeg1" << "video/mpeg2" << "video/theora";
+
+ m_elementNames["video/h264"] = "x264enc";
+ m_elementNames["video/xvid"] = "xvidenc";
+ m_elementNames["video/mpeg4"] = "ffenc_mpeg4";
+ m_elementNames["video/mpeg1"] = "ffenc_mpeg1video";
+ m_elementNames["video/mpeg2"] = "ffenc_mpeg2video";
+ m_elementNames["video/theora"] = "theoraenc";
+
+ m_codecOptions["video/h264"] = QStringList() << "quantizer";
+ m_codecOptions["video/xvid"] = QStringList() << "quantizer" << "profile";
+ m_codecOptions["video/mpeg4"] = QStringList() << "quantizer";
+ m_codecOptions["video/mpeg1"] = QStringList() << "quantizer";
+ m_codecOptions["video/mpeg2"] = QStringList() << "quantizer";
+ m_codecOptions["video/theora"] = QStringList();
+
+ foreach( const QByteArray& codecName, codecCandidates ) {
+ QByteArray elementName = m_elementNames[codecName];
+ GstElementFactory *factory = gst_element_factory_find(elementName.constData());
+ if (factory) {
+ m_codecs.append(codecName);
+ const gchar *descr = gst_element_factory_get_description(factory);
+ m_codecDescriptions.insert(codecName, QString::fromUtf8(descr));
+
+ m_streamTypes.insert(codecName,
+ QGstreamerMediaContainerControl::supportedStreamTypes(factory, GST_PAD_SRC));
+
+ gst_object_unref(GST_OBJECT(factory));
+ }
+ }
+
+ //if (!m_codecs.isEmpty())
+ // m_videoSettings.setCodec(m_codecs[0]);
+}
+
+QGstreamerVideoEncode::~QGstreamerVideoEncode()
+{
+}
+
+QList<QSize> QGstreamerVideoEncode::supportedResolutions(const QVideoEncoderSettings &, bool *continuous) const
+{
+ if (continuous)
+ *continuous = m_session->videoInput() != 0;
+
+ return m_session->videoInput() ? m_session->videoInput()->supportedResolutions() : QList<QSize>();
+}
+
+QList< qreal > QGstreamerVideoEncode::supportedFrameRates(const QVideoEncoderSettings &, bool *continuous) const
+{
+ if (continuous)
+ *continuous = false;
+
+ return m_session->videoInput() ? m_session->videoInput()->supportedFrameRates() : QList<qreal>();
+}
+
+QStringList QGstreamerVideoEncode::supportedVideoCodecs() const
+{
+ return m_codecs;
+}
+
+QString QGstreamerVideoEncode::videoCodecDescription(const QString &codecName) const
+{
+ return m_codecDescriptions.value(codecName);
+}
+
+QStringList QGstreamerVideoEncode::supportedEncodingOptions(const QString &codec) const
+{
+ return m_codecOptions.value(codec);
+}
+
+QVariant QGstreamerVideoEncode::encodingOption(const QString &codec, const QString &name) const
+{
+ return m_options[codec].value(name);
+}
+
+void QGstreamerVideoEncode::setEncodingOption(
+ const QString &codec, const QString &name, const QVariant &value)
+{
+ m_options[codec][name] = value;
+}
+
+QVideoEncoderSettings QGstreamerVideoEncode::videoSettings() const
+{
+ return m_videoSettings;
+}
+
+void QGstreamerVideoEncode::setVideoSettings(const QVideoEncoderSettings &settings)
+{
+ m_videoSettings = settings;
+}
+
+GstElement *QGstreamerVideoEncode::createEncoder()
+{
+ QString codec = m_videoSettings.codec();
+ //qDebug() << "create encoder for video codec" << codec;
+ GstElement *encoderElement = gst_element_factory_make( m_elementNames.value(codec).constData(), "video-encoder");
+ if (!encoderElement)
+ return 0;
+
+ GstBin *encoderBin = GST_BIN(gst_bin_new("video-encoder-bin"));
+
+ GstElement *capsFilter = gst_element_factory_make("capsfilter", "capsfilter-video");
+ gst_bin_add(encoderBin, capsFilter);
+
+ GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", NULL);
+ gst_bin_add(encoderBin, colorspace);
+ gst_bin_add(encoderBin, encoderElement);
+
+ gst_element_link_many(capsFilter, colorspace, encoderElement, NULL);
+
+ // add ghostpads
+ GstPad *pad = gst_element_get_static_pad(capsFilter, "sink");
+ gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("sink", pad));
+ gst_object_unref(GST_OBJECT(pad));
+
+ pad = gst_element_get_static_pad(encoderElement, "src");
+ gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("src", pad));
+ gst_object_unref(GST_OBJECT(pad));
+
+ if (encoderElement) {
+ if (m_videoSettings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
+ QtMultimediaKit::EncodingQuality qualityValue = m_videoSettings.quality();
+
+ if (codec == QLatin1String("video/h264")) {
+ //constant quantizer mode
+ g_object_set(G_OBJECT(encoderElement), "pass", 4, NULL);
+ int qualityTable[] = {
+ 50, //VeryLow
+ 35, //Low
+ 21, //Normal
+ 15, //High
+ 8 //VeryHigh
+ };
+ g_object_set(G_OBJECT(encoderElement), "quantizer", qualityTable[qualityValue], NULL);
+ } else if (codec == QLatin1String("video/xvid")) {
+ //constant quantizer mode
+ g_object_set(G_OBJECT(encoderElement), "pass", 3, NULL);
+ int qualityTable[] = {
+ 32, //VeryLow
+ 12, //Low
+ 5, //Normal
+ 3, //High
+ 2 //VeryHigh
+ };
+ int quant = qualityTable[qualityValue];
+ g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL);
+ } else if (codec == QLatin1String("video/mpeg4") ||
+ codec == QLatin1String("video/mpeg1") ||
+ codec == QLatin1String("video/mpeg2") ) {
+ //constant quantizer mode
+ g_object_set(G_OBJECT(encoderElement), "pass", 2, NULL);
+ //quant from 1 to 30, default ~3
+ double qualityTable[] = {
+ 20, //VeryLow
+ 8.0, //Low
+ 3.0, //Normal
+ 2.5, //High
+ 2.0 //VeryHigh
+ };
+ double quant = qualityTable[qualityValue];
+ g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL);
+ } else if (codec == QLatin1String("video/theora")) {
+ int qualityTable[] = {
+ 8, //VeryLow
+ 16, //Low
+ 32, //Normal
+ 45, //High
+ 60 //VeryHigh
+ };
+ //quality from 0 to 63
+ int quality = qualityTable[qualityValue];
+ g_object_set(G_OBJECT(encoderElement), "quality", quality, NULL);
+ }
+ } else {
+ int bitrate = m_videoSettings.bitRate();
+ if (bitrate > 0) {
+ g_object_set(G_OBJECT(encoderElement), "bitrate", bitrate, NULL);
+ }
+ }
+
+ QMap<QString,QVariant> options = m_options.value(codec);
+ QMapIterator<QString,QVariant> it(options);
+ while (it.hasNext()) {
+ it.next();
+ QString option = it.key();
+ QVariant value = it.value();
+
+ switch (value.type()) {
+ case QVariant::Int:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toInt(), NULL);
+ break;
+ case QVariant::Bool:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toBool(), NULL);
+ break;
+ case QVariant::Double:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toDouble(), NULL);
+ break;
+ case QVariant::String:
+ g_object_set(G_OBJECT(encoderElement), option.toAscii(), value.toString().toUtf8().constData(), NULL);
+ break;
+ default:
+ qWarning() << "unsupported option type:" << option << value;
+ break;
+ }
+
+ }
+ }
+
+ if (!m_videoSettings.resolution().isEmpty() || m_videoSettings.frameRate() > 0.001) {
+ GstCaps *caps = gst_caps_new_empty();
+ QStringList structureTypes;
+ structureTypes << "video/x-raw-yuv" << "video/x-raw-rgb";
+
+ foreach(const QString &structureType, structureTypes) {
+ GstStructure *structure = gst_structure_new(structureType.toAscii().constData(), NULL);
+
+ if (!m_videoSettings.resolution().isEmpty()) {
+ gst_structure_set(structure, "width", G_TYPE_INT, m_videoSettings.resolution().width(), NULL);
+ gst_structure_set(structure, "height", G_TYPE_INT, m_videoSettings.resolution().height(), NULL);
+ }
+
+ if (m_videoSettings.frameRate() > 0.001) {
+ QPair<int,int> rate = rateAsRational();
+
+ //qDebug() << "frame rate:" << num << denum;
+
+ gst_structure_set(structure, "framerate", GST_TYPE_FRACTION, rate.first, rate.second, NULL);
+ }
+
+ gst_caps_append_structure(caps,structure);
+ }
+
+ //qDebug() << "set video caps filter:" << gst_caps_to_string(caps);
+
+ g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL);
+ }
+
+ return GST_ELEMENT(encoderBin);
+}
+
+QPair<int,int> QGstreamerVideoEncode::rateAsRational() const
+{
+ qreal frameRate = m_videoSettings.frameRate();
+
+ if (frameRate > 0.001) {
+ //convert to rational number
+ QList<int> denumCandidates;
+ denumCandidates << 1 << 2 << 3 << 5 << 10 << 1001 << 1000;
+
+ qreal error = 1.0;
+ int num = 1;
+ int denum = 1;
+
+ foreach (int curDenum, denumCandidates) {
+ int curNum = qRound(frameRate*curDenum);
+ qreal curError = qAbs(qreal(curNum)/curDenum - frameRate);
+
+ if (curError < error) {
+ error = curError;
+ num = curNum;
+ denum = curDenum;
+ }
+
+ if (curError < 1e-8)
+ break;
+ }
+
+ return QPair<int,int>(num,denum);
+ }
+
+ return QPair<int,int>();
+}
+
+
+QSet<QString> QGstreamerVideoEncode::supportedStreamTypes(const QString &codecName) const
+{
+ return m_streamTypes.value(codecName);
+}
diff --git a/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.h b/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.h
new file mode 100644
index 000000000..c042efd25
--- /dev/null
+++ b/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERVIDEOENCODE_H
+#define QGSTREAMERVIDEOENCODE_H
+
+#include <qvideoencodercontrol.h>
+class QGstreamerCaptureSession;
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qset.h>
+
+#include <gst/gst.h>
+
+QT_USE_NAMESPACE
+
+class QGstreamerVideoEncode : public QVideoEncoderControl
+{
+ Q_OBJECT
+public:
+ QGstreamerVideoEncode(QGstreamerCaptureSession *session);
+ virtual ~QGstreamerVideoEncode();
+
+ QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings = QVideoEncoderSettings(),
+ bool *continuous = 0) const;
+
+ QList< qreal > supportedFrameRates(const QVideoEncoderSettings &settings = QVideoEncoderSettings(),
+ bool *continuous = 0) const;
+
+ QPair<int,int> rateAsRational() const;
+
+ QStringList supportedVideoCodecs() const;
+ QString videoCodecDescription(const QString &codecName) const;
+
+ QVideoEncoderSettings videoSettings() const;
+ void setVideoSettings(const QVideoEncoderSettings &settings);
+
+ QStringList supportedEncodingOptions(const QString &codec) const;
+ QVariant encodingOption(const QString &codec, const QString &name) const;
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
+
+ GstElement *createEncoder();
+
+ QSet<QString> supportedStreamTypes(const QString &codecName) const;
+
+private:
+ QGstreamerCaptureSession *m_session;
+
+ QStringList m_codecs;
+ QMap<QString,QString> m_codecDescriptions;
+ QMap<QString,QByteArray> m_elementNames;
+ QMap<QString,QStringList> m_codecOptions;
+
+ QVideoEncoderSettings m_videoSettings;
+ QMap<QString, QMap<QString, QVariant> > m_options;
+ QMap<QString, QSet<QString> > m_streamTypes;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/mediaplayer/mediaplayer.pri b/src/plugins/gstreamer/mediaplayer/mediaplayer.pri
new file mode 100644
index 000000000..9045a80dd
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/mediaplayer.pri
@@ -0,0 +1,30 @@
+INCLUDEPATH += $$PWD
+
+DEFINES += QMEDIA_GSTREAMER_PLAYER
+
+contains(gstreamer-appsrc_enabled, yes) {
+ HEADERS += $$PWD/qgstappsrc.h
+ SOURCES += $$PWD/qgstappsrc.cpp
+
+ DEFINES += HAVE_GST_APPSRC
+
+ LIBS += -lgstapp-0.10
+}
+
+HEADERS += \
+ $$PWD/qgstreamerplayercontrol.h \
+ $$PWD/qgstreamerplayerservice.h \
+ $$PWD/qgstreamerplayersession.h \
+ $$PWD/qgstreamerstreamscontrol.h \
+ $$PWD/qgstreamermetadataprovider.h \
+ $$PWD/playerresourcepolicy.h
+
+SOURCES += \
+ $$PWD/qgstreamerplayercontrol.cpp \
+ $$PWD/qgstreamerplayerservice.cpp \
+ $$PWD/qgstreamerplayersession.cpp \
+ $$PWD/qgstreamerstreamscontrol.cpp \
+ $$PWD/qgstreamermetadataprovider.cpp \
+ $$PWD/playerresourcepolicy.cpp
+
+
diff --git a/src/plugins/gstreamer/mediaplayer/playerresourcepolicy.cpp b/src/plugins/gstreamer/mediaplayer/playerresourcepolicy.cpp
new file mode 100644
index 000000000..b2cf3498d
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/playerresourcepolicy.cpp
@@ -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$
+** 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 "playerresourcepolicy.h"
+
+#ifdef Q_WS_MAEMO_6
+#define HAVE_RESOURCE_POLICY
+#endif
+
+//#define DEBUG_RESOURCE_POLICY
+#include <QtCore/qdebug.h>
+
+#ifdef HAVE_RESOURCE_POLICY
+#include <policy/resource.h>
+#include <policy/resources.h>
+#include <policy/resource-set.h>
+#endif
+
+PlayerResourcePolicy::PlayerResourcePolicy(QObject *parent) :
+ QObject(parent),
+ m_videoEnabled(true),
+ m_resourceSet(0),
+ m_status(PlayerResourcePolicy::Initial)
+{
+#ifdef HAVE_RESOURCE_POLICY
+ m_resourceSet = new ResourcePolicy::ResourceSet("player", this);
+ m_resourceSet->setAlwaysReply();
+
+ ResourcePolicy::AudioResource *audioResource = new ResourcePolicy::AudioResource("player");
+ audioResource->setProcessID(QCoreApplication::applicationPid());
+ audioResource->setStreamTag("media.name", "*");
+ m_resourceSet->addResourceObject(audioResource);
+
+ m_resourceSet->addResource(ResourcePolicy::VideoPlaybackType);
+ m_resourceSet->update();
+
+ connect(m_resourceSet, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>)),
+ this, SLOT(handleResourcesGranted()));
+ connect(m_resourceSet, SIGNAL(resourcesDenied()),
+ this, SLOT(handleResourcesDenied()));
+ connect(m_resourceSet, SIGNAL(lostResources()),
+ this, SLOT(handleResourcesLost()));
+ connect(m_resourceSet, SIGNAL(resourcesReleasedByManager()),
+ this, SLOT(handleResourcesLost()));
+#endif
+}
+
+PlayerResourcePolicy::~PlayerResourcePolicy()
+{
+}
+
+bool PlayerResourcePolicy::isVideoEnabled() const
+{
+ return m_videoEnabled;
+}
+
+void PlayerResourcePolicy::setVideoEnabled(bool enabled)
+{
+ if (m_videoEnabled != enabled) {
+ m_videoEnabled = enabled;
+
+#ifdef HAVE_RESOURCE_POLICY
+ if (enabled)
+ m_resourceSet->addResource(ResourcePolicy::VideoPlaybackType);
+ else
+ m_resourceSet->deleteResource(ResourcePolicy::VideoPlaybackType);
+
+ m_resourceSet->update();
+#endif
+ }
+}
+
+void PlayerResourcePolicy::acquire()
+{
+#ifdef HAVE_RESOURCE_POLICY
+
+#ifdef DEBUG_RESOURCE_POLICY
+ qDebug() << Q_FUNC_INFO << "Acquire resource";
+#endif
+ m_status = RequestedResource;
+ m_resourceSet->acquire();
+#else
+ m_status = GrantedResource;
+#endif
+}
+
+void PlayerResourcePolicy::release()
+{
+#ifdef HAVE_RESOURCE_POLICY
+
+#ifdef DEBUG_RESOURCE_POLICY
+ qDebug() << Q_FUNC_INFO << "Release resource";
+#endif
+
+ m_resourceSet->release();
+#endif
+ m_status = Initial;
+
+}
+
+bool PlayerResourcePolicy::isGranted() const
+{
+ return m_status == GrantedResource;
+}
+
+bool PlayerResourcePolicy::isRequested() const
+{
+ return m_status == RequestedResource;
+}
+
+void PlayerResourcePolicy::handleResourcesGranted()
+{
+ m_status = GrantedResource;
+#ifdef DEBUG_RESOURCE_POLICY
+ qDebug() << Q_FUNC_INFO << "Resource granted";
+#endif
+ emit resourcesGranted();
+}
+
+void PlayerResourcePolicy::handleResourcesDenied()
+{
+ m_status = Initial;
+#ifdef DEBUG_RESOURCE_POLICY
+ qDebug() << Q_FUNC_INFO << "Resource denied";
+#endif
+ emit resourcesDenied();
+}
+
+void PlayerResourcePolicy::handleResourcesLost()
+{
+#ifdef DEBUG_RESOURCE_POLICY
+ qDebug() << Q_FUNC_INFO << "Resource lost";
+#endif
+ if (m_status != Initial) {
+ m_status = Initial;
+ emit resourcesLost();
+ }
+
+#ifdef HAVE_RESOURCE_POLICY
+ m_resourceSet->release();
+#endif
+}
diff --git a/src/plugins/gstreamer/mediaplayer/playerresourcepolicy.h b/src/plugins/gstreamer/mediaplayer/playerresourcepolicy.h
new file mode 100644
index 000000000..fecf5fa80
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/playerresourcepolicy.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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$
+** 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 PLAYERRESOURCEPOLICY_H
+#define PLAYERRESOURCEPOLICY_H
+
+#include <QtCore/qobject.h>
+
+namespace ResourcePolicy {
+class ResourceSet;
+};
+
+class PlayerResourcePolicy : public QObject
+{
+ Q_OBJECT
+public:
+ PlayerResourcePolicy(QObject *parent = 0);
+ ~PlayerResourcePolicy();
+
+ bool isVideoEnabled() const;
+ bool isGranted() const;
+ bool isRequested() const;
+
+Q_SIGNALS:
+ void resourcesDenied();
+ void resourcesGranted();
+ void resourcesLost();
+
+public Q_SLOTS:
+ void acquire();
+ void release();
+
+ void setVideoEnabled(bool enabled);
+
+private Q_SLOTS:
+ void handleResourcesGranted();
+ void handleResourcesDenied();
+ void handleResourcesLost();
+
+private:
+ enum ResourceStatus {
+ Initial = 0,
+ RequestedResource,
+ GrantedResource
+ };
+
+ bool m_videoEnabled;
+ ResourcePolicy::ResourceSet *m_resourceSet;
+ ResourceStatus m_status;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/mediaplayer/qgstappsrc.cpp b/src/plugins/gstreamer/mediaplayer/qgstappsrc.cpp
new file mode 100644
index 000000000..cf814c462
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/qgstappsrc.cpp
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QDebug>
+
+#include "qgstappsrc.h"
+#include <QtNetwork>
+
+QGstAppSrc::QGstAppSrc(QObject *parent)
+ :QObject(parent)
+ ,m_stream(0)
+ ,m_appSrc(0)
+ ,m_sequential(false)
+ ,m_maxBytes(0)
+ ,m_setup(false)
+ ,m_dataRequestSize(-1)
+ ,m_dataRequested(false)
+ ,m_enoughData(false)
+ ,m_forceData(false)
+{
+}
+
+QGstAppSrc::~QGstAppSrc()
+{
+ if (m_appSrc)
+ gst_object_unref(G_OBJECT(m_appSrc));
+}
+
+bool QGstAppSrc::setup(GstElement* appsrc)
+{
+ if (m_setup || m_stream == 0 || appsrc == 0)
+ return false;
+
+ m_appSrc = GST_APP_SRC(appsrc);
+ m_callbacks.need_data = &QGstAppSrc::on_need_data;
+ m_callbacks.enough_data = &QGstAppSrc::on_enough_data;
+ m_callbacks.seek_data = &QGstAppSrc::on_seek_data;
+ gst_app_src_set_callbacks(m_appSrc, (GstAppSrcCallbacks*)&m_callbacks, this, (GDestroyNotify)&QGstAppSrc::destroy_notify);
+
+ g_object_get(G_OBJECT(m_appSrc), "max-bytes", &m_maxBytes, NULL);
+
+ if (m_sequential)
+ m_streamType = GST_APP_STREAM_TYPE_STREAM;
+ else
+ m_streamType = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
+ gst_app_src_set_stream_type(m_appSrc, m_streamType);
+ gst_app_src_set_size(m_appSrc, (m_sequential) ? -1 : m_stream->size());
+
+ return m_setup = true;
+}
+
+void QGstAppSrc::setStream(QIODevice *stream)
+{
+ if (stream == 0)
+ return;
+ if (m_stream) {
+ disconnect(m_stream, SIGNAL(readyRead()), this, SLOT(onDataReady()));
+ disconnect(m_stream, SIGNAL(destroyed()), this, SLOT(streamDestroyed()));
+ }
+ if (m_appSrc)
+ gst_object_unref(G_OBJECT(m_appSrc));
+
+ m_dataRequestSize = -1;
+ m_dataRequested = false;
+ m_enoughData = false;
+ m_forceData = false;
+ m_maxBytes = 0;
+
+ m_appSrc = 0;
+ m_stream = stream;
+ connect(m_stream, SIGNAL(destroyed()), SLOT(streamDestroyed()));
+ connect(m_stream, SIGNAL(readyRead()), this, SLOT(onDataReady()));
+ m_sequential = m_stream->isSequential();
+ m_setup = false;
+}
+
+QIODevice *QGstAppSrc::stream() const
+{
+ return m_stream;
+}
+
+GstAppSrc *QGstAppSrc::element()
+{
+ return m_appSrc;
+}
+
+void QGstAppSrc::onDataReady()
+{
+ if (!m_enoughData) {
+ m_dataRequested = true;
+ pushDataToAppSrc();
+ }
+}
+
+void QGstAppSrc::streamDestroyed()
+{
+ if (sender() == m_stream) {
+ m_stream = 0;
+ sendEOS();
+ }
+}
+
+void QGstAppSrc::pushDataToAppSrc()
+{
+ if (!isStreamValid() || !m_setup)
+ return;
+
+ if (m_dataRequested && !m_enoughData) {
+ qint64 size;
+ if (m_dataRequestSize == (unsigned int)-1)
+ size = qMin(m_stream->bytesAvailable(), queueSize());
+ else
+ size = qMin(m_stream->bytesAvailable(), (qint64)m_dataRequestSize);
+ void *data = g_malloc(size);
+ GstBuffer* buffer = gst_app_buffer_new(data, size, g_free, data);
+ buffer->offset = m_stream->pos();
+ qint64 bytesRead = m_stream->read((char*)GST_BUFFER_DATA(buffer), size);
+ buffer->offset_end = buffer->offset + bytesRead - 1;
+
+ if (bytesRead > 0) {
+ m_dataRequested = false;
+ m_enoughData = false;
+ GstFlowReturn ret = gst_app_src_push_buffer (GST_APP_SRC (element()), buffer);
+ if (ret == GST_FLOW_ERROR) {
+ qWarning()<<"appsrc: push buffer error";
+ } else if (ret == GST_FLOW_WRONG_STATE) {
+ qWarning()<<"appsrc: push buffer wrong state";
+ } else if (ret == GST_FLOW_RESEND) {
+ qWarning()<<"appsrc: push buffer resend";
+ }
+ }
+ } else if (m_stream->atEnd()) {
+ sendEOS();
+ }
+}
+
+bool QGstAppSrc::doSeek(qint64 value)
+{
+ if (isStreamValid())
+ return stream()->seek(value);
+ return false;
+}
+
+
+gboolean QGstAppSrc::on_seek_data(GstAppSrc *element, guint64 arg0, gpointer userdata)
+{
+ QGstAppSrc *self = reinterpret_cast<QGstAppSrc*>(userdata);
+ if (self && self->isStreamValid()) {
+ if (!self->stream()->isSequential())
+ QMetaObject::invokeMethod(self, "doSeek", Qt::AutoConnection, Q_ARG(qint64, arg0));
+ }
+ else
+ return false;
+
+ return true;
+}
+
+void QGstAppSrc::on_enough_data(GstAppSrc *element, gpointer userdata)
+{
+ QGstAppSrc *self = reinterpret_cast<QGstAppSrc*>(userdata);
+ if (self)
+ self->enoughData() = true;
+}
+
+void QGstAppSrc::on_need_data(GstAppSrc *element, guint arg0, gpointer userdata)
+{
+ QGstAppSrc *self = reinterpret_cast<QGstAppSrc*>(userdata);
+ if (self) {
+ self->dataRequested() = true;
+ self->enoughData() = false;
+ self->dataRequestSize()= arg0;
+ QMetaObject::invokeMethod(self, "pushDataToAppSrc", Qt::AutoConnection);
+ }
+}
+
+void QGstAppSrc::destroy_notify(gpointer data)
+{
+ Q_UNUSED(data);
+}
+
+void QGstAppSrc::sendEOS()
+{
+ gst_app_src_end_of_stream(GST_APP_SRC(m_appSrc));
+ if (isStreamValid() && !stream()->isSequential())
+ stream()->reset();
+}
diff --git a/src/plugins/gstreamer/mediaplayer/qgstappsrc.h b/src/plugins/gstreamer/mediaplayer/qgstappsrc.h
new file mode 100644
index 000000000..17ee2af72
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/qgstappsrc.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTAPPSRC_H
+#define QGSTAPPSRC_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qiodevice.h>
+
+#include <gst/gst.h>
+#include <gst/app/gstappsrc.h>
+#include <gst/app/gstappbuffer.h>
+
+class QGstAppSrc : public QObject
+{
+ Q_OBJECT
+public:
+ QGstAppSrc(QObject *parent = 0);
+ ~QGstAppSrc();
+
+ bool setup(GstElement *);
+ bool isReady() const { return m_setup; }
+
+ void setStream(QIODevice *);
+ QIODevice *stream() const;
+
+ GstAppSrc *element();
+
+ qint64 queueSize() const { return m_maxBytes; }
+
+ bool& enoughData() { return m_enoughData; }
+ bool& dataRequested() { return m_dataRequested; }
+ unsigned int& dataRequestSize() { return m_dataRequestSize; }
+
+ bool isStreamValid() const
+ {
+ return m_stream != 0 &&
+ m_stream->isOpen();
+ }
+
+private slots:
+ void pushDataToAppSrc();
+ bool doSeek(qint64);
+ void onDataReady();
+
+ void streamDestroyed();
+private:
+ static gboolean on_seek_data(GstAppSrc *element, guint64 arg0, gpointer userdata);
+ static void on_enough_data(GstAppSrc *element, gpointer userdata);
+ static void on_need_data(GstAppSrc *element, uint arg0, gpointer userdata);
+ static void destroy_notify(gpointer data);
+
+ void sendEOS();
+
+ QIODevice *m_stream;
+ GstAppSrc *m_appSrc;
+ bool m_sequential;
+ GstAppStreamType m_streamType;
+ GstAppSrcCallbacks m_callbacks;
+ qint64 m_maxBytes;
+ bool m_setup;
+ unsigned int m_dataRequestSize;
+ bool m_dataRequested;
+ bool m_enoughData;
+ bool m_forceData;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp
new file mode 100644
index 000000000..cdd6d89b4
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamermetadataprovider.h"
+#include "qgstreamerplayersession.h"
+#include <QDebug>
+
+#include <gst/gstversion.h>
+
+struct QGstreamerMetaDataKeyLookup
+{
+ QtMultimediaKit::MetaData key;
+ const char *token;
+};
+
+static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] =
+{
+ { QtMultimediaKit::Title, GST_TAG_TITLE },
+ //{ QtMultimediaKit::SubTitle, 0 },
+ //{ QtMultimediaKit::Author, 0 },
+ { QtMultimediaKit::Comment, GST_TAG_COMMENT },
+ { QtMultimediaKit::Description, GST_TAG_DESCRIPTION },
+ //{ QtMultimediaKit::Category, 0 },
+ { QtMultimediaKit::Genre, GST_TAG_GENRE },
+ { QtMultimediaKit::Year, "year" },
+ //{ QtMultimediaKit::UserRating, 0 },
+
+ { QtMultimediaKit::Language, GST_TAG_LANGUAGE_CODE },
+
+ { QtMultimediaKit::Publisher, GST_TAG_ORGANIZATION },
+ { QtMultimediaKit::Copyright, GST_TAG_COPYRIGHT },
+ //{ QtMultimediaKit::ParentalRating, 0 },
+ //{ QtMultimediaKit::RatingOrganisation, 0 },
+
+ // Media
+ //{ QtMultimediaKit::Size, 0 },
+ //{ QtMultimediaKit::MediaType, 0 },
+ { QtMultimediaKit::Duration, GST_TAG_DURATION },
+
+ // Audio
+ { QtMultimediaKit::AudioBitRate, GST_TAG_BITRATE },
+ { QtMultimediaKit::AudioCodec, GST_TAG_AUDIO_CODEC },
+ //{ QtMultimediaKit::ChannelCount, 0 },
+ //{ QtMultimediaKit::SampleRate, 0 },
+
+ // Music
+ { QtMultimediaKit::AlbumTitle, GST_TAG_ALBUM },
+ { QtMultimediaKit::AlbumArtist, GST_TAG_ARTIST},
+ { QtMultimediaKit::ContributingArtist, GST_TAG_PERFORMER },
+#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
+ { QtMultimediaKit::Composer, GST_TAG_COMPOSER },
+#endif
+ //{ QtMultimediaKit::Conductor, 0 },
+ //{ QtMultimediaKit::Lyrics, 0 },
+ //{ QtMultimediaKit::Mood, 0 },
+ { QtMultimediaKit::TrackNumber, GST_TAG_TRACK_NUMBER },
+
+ //{ QtMultimediaKit::CoverArtUrlSmall, 0 },
+ //{ QtMultimediaKit::CoverArtUrlLarge, 0 },
+
+ // Image/Video
+ { QtMultimediaKit::Resolution, "resolution" },
+ { QtMultimediaKit::PixelAspectRatio, "pixel-aspect-ratio" },
+
+ // Video
+ //{ QtMultimediaKit::VideoFrameRate, 0 },
+ //{ QtMultimediaKit::VideoBitRate, 0 },
+ { QtMultimediaKit::VideoCodec, GST_TAG_VIDEO_CODEC },
+
+ //{ QtMultimediaKit::PosterUrl, 0 },
+
+ // Movie
+ //{ QtMultimediaKit::ChapterNumber, 0 },
+ //{ QtMultimediaKit::Director, 0 },
+ { QtMultimediaKit::LeadPerformer, GST_TAG_PERFORMER },
+ //{ QtMultimediaKit::Writer, 0 },
+
+ // Photos
+ //{ QtMultimediaKit::CameraManufacturer, 0 },
+ //{ QtMultimediaKit::CameraModel, 0 },
+ //{ QtMultimediaKit::Event, 0 },
+ //{ QtMultimediaKit::Subject, 0 }
+};
+
+QGstreamerMetaDataProvider::QGstreamerMetaDataProvider(QGstreamerPlayerSession *session, QObject *parent)
+ :QMetaDataReaderControl(parent), m_session(session)
+{
+ connect(m_session, SIGNAL(tagsChanged()), SLOT(updateTags()));
+}
+
+QGstreamerMetaDataProvider::~QGstreamerMetaDataProvider()
+{
+}
+
+bool QGstreamerMetaDataProvider::isMetaDataAvailable() const
+{
+ return !m_session->tags().isEmpty();
+}
+
+bool QGstreamerMetaDataProvider::isWritable() const
+{
+ return false;
+}
+
+QVariant QGstreamerMetaDataProvider::metaData(QtMultimediaKit::MetaData key) const
+{
+ static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
+
+ for (int i = 0; i < count; ++i) {
+ if (qt_gstreamerMetaDataKeys[i].key == key) {
+ return m_session->tags().value(QByteArray(qt_gstreamerMetaDataKeys[i].token));
+ }
+ }
+ return QVariant();
+}
+
+QList<QtMultimediaKit::MetaData> QGstreamerMetaDataProvider::availableMetaData() const
+{
+ static QMap<QByteArray, QtMultimediaKit::MetaData> keysMap;
+ if (keysMap.isEmpty()) {
+ const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
+ for (int i = 0; i < count; ++i) {
+ keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key;
+ }
+ }
+
+ QList<QtMultimediaKit::MetaData> res;
+ foreach (const QByteArray &key, m_session->tags().keys()) {
+ QtMultimediaKit::MetaData tag = keysMap.value(key, QtMultimediaKit::MetaData(-1));
+ if (tag != -1)
+ res.append(tag);
+ }
+
+ return res;
+}
+
+QVariant QGstreamerMetaDataProvider::extendedMetaData(const QString &key) const
+{
+ return m_session->tags().value(key.toLatin1());
+}
+
+QStringList QGstreamerMetaDataProvider::availableExtendedMetaData() const
+{
+ QStringList res;
+ foreach (const QByteArray &key, m_session->tags().keys())
+ res.append(QString(key));
+
+ return res;
+}
+
+void QGstreamerMetaDataProvider::updateTags()
+{
+ emit metaDataChanged();
+}
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h
new file mode 100644
index 000000000..fa0c0243f
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QGSTREAMERMETADATAPROVIDER_H
+#define QGSTREAMERMETADATAPROVIDER_H
+
+#include <qmetadatareadercontrol.h>
+
+QT_USE_NAMESPACE
+
+class QGstreamerPlayerSession;
+
+class QGstreamerMetaDataProvider : public QMetaDataReaderControl
+{
+ Q_OBJECT
+public:
+ QGstreamerMetaDataProvider( QGstreamerPlayerSession *session, QObject *parent );
+ virtual ~QGstreamerMetaDataProvider();
+
+ bool isMetaDataAvailable() const;
+ bool isWritable() const;
+
+ QVariant metaData(QtMultimediaKit::MetaData key) const;
+ QList<QtMultimediaKit::MetaData> availableMetaData() const;
+
+ QVariant extendedMetaData(const QString &key) const ;
+ QStringList availableExtendedMetaData() const;
+
+private slots:
+ void updateTags();
+
+private:
+ QGstreamerPlayerSession *m_session;
+};
+
+#endif // QGSTREAMERMETADATAPROVIDER_H
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp
new file mode 100644
index 000000000..f36dd08a3
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp
@@ -0,0 +1,748 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamerplayercontrol.h"
+#include "qgstreamerplayersession.h"
+#include "playerresourcepolicy.h"
+
+#include <qmediaplaylistnavigator.h>
+
+
+#include <QtCore/qdir.h>
+#include <QtCore/qsocketnotifier.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qdebug.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+//#define DEBUG_PLAYBIN
+
+QGstreamerPlayerControl::QGstreamerPlayerControl(QGstreamerPlayerSession *session, QObject *parent)
+ : QMediaPlayerControl(parent)
+ , m_ownStream(false)
+ , m_session(session)
+ , m_state(QMediaPlayer::StoppedState)
+ , m_mediaStatus(QMediaPlayer::NoMedia)
+ , m_bufferProgress(-1)
+ , m_seekToStartPending(false)
+ , m_pendingSeekPosition(-1)
+ , m_stream(0)
+ , m_fifoNotifier(0)
+ , m_fifoCanWrite(false)
+ , m_bufferSize(0)
+ , m_bufferOffset(0)
+{
+ m_fifoFd[0] = -1;
+ m_fifoFd[1] = -1;
+
+ m_resources = new PlayerResourcePolicy(this);
+
+ connect(m_session, SIGNAL(positionChanged(qint64)),
+ this, SIGNAL(positionChanged(qint64)));
+ connect(m_session, SIGNAL(durationChanged(qint64)),
+ this, SIGNAL(durationChanged(qint64)));
+ connect(m_session, SIGNAL(mutedStateChanged(bool)),
+ this, SIGNAL(mutedChanged(bool)));
+ connect(m_session, SIGNAL(volumeChanged(int)),
+ this, SIGNAL(volumeChanged(int)));
+ connect(m_session, SIGNAL(stateChanged(QMediaPlayer::State)),
+ this, SLOT(updateSessionState(QMediaPlayer::State)));
+ connect(m_session,SIGNAL(bufferingProgressChanged(int)),
+ this, SLOT(setBufferProgress(int)));
+ connect(m_session, SIGNAL(playbackFinished()),
+ this, SLOT(processEOS()));
+ connect(m_session, SIGNAL(audioAvailableChanged(bool)),
+ this, SIGNAL(audioAvailableChanged(bool)));
+ connect(m_session, SIGNAL(videoAvailableChanged(bool)),
+ this, SIGNAL(videoAvailableChanged(bool)));
+ connect(m_session, SIGNAL(seekableChanged(bool)),
+ this, SIGNAL(seekableChanged(bool)));
+ connect(m_session, SIGNAL(error(int,QString)),
+ this, SIGNAL(error(int,QString)));
+ connect(m_session, SIGNAL(invalidMedia()),
+ this, SLOT(handleInvalidMedia()));
+ connect(m_session, SIGNAL(playbackRateChanged(qreal)),
+ this, SIGNAL(playbackRateChanged(qreal)));
+ connect(m_session, SIGNAL(seekableChanged(bool)),
+ this, SLOT(applyPendingSeek(bool)));
+
+ connect(m_resources, SIGNAL(resourcesGranted()), SLOT(handleResourcesGranted()));
+ connect(m_resources, SIGNAL(resourcesDenied()), SLOT(handleResourcesLost()));
+ connect(m_resources, SIGNAL(resourcesLost()), SLOT(handleResourcesLost()));
+}
+
+QGstreamerPlayerControl::~QGstreamerPlayerControl()
+{
+ if (m_fifoFd[0] >= 0) {
+ ::close(m_fifoFd[0]);
+ ::close(m_fifoFd[1]);
+ m_fifoFd[0] = -1;
+ m_fifoFd[1] = -1;
+ }
+}
+
+qint64 QGstreamerPlayerControl::position() const
+{
+ return m_seekToStartPending ? 0 : m_session->position();
+}
+
+qint64 QGstreamerPlayerControl::duration() const
+{
+ return m_session->duration();
+}
+
+QMediaPlayer::State QGstreamerPlayerControl::state() const
+{
+ return m_state;
+}
+
+QMediaPlayer::MediaStatus QGstreamerPlayerControl::mediaStatus() const
+{
+ return m_mediaStatus;
+}
+
+int QGstreamerPlayerControl::bufferStatus() const
+{
+ if (m_bufferProgress == -1) {
+ return m_session->state() == QMediaPlayer::StoppedState ? 0 : 100;
+ } else
+ return m_bufferProgress;
+}
+
+int QGstreamerPlayerControl::volume() const
+{
+ return m_session->volume();
+}
+
+bool QGstreamerPlayerControl::isMuted() const
+{
+ return m_session->isMuted();
+}
+
+bool QGstreamerPlayerControl::isSeekable() const
+{
+ return m_session->isSeekable();
+}
+
+QMediaTimeRange QGstreamerPlayerControl::availablePlaybackRanges() const
+{
+ return m_session->availablePlaybackRanges();
+}
+
+qreal QGstreamerPlayerControl::playbackRate() const
+{
+ return m_session->playbackRate();
+}
+
+void QGstreamerPlayerControl::setPlaybackRate(qreal rate)
+{
+ m_session->setPlaybackRate(rate);
+}
+
+void QGstreamerPlayerControl::setPosition(qint64 pos)
+{
+#ifdef DEBUG_PLAYBIN
+ qDebug() << Q_FUNC_INFO << pos/1000.0;
+#endif
+
+ pushState();
+
+ if (m_mediaStatus == QMediaPlayer::EndOfMedia) {
+ m_mediaStatus = QMediaPlayer::LoadedMedia;
+ m_seekToStartPending = true;
+ }
+
+ if (m_session->isSeekable() && m_session->seek(pos)) {
+ m_seekToStartPending = false;
+ m_pendingSeekPosition = -1;
+ } else {
+ m_pendingSeekPosition = pos;
+ }
+
+ popAndNotifyState();
+}
+
+void QGstreamerPlayerControl::play()
+{
+#ifdef DEBUG_PLAYBIN
+ qDebug() << Q_FUNC_INFO;
+#endif
+
+ playOrPause(QMediaPlayer::PlayingState);
+}
+
+void QGstreamerPlayerControl::pause()
+{
+#ifdef DEBUG_PLAYBIN
+ qDebug() << Q_FUNC_INFO;
+#endif
+
+ playOrPause(QMediaPlayer::PausedState);
+}
+
+void QGstreamerPlayerControl::playOrPause(QMediaPlayer::State newState)
+{
+ if (m_mediaStatus == QMediaPlayer::NoMedia)
+ return;
+
+ pushState();
+#ifdef Q_WS_MAEMO_6
+ //this is a work around for the gstreamer bug,
+ //should be remove once it get fixed
+ if (newState == QMediaPlayer::PlayingState && m_mediaStatus == QMediaPlayer::InvalidMedia) {
+ setMedia(m_currentResource, m_stream);
+ }
+#endif
+
+ if (m_mediaStatus == QMediaPlayer::EndOfMedia) {
+ m_mediaStatus = QMediaPlayer::BufferedMedia;
+ m_seekToStartPending = true;
+ }
+
+ if (!m_resources->isGranted() && !m_resources->isRequested())
+ m_resources->acquire();
+
+ if (m_resources->isGranted()) {
+ if (m_seekToStartPending) {
+ m_session->pause();
+ if (!m_session->seek(0)) {
+ m_bufferProgress = -1;
+ m_session->stop();
+ m_mediaStatus = QMediaPlayer::LoadingMedia;
+ }
+ m_seekToStartPending = false;
+ }
+
+ bool ok = false;
+
+ if (newState == QMediaPlayer::PlayingState)
+ ok = m_session->play();
+ else
+ ok = m_session->pause();
+
+ if (!ok)
+ newState = QMediaPlayer::StoppedState;
+ }
+
+ if (m_mediaStatus == QMediaPlayer::InvalidMedia)
+ m_mediaStatus = QMediaPlayer::LoadingMedia;
+
+ m_state = newState;
+
+ if (m_mediaStatus == QMediaPlayer::EndOfMedia || m_mediaStatus == QMediaPlayer::LoadedMedia) {
+ if (m_bufferProgress == -1 || m_bufferProgress == 100)
+ m_mediaStatus = QMediaPlayer::BufferedMedia;
+ else
+ m_mediaStatus = QMediaPlayer::BufferingMedia;
+ }
+
+ popAndNotifyState();
+
+ emit positionChanged(position());
+}
+
+void QGstreamerPlayerControl::stop()
+{
+#ifdef DEBUG_PLAYBIN
+ qDebug() << Q_FUNC_INFO;
+#endif
+
+ pushState();
+
+ if (m_state != QMediaPlayer::StoppedState) {
+ m_state = QMediaPlayer::StoppedState;
+ if (m_resources->isGranted())
+ m_session->pause();
+
+ if (m_mediaStatus != QMediaPlayer::EndOfMedia) {
+ m_seekToStartPending = true;
+ emit positionChanged(position());
+ }
+ }
+
+ popAndNotifyState();
+}
+
+void QGstreamerPlayerControl::setVolume(int volume)
+{
+ m_session->setVolume(volume);
+}
+
+void QGstreamerPlayerControl::setMuted(bool muted)
+{
+ m_session->setMuted(muted);
+}
+
+QMediaContent QGstreamerPlayerControl::media() const
+{
+ return m_currentResource;
+}
+
+const QIODevice *QGstreamerPlayerControl::mediaStream() const
+{
+ return m_stream;
+}
+
+void QGstreamerPlayerControl::setMedia(const QMediaContent &content, QIODevice *stream)
+{
+#ifdef DEBUG_PLAYBIN
+ qDebug() << Q_FUNC_INFO;
+#endif
+
+ pushState();
+
+ m_state = QMediaPlayer::StoppedState;
+ QMediaContent oldMedia = m_currentResource;
+ m_pendingSeekPosition = -1;
+
+ if (!content.isNull() || stream) {
+ if (!m_resources->isRequested() && !m_resources->isGranted())
+ m_resources->acquire();
+
+ if (!m_resources->isGranted()) {
+ m_currentResource = content;
+ m_stream = stream;
+
+ m_state = QMediaPlayer::StoppedState;
+ m_mediaStatus = QMediaPlayer::LoadingMedia;
+ if (m_currentResource != oldMedia)
+ emit mediaChanged(m_currentResource);
+ popAndNotifyState();
+ return;
+ }
+ } else {
+ m_resources->release();
+ }
+
+ m_session->stop();
+
+ bool userStreamValid = false;
+
+ if (m_bufferProgress != -1) {
+ m_bufferProgress = -1;
+ emit bufferStatusChanged(0);
+ }
+
+ if (m_stream) {
+#if !defined(HAVE_GST_APPSRC)
+ closeFifo();
+
+ disconnect(m_stream, SIGNAL(readyRead()), this, SLOT(writeFifo()));
+#endif
+
+ if (m_ownStream)
+ delete m_stream;
+ m_stream = 0;
+ m_ownStream = false;
+ }
+
+ // If the canonical URL refers to a Qt resource, open with QFile and use
+ // the stream playback capability to play.
+ if (stream == 0 && content.canonicalUrl().scheme() == QLatin1String("qrc")) {
+ stream = new QFile(QLatin1Char(':') + content.canonicalUrl().path(), this);
+ if (!stream->open(QIODevice::ReadOnly)) {
+ delete stream;
+ m_mediaStatus = QMediaPlayer::InvalidMedia;
+ m_currentResource = content;
+ emit mediaChanged(m_currentResource);
+ emit error(QMediaPlayer::FormatError, tr("Attempting to play invalid Qt resource"));
+ if (m_state != QMediaPlayer::PlayingState)
+ m_resources->release();
+ popAndNotifyState();
+ return;
+ }
+ m_ownStream = true;
+ }
+
+ m_currentResource = content;
+ m_stream = stream;
+ m_seekToStartPending = false;
+
+ QNetworkRequest request;
+
+ if (m_stream) {
+#if !defined(HAVE_GST_APPSRC)
+ if (m_stream->isReadable() && openFifo()) {
+ request = QNetworkRequest(QUrl(QString(QLatin1String("fd://%1")).arg(m_fifoFd[0])));
+ }
+#else
+ userStreamValid = stream->isOpen() && m_stream->isReadable();
+ request = content.canonicalRequest();
+#endif
+ } else if (!content.isNull()) {
+ request = content.canonicalRequest();
+ }
+
+#if !defined(HAVE_GST_APPSRC)
+ m_session->loadFromUri(request);
+#else
+ if (m_stream) {
+ if (userStreamValid){
+ m_session->loadFromStream(request, m_stream);
+ } else {
+ m_mediaStatus = QMediaPlayer::InvalidMedia;
+ emit error(QMediaPlayer::FormatError, tr("Attempting to play invalid user stream"));
+ if (m_state != QMediaPlayer::PlayingState)
+ m_resources->release();
+ popAndNotifyState();
+ return;
+ }
+ } else
+ m_session->loadFromUri(request);
+#endif
+
+#if !defined(HAVE_GST_APPSRC)
+ if (m_fifoFd[1] >= 0) {
+ m_fifoCanWrite = true;
+
+ writeFifo();
+ }
+#endif
+
+#if defined(HAVE_GST_APPSRC)
+ if (!request.url().isEmpty() || userStreamValid) {
+#else
+ if (!request.url().isEmpty()) {
+#endif
+ m_mediaStatus = QMediaPlayer::LoadingMedia;
+ m_session->pause();
+ } else {
+ m_mediaStatus = QMediaPlayer::NoMedia;
+ setBufferProgress(0);
+ }
+
+ if (m_currentResource != oldMedia)
+ emit mediaChanged(m_currentResource);
+
+ emit positionChanged(position());
+
+ if (content.isNull() && !stream)
+ m_resources->release();
+
+ popAndNotifyState();
+}
+
+void QGstreamerPlayerControl::setVideoOutput(QObject *output)
+{
+ m_session->setVideoRenderer(output);
+}
+
+bool QGstreamerPlayerControl::isAudioAvailable() const
+{
+ return m_session->isAudioAvailable();
+}
+
+bool QGstreamerPlayerControl::isVideoAvailable() const
+{
+ return m_session->isVideoAvailable();
+}
+
+void QGstreamerPlayerControl::updateSessionState(QMediaPlayer::State state)
+{
+ pushState();
+
+ if (state == QMediaPlayer::StoppedState)
+ m_state = QMediaPlayer::StoppedState;
+
+ updateMediaStatus();
+
+ popAndNotifyState();
+}
+
+void QGstreamerPlayerControl::updateMediaStatus()
+{
+ pushState();
+ QMediaPlayer::MediaStatus oldStatus = m_mediaStatus;
+
+ switch (m_session->state()) {
+ case QMediaPlayer::StoppedState:
+ if (m_currentResource.isNull())
+ m_mediaStatus = QMediaPlayer::NoMedia;
+ else if (oldStatus != QMediaPlayer::InvalidMedia)
+ m_mediaStatus = QMediaPlayer::LoadingMedia;
+ break;
+
+ case QMediaPlayer::PlayingState:
+ case QMediaPlayer::PausedState:
+ if (m_state == QMediaPlayer::StoppedState) {
+ m_mediaStatus = QMediaPlayer::LoadedMedia;
+ } else {
+ if (m_bufferProgress == -1 || m_bufferProgress == 100)
+ m_mediaStatus = QMediaPlayer::BufferedMedia;
+ else
+ m_mediaStatus = QMediaPlayer::StalledMedia;
+ }
+ break;
+ }
+
+ if (m_state == QMediaPlayer::PlayingState && !m_resources->isGranted())
+ m_mediaStatus = QMediaPlayer::StalledMedia;
+
+ //EndOfMedia status should be kept, until reset by pause, play or setMedia
+ if (oldStatus == QMediaPlayer::EndOfMedia)
+ m_mediaStatus = QMediaPlayer::EndOfMedia;
+
+ popAndNotifyState();
+}
+
+void QGstreamerPlayerControl::processEOS()
+{
+ pushState();
+ m_mediaStatus = QMediaPlayer::EndOfMedia;
+ emit positionChanged(position());
+ stop();
+ popAndNotifyState();
+}
+
+void QGstreamerPlayerControl::setBufferProgress(int progress)
+{
+ if (m_bufferProgress == progress || m_mediaStatus == QMediaPlayer::NoMedia)
+ return;
+
+#ifdef DEBUG_PLAYBIN
+ qDebug() << Q_FUNC_INFO << progress;
+#endif
+ m_bufferProgress = progress;
+
+ if (m_resources->isGranted()) {
+ if (m_state == QMediaPlayer::PlayingState &&
+ m_bufferProgress == 100 &&
+ m_session->state() != QMediaPlayer::PlayingState)
+ m_session->play();
+
+ if (m_bufferProgress < 100 &&
+ (m_session->state() == QMediaPlayer::PlayingState ||
+ m_session->pendingState() == QMediaPlayer::PlayingState))
+ m_session->pause();
+ }
+
+ updateMediaStatus();
+
+ emit bufferStatusChanged(m_bufferProgress);
+}
+
+void QGstreamerPlayerControl::writeFifo()
+{
+ if (m_fifoCanWrite) {
+ qint64 bytesToRead = qMin<qint64>(
+ m_stream->bytesAvailable(), PIPE_BUF - m_bufferSize);
+
+ if (bytesToRead > 0) {
+ int bytesRead = m_stream->read(&m_buffer[m_bufferOffset + m_bufferSize], bytesToRead);
+
+ if (bytesRead > 0)
+ m_bufferSize += bytesRead;
+ }
+
+ if (m_bufferSize > 0) {
+ int bytesWritten = ::write(m_fifoFd[1], &m_buffer[m_bufferOffset], size_t(m_bufferSize));
+
+ if (bytesWritten > 0) {
+ m_bufferOffset += bytesWritten;
+ m_bufferSize -= bytesWritten;
+
+ if (m_bufferSize == 0)
+ m_bufferOffset = 0;
+ } else if (errno == EAGAIN) {
+ m_fifoCanWrite = false;
+ } else {
+ closeFifo();
+ }
+ }
+ }
+
+ m_fifoNotifier->setEnabled(m_stream->bytesAvailable() > 0);
+}
+
+void QGstreamerPlayerControl::fifoReadyWrite(int socket)
+{
+ if (socket == m_fifoFd[1]) {
+ m_fifoCanWrite = true;
+
+ writeFifo();
+ }
+}
+
+bool QGstreamerPlayerControl::openFifo()
+{
+ Q_ASSERT(m_fifoFd[0] < 0);
+ Q_ASSERT(m_fifoFd[1] < 0);
+
+ if (::pipe(m_fifoFd) == 0) {
+ int flags = ::fcntl(m_fifoFd[1], F_GETFD);
+
+ if (::fcntl(m_fifoFd[1], F_SETFD, flags | O_NONBLOCK) >= 0) {
+ m_fifoNotifier = new QSocketNotifier(m_fifoFd[1], QSocketNotifier::Write);
+
+ connect(m_fifoNotifier, SIGNAL(activated(int)), this, SLOT(fifoReadyWrite(int)));
+
+ return true;
+ } else {
+ qWarning("Failed to make pipe non blocking %d", errno);
+
+ ::close(m_fifoFd[0]);
+ ::close(m_fifoFd[1]);
+
+ m_fifoFd[0] = -1;
+ m_fifoFd[1] = -1;
+
+ return false;
+ }
+ } else {
+ qWarning("Failed to create pipe %d", errno);
+
+ return false;
+ }
+}
+
+void QGstreamerPlayerControl::closeFifo()
+{
+ if (m_fifoFd[0] >= 0) {
+ delete m_fifoNotifier;
+ m_fifoNotifier = 0;
+
+ ::close(m_fifoFd[0]);
+ ::close(m_fifoFd[1]);
+ m_fifoFd[0] = -1;
+ m_fifoFd[1] = -1;
+
+ m_fifoCanWrite = false;
+
+ m_bufferSize = 0;
+ m_bufferOffset = 0;
+ }
+}
+
+void QGstreamerPlayerControl::applyPendingSeek(bool isSeekable)
+{
+ if (isSeekable && m_pendingSeekPosition != -1)
+ setPosition(m_pendingSeekPosition);
+}
+
+void QGstreamerPlayerControl::handleInvalidMedia()
+{
+ pushState();
+ m_mediaStatus = QMediaPlayer::InvalidMedia;
+ m_state = QMediaPlayer::StoppedState;
+ popAndNotifyState();
+}
+
+void QGstreamerPlayerControl::handleResourcesGranted()
+{
+ pushState();
+
+ QMediaPlayer::State state = m_state;
+
+ //preserve m_pendingSeekPosition, it's reset on setMedia
+ qint64 pos = m_pendingSeekPosition;
+ setMedia(m_currentResource, m_stream);
+
+ if (pos != -1)
+ setPosition(pos);
+
+ if (state != QMediaPlayer::StoppedState)
+ playOrPause(state);
+ else
+ updateMediaStatus();
+
+ popAndNotifyState();
+}
+
+void QGstreamerPlayerControl::handleResourcesLost()
+{
+ //on resource lost the pipeline should be stopped
+ //player status is changed to paused
+
+ pushState();
+ QMediaPlayer::State oldState = m_state;
+
+ qint64 pos = m_session->position();
+ m_session->stop();
+ m_pendingSeekPosition = pos;
+
+ if (oldState != QMediaPlayer::StoppedState )
+ m_state = QMediaPlayer::PausedState;
+
+ popAndNotifyState();
+}
+
+bool QGstreamerPlayerControl::isMediaDownloadEnabled() const
+{
+ return m_session->property("mediaDownloadEnabled").toBool();
+}
+
+void QGstreamerPlayerControl::setMediaDownloadEnabled(bool enabled)
+{
+ m_session->setProperty("mediaDownloadEnabled", enabled);
+}
+
+void QGstreamerPlayerControl::pushState()
+{
+ m_stateStack.push(m_state);
+ m_mediaStatusStack.push(m_mediaStatus);
+}
+
+void QGstreamerPlayerControl::popAndNotifyState()
+{
+ Q_ASSERT(!m_stateStack.isEmpty());
+
+ QMediaPlayer::State oldState = m_stateStack.pop();
+ QMediaPlayer::MediaStatus oldMediaStatus = m_mediaStatusStack.pop();
+
+ if (m_stateStack.isEmpty()) {
+ if (m_state != oldState) {
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "State changed:" << m_state;
+#endif
+ emit stateChanged(m_state);
+ }
+
+ if (m_mediaStatus != oldMediaStatus) {
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "Media status changed:" << m_mediaStatus;
+#endif
+ emit mediaStatusChanged(m_mediaStatus);
+ }
+ }
+}
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h
new file mode 100644
index 000000000..5a53a0713
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERPLAYERCONTROL_H
+#define QGSTREAMERPLAYERCONTROL_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstack.h>
+
+#include <qmediaplayercontrol.h>
+#include <qmediaplayer.h>
+
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+class QMediaPlaylist;
+class QMediaPlaylistNavigator;
+class QSocketNotifier;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class QGstreamerPlayerSession;
+class QGstreamerPlayerService;
+class PlayerResourcePolicy;
+
+class QGstreamerPlayerControl : public QMediaPlayerControl
+{
+ Q_OBJECT
+ Q_PROPERTY(bool mediaDownloadEnabled READ isMediaDownloadEnabled WRITE setMediaDownloadEnabled)
+
+public:
+ QGstreamerPlayerControl(QGstreamerPlayerSession *session, QObject *parent = 0);
+ ~QGstreamerPlayerControl();
+
+ QMediaPlayer::State state() const;
+ QMediaPlayer::MediaStatus mediaStatus() const;
+
+ qint64 position() const;
+ qint64 duration() const;
+
+ int bufferStatus() const;
+
+ int volume() const;
+ bool isMuted() const;
+
+ bool isAudioAvailable() const;
+ bool isVideoAvailable() const;
+ void setVideoOutput(QObject *output);
+
+ bool isSeekable() const;
+ QMediaTimeRange availablePlaybackRanges() const;
+
+ qreal playbackRate() const;
+ void setPlaybackRate(qreal rate);
+
+ QMediaContent media() const;
+ const QIODevice *mediaStream() const;
+ void setMedia(const QMediaContent&, QIODevice *);
+
+ bool isMediaDownloadEnabled() const;
+ void setMediaDownloadEnabled(bool enabled);
+
+public Q_SLOTS:
+ void setPosition(qint64 pos);
+
+ void play();
+ void pause();
+ void stop();
+
+ void setVolume(int volume);
+ void setMuted(bool muted);
+
+private Q_SLOTS:
+ void writeFifo();
+ void fifoReadyWrite(int socket);
+
+ void updateSessionState(QMediaPlayer::State state);
+ void updateMediaStatus();
+ void processEOS();
+ void setBufferProgress(int progress);
+ void applyPendingSeek(bool isSeekable);
+
+ void handleInvalidMedia();
+
+ void handleResourcesGranted();
+ void handleResourcesLost();
+
+private:
+ bool openFifo();
+ void closeFifo();
+ void playOrPause(QMediaPlayer::State state);
+
+ void pushState();
+ void popAndNotifyState();
+
+ bool m_ownStream;
+ QGstreamerPlayerSession *m_session;
+ QMediaPlayer::State m_state;
+ QMediaPlayer::MediaStatus m_mediaStatus;
+ QStack<QMediaPlayer::State> m_stateStack;
+ QStack<QMediaPlayer::MediaStatus> m_mediaStatusStack;
+
+ int m_bufferProgress;
+ bool m_seekToStartPending;
+ qint64 m_pendingSeekPosition;
+ QMediaContent m_currentResource;
+ QIODevice *m_stream;
+ QSocketNotifier *m_fifoNotifier;
+ int m_fifoFd[2];
+ bool m_fifoCanWrite;
+ int m_bufferSize;
+ int m_bufferOffset;
+ char m_buffer[PIPE_BUF];
+
+ PlayerResourcePolicy *m_resources;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp
new file mode 100644
index 000000000..6976c18ae
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp
@@ -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$
+** 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 <QtCore/qvariant.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/qwidget.h>
+
+#include "qgstreamerplayerservice.h"
+#include "qgstreamerplayercontrol.h"
+#include "qgstreamerplayersession.h"
+#include "qgstreamermetadataprovider.h"
+
+#include "qgstreamervideooverlay.h"
+#include "qgstreamervideowindow.h"
+#include "qgstreamervideorenderer.h"
+
+#if defined(Q_WS_MAEMO_6) && defined(__arm__)
+#include "qgstreamergltexturerenderer.h"
+#endif
+
+#include "qgstreamervideowidget.h"
+#include "qgstreamerstreamscontrol.h"
+
+#include <qmediaplaylistnavigator.h>
+#include <qmediaplaylist.h>
+
+QGstreamerPlayerService::QGstreamerPlayerService(QObject *parent):
+ QMediaService(parent),
+ m_videoOutput(0),
+ m_videoRenderer(0),
+ m_videoWindow(0),
+ m_videoWidget(0)
+{
+ m_session = new QGstreamerPlayerSession(this);
+ m_control = new QGstreamerPlayerControl(m_session, this);
+ m_metaData = new QGstreamerMetaDataProvider(m_session, this);
+ m_streamsControl = new QGstreamerStreamsControl(m_session,this);
+
+#if defined(Q_WS_MAEMO_6) && defined(__arm__)
+ m_videoRenderer = new QGstreamerGLTextureRenderer(this);
+#else
+ m_videoRenderer = new QGstreamerVideoRenderer(this);
+#endif
+
+#if defined(Q_WS_X11) && !defined(QT_NO_XVIDEO)
+
+#ifdef Q_WS_MAEMO_6
+ m_videoWindow = new QGstreamerVideoWindow(this, "omapxvsink");
+#else
+ m_videoWindow = new QGstreamerVideoOverlay(this);
+#endif
+
+ m_videoWidget = new QGstreamerVideoWidgetControl(this);
+#endif
+}
+
+QGstreamerPlayerService::~QGstreamerPlayerService()
+{
+}
+
+QMediaControl *QGstreamerPlayerService::requestControl(const char *name)
+{
+ if (qstrcmp(name,QMediaPlayerControl_iid) == 0)
+ return m_control;
+
+ if (qstrcmp(name,QMetaDataReaderControl_iid) == 0)
+ return m_metaData;
+
+ if (qstrcmp(name,QMediaStreamsControl_iid) == 0)
+ return m_streamsControl;
+
+ if (!m_videoOutput) {
+ if (qstrcmp(name, QVideoWidgetControl_iid) == 0)
+ m_videoOutput = m_videoWidget;
+ else if (qstrcmp(name, QVideoRendererControl_iid) == 0)
+ m_videoOutput = m_videoRenderer;
+ else if (qstrcmp(name, QVideoWindowControl_iid) == 0)
+ m_videoOutput = m_videoWindow;
+
+ if (m_videoOutput) {
+ m_control->setVideoOutput(m_videoOutput);
+ return m_videoOutput;
+ }
+ }
+
+ return 0;
+}
+
+void QGstreamerPlayerService::releaseControl(QMediaControl *control)
+{
+ if (control == m_videoOutput) {
+ m_videoOutput = 0;
+ m_control->setVideoOutput(0);
+ }
+}
+
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h
new file mode 100644
index 000000000..92ea9ffa4
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERPLAYERSERVICE_H
+#define QGSTREAMERPLAYERSERVICE_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qiodevice.h>
+
+#include <qmediaservice.h>
+
+QT_BEGIN_NAMESPACE
+class QMediaMetaData;
+class QMediaPlayerControl;
+class QMediaPlaylist;
+class QMediaPlaylistNavigator;
+QT_END_NAMESPACE
+
+class QGstreamerMetaData;
+class QGstreamerPlayerControl;
+class QGstreamerPlayerSession;
+class QGstreamerMetaDataProvider;
+class QGstreamerStreamsControl;
+class QGstreamerVideoRenderer;
+class QGstreamerVideoOverlay;
+class QGstreamerVideoWidgetControl;
+
+QT_USE_NAMESPACE
+
+class QGstreamerPlayerService : public QMediaService
+{
+ Q_OBJECT
+public:
+ QGstreamerPlayerService(QObject *parent = 0);
+ ~QGstreamerPlayerService();
+
+ QMediaControl *requestControl(const char *name);
+ void releaseControl(QMediaControl *control);
+
+private:
+ QGstreamerPlayerControl *m_control;
+ QGstreamerPlayerSession *m_session;
+ QGstreamerMetaDataProvider *m_metaData;
+ QGstreamerStreamsControl *m_streamsControl;
+
+ QMediaControl *m_videoOutput;
+ QMediaControl *m_videoRenderer;
+ QMediaControl *m_videoWindow;
+ QMediaControl *m_videoWidget;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
new file mode 100644
index 000000000..d12bb2697
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp
@@ -0,0 +1,1537 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamerplayersession.h"
+#include "qgstreamerbushelper.h"
+
+#include "qgstreamervideorendererinterface.h"
+#include "gstvideoconnector.h"
+#include "qgstutils.h"
+
+#include <gst/gstvalue.h>
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qdir.h>
+#include <QtGui/qdesktopservices.h>
+
+#if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) || (GST_VERSION_MICRO > 20)
+#define USE_PLAYBIN2
+#endif
+
+//#define DEBUG_PLAYBIN
+//#define DEBUG_VO_BIN_DUMP
+
+typedef enum {
+ GST_PLAY_FLAG_VIDEO = 0x00000001,
+ GST_PLAY_FLAG_AUDIO = 0x00000002,
+ GST_PLAY_FLAG_TEXT = 0x00000004,
+ GST_PLAY_FLAG_VIS = 0x00000008,
+ GST_PLAY_FLAG_SOFT_VOLUME = 0x00000010,
+ GST_PLAY_FLAG_NATIVE_AUDIO = 0x00000020,
+ GST_PLAY_FLAG_NATIVE_VIDEO = 0x00000040,
+ GST_PLAY_FLAG_DOWNLOAD = 0x00000080,
+ GST_PLAY_FLAG_BUFFERING = 0x000000100
+} GstPlayFlags;
+
+QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent)
+ :QObject(parent),
+ m_state(QMediaPlayer::StoppedState),
+ m_pendingState(QMediaPlayer::StoppedState),
+ m_busHelper(0),
+ m_playbin(0),
+ m_usePlaybin2(false),
+ m_usingColorspaceElement(false),
+ m_videoSink(0),
+ m_pendingVideoSink(0),
+ m_nullVideoSink(0),
+ m_bus(0),
+ m_videoOutput(0),
+ m_renderer(0),
+ m_haveQueueElement(false),
+#if defined(HAVE_GST_APPSRC)
+ m_appSrc(0),
+#endif
+ m_volume(100),
+ m_playbackRate(1.0),
+ m_muted(false),
+ m_audioAvailable(false),
+ m_videoAvailable(false),
+ m_seekable(false),
+ m_lastPosition(0),
+ m_duration(-1),
+ m_durationQueries(0),
+ m_everPlayed(false) ,
+ m_sourceType(UnknownSrc)
+{
+#ifdef USE_PLAYBIN2
+ m_playbin = gst_element_factory_make("playbin2", NULL);
+#endif
+
+ if (m_playbin) {
+ m_usePlaybin2 = true;
+
+ //GST_PLAY_FLAG_NATIVE_VIDEO omits configuration of ffmpegcolorspace and videoscale,
+ //since those elements are included in the video output bin when necessary.
+#ifdef Q_WS_MAEMO_6
+ int flags = GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO |
+ GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_NATIVE_AUDIO;
+#else
+ int flags = 0;
+ g_object_get(G_OBJECT(m_playbin), "flags", &flags, NULL);
+ flags |= GST_PLAY_FLAG_NATIVE_VIDEO;
+#endif
+ g_object_set(G_OBJECT(m_playbin), "flags", flags, NULL);
+ } else {
+ m_usePlaybin2 = false;
+ m_playbin = gst_element_factory_make("playbin", NULL);
+ }
+
+ m_videoOutputBin = gst_bin_new("video-output-bin");
+ gst_object_ref(GST_OBJECT(m_videoOutputBin));
+
+ m_videoIdentity = GST_ELEMENT(g_object_new(gst_video_connector_get_type(), 0));
+ g_signal_connect(G_OBJECT(m_videoIdentity), "connection-failed", G_CALLBACK(insertColorSpaceElement), (gpointer)this);
+ m_colorSpace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-vo");
+ gst_object_ref(GST_OBJECT(m_colorSpace));
+
+ m_nullVideoSink = gst_element_factory_make("fakesink", NULL);
+ g_object_set(G_OBJECT(m_nullVideoSink), "sync", true, NULL);
+ gst_object_ref(GST_OBJECT(m_nullVideoSink));
+ gst_bin_add_many(GST_BIN(m_videoOutputBin), m_videoIdentity, m_nullVideoSink, NULL);
+ gst_element_link(m_videoIdentity, m_nullVideoSink);
+
+ m_videoSink = m_nullVideoSink;
+
+ // add ghostpads
+ GstPad *pad = gst_element_get_static_pad(m_videoIdentity,"sink");
+ gst_element_add_pad(GST_ELEMENT(m_videoOutputBin), gst_ghost_pad_new("videosink", pad));
+ gst_object_unref(GST_OBJECT(pad));
+
+ if (m_playbin != 0) {
+ // Sort out messages
+ m_bus = gst_element_get_bus(m_playbin);
+ m_busHelper = new QGstreamerBusHelper(m_bus, this);
+ connect(m_busHelper, SIGNAL(message(QGstreamerMessage)), SLOT(busMessage(QGstreamerMessage)));
+ m_busHelper->installSyncEventFilter(this);
+
+ g_object_set(G_OBJECT(m_playbin), "video-sink", m_videoOutputBin, NULL);
+
+ g_signal_connect(G_OBJECT(m_playbin), "notify::source", G_CALLBACK(playbinNotifySource), this);
+ g_signal_connect(G_OBJECT(m_playbin), "element-added", G_CALLBACK(handleElementAdded), this);
+
+ // Initial volume
+ double volume = 1.0;
+ g_object_get(G_OBJECT(m_playbin), "volume", &volume, NULL);
+ m_volume = int(volume*100);
+
+ g_signal_connect(G_OBJECT(m_playbin), "notify::volume", G_CALLBACK(handleVolumeChange), this);
+ if (m_usePlaybin2)
+ g_signal_connect(G_OBJECT(m_playbin), "notify::mute", G_CALLBACK(handleMutedChange), this);
+ }
+}
+
+QGstreamerPlayerSession::~QGstreamerPlayerSession()
+{
+ if (m_playbin) {
+ stop();
+
+ delete m_busHelper;
+ gst_object_unref(GST_OBJECT(m_bus));
+ gst_object_unref(GST_OBJECT(m_playbin));
+ gst_object_unref(GST_OBJECT(m_colorSpace));
+ gst_object_unref(GST_OBJECT(m_nullVideoSink));
+ gst_object_unref(GST_OBJECT(m_videoOutputBin));
+ }
+}
+
+#if defined(HAVE_GST_APPSRC)
+void QGstreamerPlayerSession::configureAppSrcElement(GObject* object, GObject *orig, GParamSpec *pspec, QGstreamerPlayerSession* self)
+{
+ if (self->appsrc()->isReady())
+ return;
+
+ GstElement *appsrc;
+ g_object_get(orig, "source", &appsrc, NULL);
+
+ if (!self->appsrc()->setup(appsrc))
+ qWarning()<<"Could not setup appsrc element";
+}
+#endif
+
+void QGstreamerPlayerSession::loadFromStream(const QNetworkRequest &request, QIODevice *appSrcStream)
+{
+#if defined(HAVE_GST_APPSRC)
+ m_request = request;
+ m_duration = -1;
+ m_lastPosition = 0;
+ m_haveQueueElement = false;
+
+ if (m_appSrc)
+ m_appSrc->deleteLater();
+ m_appSrc = new QGstAppSrc(this);
+ m_appSrc->setStream(appSrcStream);
+
+ if (m_playbin) {
+ m_tags.clear();
+ emit tagsChanged();
+
+ g_signal_connect(G_OBJECT(m_playbin), "deep-notify::source", (GCallback) &QGstreamerPlayerSession::configureAppSrcElement, (gpointer)this);
+ g_object_set(G_OBJECT(m_playbin), "uri", "appsrc://", NULL);
+
+ if (!m_streamTypes.isEmpty()) {
+ m_streamProperties.clear();
+ m_streamTypes.clear();
+
+ emit streamsChanged();
+ }
+ }
+#endif
+}
+
+void QGstreamerPlayerSession::loadFromUri(const QNetworkRequest &request)
+{
+ m_request = request;
+ m_duration = -1;
+ m_lastPosition = 0;
+ m_haveQueueElement = false;
+
+ if (m_playbin) {
+ m_tags.clear();
+ emit tagsChanged();
+
+ g_object_set(G_OBJECT(m_playbin), "uri", m_request.url().toEncoded().constData(), NULL);
+
+ if (!m_streamTypes.isEmpty()) {
+ m_streamProperties.clear();
+ m_streamTypes.clear();
+
+ emit streamsChanged();
+ }
+ }
+}
+
+qint64 QGstreamerPlayerSession::duration() const
+{
+ return m_duration;
+}
+
+qint64 QGstreamerPlayerSession::position() const
+{
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 position = 0;
+
+ if ( m_playbin && gst_element_query_position(m_playbin, &format, &position))
+ m_lastPosition = position / 1000000;
+
+ return m_lastPosition;
+}
+
+qreal QGstreamerPlayerSession::playbackRate() const
+{
+ return m_playbackRate;
+}
+
+void QGstreamerPlayerSession::setPlaybackRate(qreal rate)
+{
+ if (!qFuzzyCompare(m_playbackRate, rate)) {
+ m_playbackRate = rate;
+ if (m_playbin) {
+ gst_element_seek(m_playbin, rate, GST_FORMAT_TIME,
+ GstSeekFlags(GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH),
+ GST_SEEK_TYPE_NONE,0,
+ GST_SEEK_TYPE_NONE,0 );
+ }
+ emit playbackRateChanged(m_playbackRate);
+ }
+}
+
+QMediaTimeRange QGstreamerPlayerSession::availablePlaybackRanges() const
+{
+ QMediaTimeRange ranges;
+#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 31)
+ //GST_FORMAT_TIME would be more appropriate, but unfortunately it's not supported.
+ //with GST_FORMAT_PERCENT media is treated as encoded with constant bitrate.
+ GstQuery* query = gst_query_new_buffering(GST_FORMAT_PERCENT);
+
+ if (gst_element_query(m_playbin, query)) {
+ for (guint index = 0; index < gst_query_get_n_buffering_ranges(query); index++) {
+ gint64 rangeStart = 0;
+ gint64 rangeStop = 0;
+
+ //This query should return values in GST_FORMAT_PERCENT_MAX range,
+ //but queue2 returns values in 0..100 range instead
+ if (gst_query_parse_nth_buffering_range(query, index, &rangeStart, &rangeStop))
+ ranges.addInterval(rangeStart * duration() / 100,
+ rangeStop * duration() / 100);
+ }
+ }
+
+ gst_query_unref(query);
+#endif
+
+ //without queue2 element in pipeline all the media is considered available
+ if (ranges.isEmpty() && duration() > 0 && !m_haveQueueElement)
+ ranges.addInterval(0, duration());
+
+#ifdef DEBUG_PLAYBIN
+ qDebug() << ranges;
+#endif
+
+ return ranges;
+}
+
+int QGstreamerPlayerSession::activeStream(QMediaStreamsControl::StreamType streamType) const
+{
+ int streamNumber = -1;
+ if (m_playbin) {
+ switch (streamType) {
+ case QMediaStreamsControl::AudioStream:
+ g_object_get(G_OBJECT(m_playbin), "current-audio", streamNumber, NULL);
+ break;
+ case QMediaStreamsControl::VideoStream:
+ g_object_get(G_OBJECT(m_playbin), "current-video", streamNumber, NULL);
+ break;
+ case QMediaStreamsControl::SubPictureStream:
+ g_object_get(G_OBJECT(m_playbin), "current-text", streamNumber, NULL);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (m_usePlaybin2 && streamNumber >= 0)
+ streamNumber += m_playbin2StreamOffset.value(streamType,0);
+
+ return streamNumber;
+}
+
+void QGstreamerPlayerSession::setActiveStream(QMediaStreamsControl::StreamType streamType, int streamNumber)
+{
+
+ if (m_usePlaybin2 && streamNumber >= 0)
+ streamNumber -= m_playbin2StreamOffset.value(streamType,0);
+
+ if (m_playbin) {
+ switch (streamType) {
+ case QMediaStreamsControl::AudioStream:
+ g_object_set(G_OBJECT(m_playbin), "current-audio", &streamNumber, NULL);
+ break;
+ case QMediaStreamsControl::VideoStream:
+ g_object_set(G_OBJECT(m_playbin), "current-video", &streamNumber, NULL);
+ break;
+ case QMediaStreamsControl::SubPictureStream:
+ g_object_set(G_OBJECT(m_playbin), "current-text", &streamNumber, NULL);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+
+bool QGstreamerPlayerSession::isBuffering() const
+{
+ return false;
+}
+
+int QGstreamerPlayerSession::bufferingProgress() const
+{
+ return 0;
+}
+
+int QGstreamerPlayerSession::volume() const
+{
+ return m_volume;
+}
+
+bool QGstreamerPlayerSession::isMuted() const
+{
+ return m_muted;
+}
+
+bool QGstreamerPlayerSession::isAudioAvailable() const
+{
+ return m_audioAvailable;
+}
+
+static void block_pad_cb(GstPad *pad, gboolean blocked, gpointer user_data)
+{
+ Q_UNUSED(pad);
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "block_pad_cb, blocked:" << blocked;
+#endif
+
+ if (blocked && user_data) {
+ QGstreamerPlayerSession *session = reinterpret_cast<QGstreamerPlayerSession*>(user_data);
+ QMetaObject::invokeMethod(session, "finishVideoOutputChange", Qt::QueuedConnection);
+ }
+}
+
+void QGstreamerPlayerSession::updateVideoRenderer()
+{
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "Video sink has chaged, reload video output";
+#endif
+
+ if (m_videoOutput)
+ setVideoRenderer(m_videoOutput);
+}
+
+void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput)
+{
+ if (m_videoOutput != videoOutput) {
+ if (m_videoOutput) {
+ disconnect(m_videoOutput, SIGNAL(sinkChanged()),
+ this, SLOT(updateVideoRenderer()));
+ disconnect(m_videoOutput, SIGNAL(readyChanged(bool)),
+ this, SLOT(updateVideoRenderer()));
+ }
+
+ if (videoOutput) {
+ connect(videoOutput, SIGNAL(sinkChanged()),
+ this, SLOT(updateVideoRenderer()));
+ connect(videoOutput, SIGNAL(readyChanged(bool)),
+ this, SLOT(updateVideoRenderer()));
+ }
+
+ m_videoOutput = videoOutput;
+ }
+
+ QGstreamerVideoRendererInterface* renderer = qobject_cast<QGstreamerVideoRendererInterface*>(videoOutput);
+
+ m_renderer = renderer;
+
+#ifdef DEBUG_VO_BIN_DUMP
+ _gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
+ GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES*/),
+ "playbin_set");
+#endif
+
+ GstElement *videoSink = 0;
+ if (m_renderer && m_renderer->isReady())
+ videoSink = m_renderer->videoSink();
+
+ if (!videoSink)
+ videoSink = m_nullVideoSink;
+
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "Set video output:" << videoOutput;
+ qDebug() << "Current sink:" << (m_videoSink ? GST_ELEMENT_NAME(m_videoSink) : "") << m_videoSink
+ << "pending:" << (m_pendingVideoSink ? GST_ELEMENT_NAME(m_pendingVideoSink) : "") << m_pendingVideoSink
+ << "new sink:" << (videoSink ? GST_ELEMENT_NAME(videoSink) : "") << videoSink;
+#endif
+
+ if (m_pendingVideoSink == videoSink ||
+ (m_pendingVideoSink == 0 && m_videoSink == videoSink)) {
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "Video sink has not changed, skip video output reconfiguration";
+#endif
+ return;
+ }
+
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "Reconfigure video output";
+#endif
+
+ if (m_state == QMediaPlayer::StoppedState) {
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "The pipeline has not started yet, pending state:" << m_pendingState;
+#endif
+ //the pipeline has not started yet
+ m_pendingVideoSink = 0;
+ gst_element_set_state(m_videoSink, GST_STATE_NULL);
+ gst_element_set_state(m_playbin, GST_STATE_NULL);
+
+ if (m_usingColorspaceElement) {
+ gst_element_unlink(m_colorSpace, m_videoSink);
+ gst_bin_remove(GST_BIN(m_videoOutputBin), m_colorSpace);
+ } else {
+ gst_element_unlink(m_videoIdentity, m_videoSink);
+ }
+
+ gst_bin_remove(GST_BIN(m_videoOutputBin), m_videoSink);
+
+ m_videoSink = videoSink;
+
+ gst_bin_add(GST_BIN(m_videoOutputBin), m_videoSink);
+
+ m_usingColorspaceElement = false;
+ bool linked = gst_element_link(m_videoIdentity, m_videoSink);
+ if (!linked) {
+ m_usingColorspaceElement = true;
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "Failed to connect video output, inserting the colorspace element.";
+#endif
+ gst_bin_add(GST_BIN(m_videoOutputBin), m_colorSpace);
+ linked = gst_element_link_many(m_videoIdentity, m_colorSpace, m_videoSink, NULL);
+ }
+
+ switch (m_pendingState) {
+ case QMediaPlayer::PausedState:
+ gst_element_set_state(m_playbin, GST_STATE_PAUSED);
+ break;
+ case QMediaPlayer::PlayingState:
+ gst_element_set_state(m_playbin, GST_STATE_PLAYING);
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (m_pendingVideoSink) {
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "already waiting for pad to be blocked, just change the pending sink";
+#endif
+ m_pendingVideoSink = videoSink;
+ return;
+ }
+
+ m_pendingVideoSink = videoSink;
+
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "Blocking the video output pad...";
+#endif
+
+ //block pads, async to avoid locking in paused state
+ GstPad *srcPad = gst_element_get_static_pad(m_videoIdentity, "src");
+ gst_pad_set_blocked_async(srcPad, true, &block_pad_cb, this);
+ gst_object_unref(GST_OBJECT(srcPad));
+
+ //Unpause the sink to avoid waiting until the buffer is processed
+ //while the sink is paused. The pad will be blocked as soon as the current
+ //buffer is processed.
+ if (m_state == QMediaPlayer::PausedState) {
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "Starting video output to avoid blocking in paused state...";
+#endif
+ gst_element_set_state(m_videoSink, GST_STATE_PLAYING);
+ }
+ }
+}
+
+void QGstreamerPlayerSession::finishVideoOutputChange()
+{
+ if (!m_pendingVideoSink)
+ return;
+
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "finishVideoOutputChange" << m_pendingVideoSink;
+#endif
+
+ GstPad *srcPad = gst_element_get_static_pad(m_videoIdentity, "src");
+
+ if (!gst_pad_is_blocked(srcPad)) {
+ //pad is not blocked, it's possible to swap outputs only in the null state
+ qWarning() << "Pad is not blocked yet, could not switch video sink";
+ GstState identityElementState = GST_STATE_NULL;
+ gst_element_get_state(m_videoIdentity, &identityElementState, NULL, GST_CLOCK_TIME_NONE);
+ if (identityElementState != GST_STATE_NULL) {
+ gst_object_unref(GST_OBJECT(srcPad));
+ return; //can't change vo yet, received async call from the previous change
+ }
+ }
+
+ if (m_pendingVideoSink == m_videoSink) {
+ //video output was change back to the current one,
+ //no need to torment the pipeline, just unblock the pad
+ if (gst_pad_is_blocked(srcPad))
+ gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0);
+
+ m_pendingVideoSink = 0;
+ gst_object_unref(GST_OBJECT(srcPad));
+ return;
+ }
+
+ if (m_usingColorspaceElement) {
+ gst_element_set_state(m_colorSpace, GST_STATE_NULL);
+ gst_element_set_state(m_videoSink, GST_STATE_NULL);
+
+ gst_element_unlink(m_colorSpace, m_videoSink);
+ gst_bin_remove(GST_BIN(m_videoOutputBin), m_colorSpace);
+ } else {
+ gst_element_set_state(m_videoSink, GST_STATE_NULL);
+ gst_element_unlink(m_videoIdentity, m_videoSink);
+ }
+
+ gst_bin_remove(GST_BIN(m_videoOutputBin), m_videoSink);
+
+ m_videoSink = m_pendingVideoSink;
+ m_pendingVideoSink = 0;
+
+ gst_bin_add(GST_BIN(m_videoOutputBin), m_videoSink);
+
+ m_usingColorspaceElement = false;
+ bool linked = gst_element_link(m_videoIdentity, m_videoSink);
+ if (!linked) {
+ m_usingColorspaceElement = true;
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "Failed to connect video output, inserting the colorspace element.";
+#endif
+ gst_bin_add(GST_BIN(m_videoOutputBin), m_colorSpace);
+ linked = gst_element_link_many(m_videoIdentity, m_colorSpace, m_videoSink, NULL);
+ }
+
+ if (!linked)
+ qWarning() << "Linking video output element failed";
+
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "notify the video connector it has to emit a new segment message...";
+#endif
+ //it's necessary to send a new segment event just before
+ //the first buffer pushed to the new sink
+ g_signal_emit_by_name(m_videoIdentity,
+ "resend-new-segment",
+ true //emit connection-failed signal
+ //to have a chance to insert colorspace element
+ );
+
+
+ GstState state;
+
+ switch (m_pendingState) {
+ case QMediaPlayer::StoppedState:
+ state = GST_STATE_NULL;
+ break;
+ case QMediaPlayer::PausedState:
+ state = GST_STATE_PAUSED;
+ break;
+ case QMediaPlayer::PlayingState:
+ state = GST_STATE_PLAYING;
+ break;
+ }
+
+ if (m_usingColorspaceElement)
+ gst_element_set_state(m_colorSpace, state);
+
+ gst_element_set_state(m_videoSink, state);
+
+ // Set state change that was deferred due the video output
+ // change being pending
+ gst_element_set_state(m_playbin, state);
+
+ //don't have to wait here, it will unblock eventually
+ if (gst_pad_is_blocked(srcPad))
+ gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0);
+ gst_object_unref(GST_OBJECT(srcPad));
+
+#ifdef DEBUG_VO_BIN_DUMP
+ _gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin),
+ GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES*/),
+ "playbin_finish");
+#endif
+}
+
+void QGstreamerPlayerSession::insertColorSpaceElement(GstElement *element, gpointer data)
+{
+ Q_UNUSED(element);
+ QGstreamerPlayerSession* session = reinterpret_cast<QGstreamerPlayerSession*>(data);
+
+ if (session->m_usingColorspaceElement)
+ return;
+ session->m_usingColorspaceElement = true;
+
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "Failed to connect video output, inserting the colorspace elemnt.";
+ qDebug() << "notify the video connector it has to emit a new segment message...";
+#endif
+ //it's necessary to send a new segment event just before
+ //the first buffer pushed to the new sink
+ g_signal_emit_by_name(session->m_videoIdentity,
+ "resend-new-segment",
+ false // don't emit connection-failed signal
+ );
+
+ gst_element_unlink(session->m_videoIdentity, session->m_videoSink);
+ gst_bin_add(GST_BIN(session->m_videoOutputBin), session->m_colorSpace);
+ gst_element_link_many(session->m_videoIdentity, session->m_colorSpace, session->m_videoSink, NULL);
+
+ GstState state;
+
+ switch (session->m_pendingState) {
+ case QMediaPlayer::StoppedState:
+ state = GST_STATE_NULL;
+ break;
+ case QMediaPlayer::PausedState:
+ state = GST_STATE_PAUSED;
+ break;
+ case QMediaPlayer::PlayingState:
+ state = GST_STATE_PLAYING;
+ break;
+ }
+
+ gst_element_set_state(session->m_colorSpace, state);
+}
+
+
+bool QGstreamerPlayerSession::isVideoAvailable() const
+{
+ return m_videoAvailable;
+}
+
+bool QGstreamerPlayerSession::isSeekable() const
+{
+ return m_seekable;
+}
+
+bool QGstreamerPlayerSession::play()
+{
+ m_everPlayed = false;
+ if (m_playbin) {
+ m_pendingState = QMediaPlayer::PlayingState;
+ if (gst_element_set_state(m_playbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
+ qWarning() << "GStreamer; Unable to play -" << m_request.url().toString();
+ m_pendingState = m_state = QMediaPlayer::StoppedState;
+
+ emit stateChanged(m_state);
+ } else
+ return true;
+ }
+
+ return false;
+}
+
+bool QGstreamerPlayerSession::pause()
+{
+ if (m_playbin) {
+ m_pendingState = QMediaPlayer::PausedState;
+ if (m_pendingVideoSink != 0)
+ return true;
+
+ if (gst_element_set_state(m_playbin, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
+ qWarning() << "GStreamer; Unable to pause -" << m_request.url().toString();
+ m_pendingState = m_state = QMediaPlayer::StoppedState;
+
+ emit stateChanged(m_state);
+ } else {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void QGstreamerPlayerSession::stop()
+{
+ m_everPlayed = false;
+ if (m_playbin) {
+ if (m_renderer)
+ m_renderer->stopRenderer();
+
+ gst_element_set_state(m_playbin, GST_STATE_NULL);
+
+ m_lastPosition = 0;
+ QMediaPlayer::State oldState = m_state;
+ m_pendingState = m_state = QMediaPlayer::StoppedState;
+
+ finishVideoOutputChange();
+
+ //we have to do it here, since gstreamer will not emit bus messages any more
+ setSeekable(false);
+ if (oldState != m_state)
+ emit stateChanged(m_state);
+ }
+}
+
+bool QGstreamerPlayerSession::seek(qint64 ms)
+{
+ //seek locks when the video output sink is changing and pad is blocked
+ if (m_playbin && !m_pendingVideoSink && m_state != QMediaPlayer::StoppedState) {
+ ms = qMax(ms,qint64(0));
+ gint64 position = ms * 1000000;
+ bool isSeeking = gst_element_seek(m_playbin,
+ m_playbackRate,
+ GST_FORMAT_TIME,
+ GstSeekFlags(GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH),
+ GST_SEEK_TYPE_SET,
+ position,
+ GST_SEEK_TYPE_NONE,
+ 0);
+ if (isSeeking)
+ m_lastPosition = ms;
+
+ return isSeeking;
+ }
+
+ return false;
+}
+
+void QGstreamerPlayerSession::setVolume(int volume)
+{
+ if (m_volume != volume) {
+ m_volume = volume;
+
+ if (m_playbin) {
+ //playbin2 allows to set volume and muted independently,
+ //with playbin1 it's necessary to keep volume at 0 while muted
+ if (!m_muted || m_usePlaybin2)
+ g_object_set(G_OBJECT(m_playbin), "volume", m_volume/100.0, NULL);
+ }
+
+ emit volumeChanged(m_volume);
+ }
+}
+
+void QGstreamerPlayerSession::setMuted(bool muted)
+{
+ if (m_muted != muted) {
+ m_muted = muted;
+
+ if (m_usePlaybin2)
+ g_object_set(G_OBJECT(m_playbin), "mute", m_muted, NULL);
+ else
+ g_object_set(G_OBJECT(m_playbin), "volume", (m_muted ? 0 : m_volume/100.0), NULL);
+
+ emit mutedStateChanged(m_muted);
+ }
+}
+
+
+void QGstreamerPlayerSession::setSeekable(bool seekable)
+{
+ if (seekable != m_seekable) {
+ m_seekable = seekable;
+ emit seekableChanged(m_seekable);
+ }
+}
+
+bool QGstreamerPlayerSession::processSyncMessage(const QGstreamerMessage &message)
+{
+ GstMessage* gm = message.rawMessage();
+
+ if (gm && GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) {
+ if (m_renderer) {
+ if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoSink))
+ m_renderer->handleSyncMessage(gm);
+
+ if (gst_structure_has_name(gm->structure, "prepare-xwindow-id")) {
+ m_renderer->precessNewStream();
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void QGstreamerPlayerSession::busMessage(const QGstreamerMessage &message)
+{
+ GstMessage* gm = message.rawMessage();
+
+ if (gm) {
+ //tag message comes from elements inside playbin, not from playbin itself
+ if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_TAG) {
+ //qDebug() << "tag message";
+ GstTagList *tag_list;
+ gst_message_parse_tag(gm, &tag_list);
+ m_tags.unite(QGstUtils::gstTagListToMap(tag_list));
+
+ //qDebug() << m_tags;
+
+ emit tagsChanged();
+ } else if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_DURATION) {
+ updateDuration();
+ }
+
+#ifdef DEBUG_PLAYBIN
+ if (m_sourceType == MMSSrc && qstrcmp(GST_OBJECT_NAME(GST_MESSAGE_SRC(gm)), "source") == 0) {
+ qDebug() << "Message from MMSSrc: " << GST_MESSAGE_TYPE(gm);
+ }
+#endif
+
+ if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_BUFFERING) {
+ int progress = 0;
+ gst_message_parse_buffering(gm, &progress);
+ emit bufferingProgressChanged(progress);
+ }
+
+ bool handlePlaybin2 = false;
+ if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_playbin)) {
+ switch (GST_MESSAGE_TYPE(gm)) {
+ case GST_MESSAGE_STATE_CHANGED:
+ {
+ GstState oldState;
+ GstState newState;
+ GstState pending;
+
+ gst_message_parse_state_changed(gm, &oldState, &newState, &pending);
+
+#ifdef DEBUG_PLAYBIN
+ QStringList states;
+ states << "GST_STATE_VOID_PENDING" << "GST_STATE_NULL" << "GST_STATE_READY" << "GST_STATE_PAUSED" << "GST_STATE_PLAYING";
+
+ qDebug() << QString("state changed: old: %1 new: %2 pending: %3") \
+ .arg(states[oldState]) \
+ .arg(states[newState]) \
+ .arg(states[pending]);
+#endif
+
+ switch (newState) {
+ case GST_STATE_VOID_PENDING:
+ case GST_STATE_NULL:
+ setSeekable(false);
+ finishVideoOutputChange();
+ if (m_state != QMediaPlayer::StoppedState)
+ emit stateChanged(m_state = QMediaPlayer::StoppedState);
+ break;
+ case GST_STATE_READY:
+ setSeekable(false);
+ if (m_state != QMediaPlayer::StoppedState)
+ emit stateChanged(m_state = QMediaPlayer::StoppedState);
+ break;
+ case GST_STATE_PAUSED:
+ {
+ QMediaPlayer::State prevState = m_state;
+ m_state = QMediaPlayer::PausedState;
+
+ //check for seekable
+ if (oldState == GST_STATE_READY) {
+ if (m_sourceType == SoupHTTPSrc || m_sourceType == MMSSrc) {
+ //since udpsrc is a live source, it is not applicable here
+ m_everPlayed = true;
+ }
+
+ getStreamsInfo();
+ updateVideoResolutionTag();
+
+ //gstreamer doesn't give a reliable indication the duration
+ //information is ready, GST_MESSAGE_DURATION is not sent by most elements
+ //the duration is queried up to 5 times with increasing delay
+ m_durationQueries = 5;
+ updateDuration();
+
+ /*
+ //gst_element_seek_simple doesn't work reliably here, have to find a better solution
+
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 position = 0;
+ bool seekable = false;
+ if (gst_element_query_position(m_playbin, &format, &position)) {
+ seekable = gst_element_seek_simple(m_playbin, format, GST_SEEK_FLAG_NONE, position);
+ }
+
+ setSeekable(seekable);
+ */
+
+ setSeekable(true);
+
+ if (!qFuzzyCompare(m_playbackRate, qreal(1.0))) {
+ qreal rate = m_playbackRate;
+ m_playbackRate = 1.0;
+ setPlaybackRate(rate);
+ }
+ }
+
+ if (m_state != prevState)
+ emit stateChanged(m_state);
+
+ break;
+ }
+ case GST_STATE_PLAYING:
+ m_everPlayed = true;
+ if (m_state != QMediaPlayer::PlayingState)
+ emit stateChanged(m_state = QMediaPlayer::PlayingState);
+
+ break;
+ }
+ }
+ break;
+
+ case GST_MESSAGE_EOS:
+ emit playbackFinished();
+ break;
+
+ case GST_MESSAGE_TAG:
+ case GST_MESSAGE_STREAM_STATUS:
+ case GST_MESSAGE_UNKNOWN:
+ break;
+ case GST_MESSAGE_ERROR: {
+ GError *err;
+ gchar *debug;
+ gst_message_parse_error(gm, &err, &debug);
+ if (err->domain == GST_STREAM_ERROR && err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND)
+ processInvalidMedia(QMediaPlayer::FormatError, tr("Cannot play stream of type: <unknown>"));
+ else
+ processInvalidMedia(QMediaPlayer::ResourceError, QString::fromUtf8(err->message));
+ qWarning() << "Error:" << QString::fromUtf8(err->message);
+ g_error_free(err);
+ g_free(debug);
+ }
+ break;
+ case GST_MESSAGE_WARNING:
+ {
+ GError *err;
+ gchar *debug;
+ gst_message_parse_warning (gm, &err, &debug);
+ qWarning() << "Warning:" << QString::fromUtf8(err->message);
+ g_error_free (err);
+ g_free (debug);
+ }
+ break;
+ case GST_MESSAGE_INFO:
+#ifdef DEBUG_PLAYBIN
+ {
+ GError *err;
+ gchar *debug;
+ gst_message_parse_info (gm, &err, &debug);
+ qDebug() << "Info:" << QString::fromUtf8(err->message);
+ g_error_free (err);
+ g_free (debug);
+ }
+#endif
+ break;
+ case GST_MESSAGE_BUFFERING:
+ case GST_MESSAGE_STATE_DIRTY:
+ case GST_MESSAGE_STEP_DONE:
+ case GST_MESSAGE_CLOCK_PROVIDE:
+ case GST_MESSAGE_CLOCK_LOST:
+ case GST_MESSAGE_NEW_CLOCK:
+ case GST_MESSAGE_STRUCTURE_CHANGE:
+ case GST_MESSAGE_APPLICATION:
+ case GST_MESSAGE_ELEMENT:
+ break;
+ case GST_MESSAGE_SEGMENT_START:
+ {
+ const GstStructure *structure = gst_message_get_structure(gm);
+ qint64 position = g_value_get_int64(gst_structure_get_value(structure, "position"));
+ position /= 1000000;
+ m_lastPosition = position;
+ emit positionChanged(position);
+ }
+ break;
+ case GST_MESSAGE_SEGMENT_DONE:
+ break;
+ case GST_MESSAGE_LATENCY:
+#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 13)
+ case GST_MESSAGE_ASYNC_START:
+ break;
+ case GST_MESSAGE_ASYNC_DONE:
+ {
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 position = 0;
+ if (gst_element_query_position(m_playbin, &format, &position)) {
+ position /= 1000000;
+ m_lastPosition = position;
+ emit positionChanged(position);
+ }
+ break;
+ }
+#if GST_VERSION_MICRO >= 23
+ case GST_MESSAGE_REQUEST_STATE:
+#endif
+#endif
+ case GST_MESSAGE_ANY:
+ break;
+ default:
+ break;
+ }
+ } else if (m_videoSink
+ && m_renderer
+ && GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_videoSink)) {
+
+ m_renderer->handleBusMessage(gm);
+ if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED) {
+ GstState oldState;
+ GstState newState;
+ gst_message_parse_state_changed(gm, &oldState, &newState, 0);
+
+ if (oldState == GST_STATE_READY && newState == GST_STATE_PAUSED)
+ m_renderer->precessNewStream();
+ }
+ } else if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ERROR) {
+ GError *err;
+ gchar *debug;
+ gst_message_parse_error(gm, &err, &debug);
+ // If the source has given up, so do we.
+ if (qstrcmp(GST_OBJECT_NAME(GST_MESSAGE_SRC(gm)), "source") == 0) {
+ bool everPlayed = m_everPlayed;
+ // Try and differentiate network related resource errors from the others
+ if (!m_request.url().isRelative() && m_request.url().scheme().compare(QLatin1String("file"), Qt::CaseInsensitive) != 0 ) {
+ if (everPlayed ||
+ (err->domain == GST_RESOURCE_ERROR && (
+ err->code == GST_RESOURCE_ERROR_BUSY ||
+ err->code == GST_RESOURCE_ERROR_OPEN_READ ||
+ err->code == GST_RESOURCE_ERROR_READ ||
+ err->code == GST_RESOURCE_ERROR_SEEK ||
+ err->code == GST_RESOURCE_ERROR_SYNC))) {
+ processInvalidMedia(QMediaPlayer::NetworkError, QString::fromUtf8(err->message));
+ } else {
+ processInvalidMedia(QMediaPlayer::ResourceError, QString::fromUtf8(err->message));
+ }
+ }
+ else
+ processInvalidMedia(QMediaPlayer::ResourceError, QString::fromUtf8(err->message));
+ } else if (err->domain == GST_STREAM_ERROR
+ && (err->code == GST_STREAM_ERROR_DECRYPT || err->code == GST_STREAM_ERROR_DECRYPT_NOKEY)) {
+ processInvalidMedia(QMediaPlayer::AccessDeniedError, QString::fromUtf8(err->message));
+ } else {
+ handlePlaybin2 = m_usePlaybin2;
+ }
+ if (!handlePlaybin2)
+ qWarning() << "Error:" << QString::fromUtf8(err->message);
+ g_error_free(err);
+ g_free(debug);
+ } else if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT
+ && qstrcmp(GST_OBJECT_NAME(GST_MESSAGE_SRC(gm)), "source") == 0
+ && m_sourceType == UDPSrc
+ && gst_structure_has_name(gst_message_get_structure(gm), "GstUDPSrcTimeout")) {
+ //since udpsrc will not generate an error for the timeout event,
+ //we need to process its element message here and treat it as an error.
+ processInvalidMedia(m_everPlayed ? QMediaPlayer::NetworkError : QMediaPlayer::ResourceError,
+ tr("UDP source timeout"));
+ } else {
+ handlePlaybin2 = m_usePlaybin2;
+ }
+
+ if (handlePlaybin2) {
+ if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_WARNING) {
+ GError *err;
+ gchar *debug;
+ gst_message_parse_warning(gm, &err, &debug);
+ if (err->domain == GST_STREAM_ERROR && err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND)
+ emit error(int(QMediaPlayer::FormatError), tr("Cannot play stream of type: <unknown>"));
+ qWarning() << "Warning:" << QString::fromUtf8(err->message);
+ g_error_free(err);
+ g_free(debug);
+ } else if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ERROR) {
+ GError *err;
+ gchar *debug;
+ gst_message_parse_error(gm, &err, &debug);
+ if (qstrncmp(GST_OBJECT_NAME(GST_MESSAGE_SRC(gm)), "decodebin2", 10) == 0
+ || qstrncmp(GST_OBJECT_NAME(GST_MESSAGE_SRC(gm)), "uridecodebin", 12) == 0) {
+ processInvalidMedia(QMediaPlayer::ResourceError, QString::fromUtf8(err->message));
+ } else if (err->domain == GST_STREAM_ERROR
+ && (err->code == GST_STREAM_ERROR_DECRYPT || err->code == GST_STREAM_ERROR_DECRYPT_NOKEY)) {
+ processInvalidMedia(QMediaPlayer::AccessDeniedError, QString::fromUtf8(err->message));
+ }
+ qWarning() << "Error:" << QString::fromUtf8(err->message);
+ g_error_free(err);
+ g_free(debug);
+ }
+ }
+ }
+}
+
+void QGstreamerPlayerSession::getStreamsInfo()
+{
+ //check if video is available:
+ bool haveAudio = false;
+ bool haveVideo = false;
+ m_streamProperties.clear();
+ m_streamTypes.clear();
+
+ if (m_usePlaybin2) {
+ gint audioStreamsCount = 0;
+ gint videoStreamsCount = 0;
+ gint textStreamsCount = 0;
+
+ g_object_get(G_OBJECT(m_playbin), "n-audio", &audioStreamsCount, NULL);
+ g_object_get(G_OBJECT(m_playbin), "n-video", &videoStreamsCount, NULL);
+ g_object_get(G_OBJECT(m_playbin), "n-text", &textStreamsCount, NULL);
+
+ haveAudio = audioStreamsCount > 0;
+ haveVideo = videoStreamsCount > 0;
+
+ m_playbin2StreamOffset[QMediaStreamsControl::AudioStream] = 0;
+ m_playbin2StreamOffset[QMediaStreamsControl::VideoStream] = audioStreamsCount;
+ m_playbin2StreamOffset[QMediaStreamsControl::SubPictureStream] = audioStreamsCount+videoStreamsCount;
+
+ for (int i=0; i<audioStreamsCount; i++)
+ m_streamTypes.append(QMediaStreamsControl::AudioStream);
+
+ for (int i=0; i<videoStreamsCount; i++)
+ m_streamTypes.append(QMediaStreamsControl::VideoStream);
+
+ for (int i=0; i<textStreamsCount; i++)
+ m_streamTypes.append(QMediaStreamsControl::SubPictureStream);
+
+ for (int i=0; i<m_streamTypes.count(); i++) {
+ QMediaStreamsControl::StreamType streamType = m_streamTypes[i];
+ QMap<QtMultimediaKit::MetaData, QVariant> streamProperties;
+
+ int streamIndex = i - m_playbin2StreamOffset[streamType];
+
+ GstTagList *tags = 0;
+ switch (streamType) {
+ case QMediaStreamsControl::AudioStream:
+ g_signal_emit_by_name(G_OBJECT(m_playbin), "get-audio-tags", streamIndex, &tags);
+ break;
+ case QMediaStreamsControl::VideoStream:
+ g_signal_emit_by_name(G_OBJECT(m_playbin), "get-video-tags", streamIndex, &tags);
+ break;
+ case QMediaStreamsControl::SubPictureStream:
+ g_signal_emit_by_name(G_OBJECT(m_playbin), "get-text-tags", streamIndex, &tags);
+ break;
+ default:
+ break;
+ }
+
+ if (tags && gst_is_tag_list(tags)) {
+ gchar *languageCode = 0;
+ if (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &languageCode))
+ streamProperties[QtMultimediaKit::Language] = QString::fromUtf8(languageCode);
+
+ //qDebug() << "language for setream" << i << QString::fromUtf8(languageCode);
+ g_free (languageCode);
+ }
+
+ m_streamProperties.append(streamProperties);
+ }
+ } else { // PlayBin 1
+ enum {
+ GST_STREAM_TYPE_UNKNOWN,
+ GST_STREAM_TYPE_AUDIO,
+ GST_STREAM_TYPE_VIDEO,
+ GST_STREAM_TYPE_TEXT,
+ GST_STREAM_TYPE_SUBPICTURE,
+ GST_STREAM_TYPE_ELEMENT
+ };
+
+ GList* streamInfoList;
+ g_object_get(G_OBJECT(m_playbin), "stream-info", &streamInfoList, NULL);
+
+ for (; streamInfoList != 0; streamInfoList = g_list_next(streamInfoList)) {
+ gint type;
+ gchar *languageCode = 0;
+
+ GObject* streamInfo = G_OBJECT(streamInfoList->data);
+
+ g_object_get(streamInfo, "type", &type, NULL);
+ g_object_get(streamInfo, "language-code", &languageCode, NULL);
+
+ QMediaStreamsControl::StreamType streamType = QMediaStreamsControl::UnknownStream;
+
+ switch (type) {
+ case GST_STREAM_TYPE_VIDEO:
+ streamType = QMediaStreamsControl::VideoStream;
+ haveVideo = true;
+ break;
+ case GST_STREAM_TYPE_AUDIO:
+ streamType = QMediaStreamsControl::AudioStream;
+ haveAudio = true;
+ break;
+ case GST_STREAM_TYPE_SUBPICTURE:
+ streamType = QMediaStreamsControl::SubPictureStream;
+ break;
+ case GST_STREAM_TYPE_UNKNOWN: {
+ GstCaps *caps = 0;
+ g_object_get(streamInfo, "caps", &caps, NULL);
+ const GstStructure *structure = gst_caps_get_structure(caps, 0);
+ const gchar *media_type = gst_structure_get_name(structure);
+ emit error(int(QMediaPlayer::FormatError), QString::fromLatin1("Cannot play stream of type: %1").arg(QString::fromUtf8(media_type)));
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "Encountered unknown stream type";
+#endif
+ gst_caps_unref(caps);
+ }
+ default:
+ streamType = QMediaStreamsControl::UnknownStream;
+ break;
+ }
+
+ QMap<QtMultimediaKit::MetaData, QVariant> streamProperties;
+ streamProperties[QtMultimediaKit::Language] = QString::fromUtf8(languageCode);
+
+ m_streamProperties.append(streamProperties);
+ m_streamTypes.append(streamType);
+ }
+ }
+
+
+ if (haveAudio != m_audioAvailable) {
+ m_audioAvailable = haveAudio;
+ emit audioAvailableChanged(m_audioAvailable);
+ }
+ if (haveVideo != m_videoAvailable) {
+ m_videoAvailable = haveVideo;
+ emit videoAvailableChanged(m_videoAvailable);
+ }
+
+ emit streamsChanged();
+}
+
+void QGstreamerPlayerSession::updateVideoResolutionTag()
+{
+ QSize size;
+ QSize aspectRatio;
+
+ GstPad *pad = gst_element_get_static_pad(m_videoIdentity, "src");
+ GstCaps *caps = gst_pad_get_negotiated_caps(pad);
+
+ if (caps) {
+ const GstStructure *structure = gst_caps_get_structure(caps, 0);
+ gst_structure_get_int(structure, "width", &size.rwidth());
+ gst_structure_get_int(structure, "height", &size.rheight());
+
+ gint aspectNum = 0;
+ gint aspectDenum = 0;
+ if (!size.isEmpty() && gst_structure_get_fraction(
+ structure, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) {
+ if (aspectDenum > 0)
+ aspectRatio = QSize(aspectNum, aspectDenum);
+ }
+ gst_caps_unref(caps);
+ }
+
+ gst_object_unref(GST_OBJECT(pad));
+
+ QSize currentSize = m_tags.value("resolution").toSize();
+ QSize currentAspectRatio = m_tags.value("pixel-aspect-ratio").toSize();
+
+ if (currentSize != size || currentAspectRatio != aspectRatio) {
+ if (aspectRatio.isEmpty())
+ m_tags.remove("pixel-aspect-ratio");
+
+ if (size.isEmpty()) {
+ m_tags.remove("resolution");
+ } else {
+ m_tags.insert("resolution", QVariant(size));
+ if (!aspectRatio.isEmpty())
+ m_tags.insert("pixel-aspect-ratio", QVariant(aspectRatio));
+ }
+
+ emit tagsChanged();
+ }
+}
+
+void QGstreamerPlayerSession::updateDuration()
+{
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 gstDuration = 0;
+ int duration = -1;
+
+ if (m_playbin && gst_element_query_duration(m_playbin, &format, &gstDuration))
+ duration = gstDuration / 1000000;
+
+ if (m_duration != duration) {
+ m_duration = duration;
+ emit durationChanged(m_duration);
+ }
+
+ if (m_duration > 0)
+ m_durationQueries = 0;
+
+ if (m_durationQueries > 0) {
+ //increase delay between duration requests
+ int delay = 25 << (5 - m_durationQueries);
+ QTimer::singleShot(delay, this, SLOT(updateDuration()));
+ m_durationQueries--;
+ }
+}
+
+void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpointer d)
+{
+ Q_UNUSED(p);
+
+ GstElement *source = 0;
+ g_object_get(o, "source", &source, NULL);
+ if (source == 0)
+ return;
+
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "Playbin source added:" << G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source));
+#endif
+
+ // Turn off icecast metadata request, will be re-set if in QNetworkRequest
+ // (souphttpsrc docs say is false by default, but header appears in request
+ // @version 0.10.21)
+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "iradio-mode") != 0)
+ g_object_set(G_OBJECT(source), "iradio-mode", FALSE, NULL);
+
+
+ // Set Headers
+ const QByteArray userAgentString("User-Agent");
+
+ QGstreamerPlayerSession *self = reinterpret_cast<QGstreamerPlayerSession *>(d);
+
+ // User-Agent - special case, souphhtpsrc will always set something, even if
+ // defined in extra-headers
+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "user-agent") != 0) {
+ g_object_set(G_OBJECT(source), "user-agent",
+ self->m_request.rawHeader(userAgentString).constData(), NULL);
+ }
+
+ // The rest
+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "extra-headers") != 0) {
+ GstStructure *extras = gst_structure_empty_new("extras");
+
+ foreach (const QByteArray &rawHeader, self->m_request.rawHeaderList()) {
+ if (rawHeader == userAgentString) // Filter User-Agent
+ continue;
+ else {
+ GValue headerValue;
+
+ memset(&headerValue, 0, sizeof(GValue));
+ g_value_init(&headerValue, G_TYPE_STRING);
+
+ g_value_set_string(&headerValue,
+ self->m_request.rawHeader(rawHeader).constData());
+
+ gst_structure_set_value(extras, rawHeader.constData(), &headerValue);
+ }
+ }
+
+ if (gst_structure_n_fields(extras) > 0)
+ g_object_set(G_OBJECT(source), "extra-headers", extras, NULL);
+
+ gst_structure_free(extras);
+ }
+
+ //set timeout property to 5 seconds
+ if (qstrcmp(G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source)), "GstUDPSrc") == 0) {
+ //udpsrc timeout unit = microsecond
+ g_object_set(G_OBJECT(source), "timeout", G_GUINT64_CONSTANT(5000000), NULL);
+ self->m_sourceType = UDPSrc;
+ } else if (qstrcmp(G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source)), "GstSoupHTTPSrc") == 0) {
+ //souphttpsrc timeout unit = second
+ g_object_set(G_OBJECT(source), "timeout", guint(5), NULL);
+ self->m_sourceType = SoupHTTPSrc;
+ } else if (qstrcmp(G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source)), "GstMMSSrc") == 0) {
+ self->m_sourceType = MMSSrc;
+ g_object_set(G_OBJECT(source), "tcp-timeout", G_GUINT64_CONSTANT(5000000), NULL);
+ } else {
+ self->m_sourceType = UnknownSrc;
+ }
+
+ gst_object_unref(source);
+}
+
+void QGstreamerPlayerSession::handleVolumeChange(GObject *o, GParamSpec *p, gpointer d)
+{
+ Q_UNUSED(o);
+ Q_UNUSED(p);
+ QGstreamerPlayerSession *session = reinterpret_cast<QGstreamerPlayerSession *>(d);
+ QMetaObject::invokeMethod(session, "updateVolume", Qt::QueuedConnection);
+}
+
+void QGstreamerPlayerSession::updateVolume()
+{
+ double volume = 1.0;
+ g_object_get(m_playbin, "volume", &volume, NULL);
+
+ //special case for playbin1 volume changes in muted state
+ //playbin1 has no separate muted state,
+ //it's emulated with volume value saved and set to 0
+ //this change should not be reported to user
+ if (!m_usePlaybin2 && m_muted) {
+ if (volume > 0.001) {
+ //volume is changed, player in not muted any more
+ m_muted = false;
+ emit mutedStateChanged(m_muted = false);
+ } else {
+ //don't emit volume changed to 0 when player is muted
+ return;
+ }
+ }
+
+ if (m_volume != int(volume*100)) {
+ m_volume = int(volume*100);
+#ifdef DEBUG_PLAYBIN
+ qDebug() << Q_FUNC_INFO << m_muted;
+#endif
+ emit volumeChanged(m_volume);
+ }
+}
+
+void QGstreamerPlayerSession::handleMutedChange(GObject *o, GParamSpec *p, gpointer d)
+{
+ Q_UNUSED(o);
+ Q_UNUSED(p);
+ QGstreamerPlayerSession *session = reinterpret_cast<QGstreamerPlayerSession *>(d);
+ QMetaObject::invokeMethod(session, "updateMuted", Qt::QueuedConnection);
+}
+
+void QGstreamerPlayerSession::updateMuted()
+{
+ gboolean muted = false;
+ g_object_get(G_OBJECT(m_playbin), "mute", &muted, NULL);
+ if (m_muted != muted) {
+ m_muted = muted;
+#ifdef DEBUG_PLAYBIN
+ qDebug() << Q_FUNC_INFO << m_muted;
+#endif
+ emit mutedStateChanged(muted);
+ }
+}
+
+
+void QGstreamerPlayerSession::handleElementAdded(GstBin *bin, GstElement *element, QGstreamerPlayerSession *session)
+{
+ Q_UNUSED(bin);
+ //we have to configure queue2 element to enable media downloading
+ //and reporting available ranges,
+ //but it's added dynamically to playbin2
+
+ gchar *elementName = gst_element_get_name(element);
+
+ if (g_str_has_prefix(elementName, "queue2")) {
+ session->m_haveQueueElement = true;
+
+ if (session->property("mediaDownloadEnabled").toBool()) {
+ QDir cacheDir(QDesktopServices::storageLocation(QDesktopServices::CacheLocation));
+ QString cacheLocation = cacheDir.absoluteFilePath("gstmedia__XXXXXX");
+#ifdef DEBUG_PLAYBIN
+ qDebug() << "set queue2 temp-location" << cacheLocation;
+#endif
+ g_object_set(G_OBJECT(element), "temp-template", cacheLocation.toUtf8().constData(), NULL);
+ } else {
+ g_object_set(G_OBJECT(element), "temp-template", NULL, NULL);
+ }
+ } else if (g_str_has_prefix(elementName, "uridecodebin") ||
+ g_str_has_prefix(elementName, "decodebin2")) {
+ //listen for queue2 element added to uridecodebin/decodebin2 as well.
+ //Don't touch other bins since they may have unrelated queues
+ g_signal_connect(element, "element-added",
+ G_CALLBACK(handleElementAdded), session);
+ }
+
+ g_free(elementName);
+}
+
+//doing proper operations when detecting an invalidMedia: change media status before signal the erorr
+void QGstreamerPlayerSession::processInvalidMedia(QMediaPlayer::Error errorCode, const QString& errorString)
+{
+ emit invalidMedia();
+ stop();
+ emit error(int(errorCode), errorString);
+}
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h
new file mode 100644
index 000000000..e6fa996b0
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERPLAYERSESSION_H
+#define QGSTREAMERPLAYERSESSION_H
+
+#include <QObject>
+#include <QtNetwork/qnetworkrequest.h>
+#include "qgstreamerplayercontrol.h"
+#include "qgstreamerbushelper.h"
+#include <qmediaplayer.h>
+#include <qmediastreamscontrol.h>
+
+#if defined(HAVE_GST_APPSRC)
+#include "qgstappsrc.h"
+#endif
+
+#include <gst/gst.h>
+
+class QGstreamerBusHelper;
+class QGstreamerMessage;
+
+class QGstreamerVideoRendererInterface;
+
+QT_USE_NAMESPACE
+
+class QGstreamerPlayerSession : public QObject, public QGstreamerSyncEventFilter
+{
+Q_OBJECT
+
+public:
+ QGstreamerPlayerSession(QObject *parent);
+ virtual ~QGstreamerPlayerSession();
+
+ QNetworkRequest request() const;
+
+ QMediaPlayer::State state() const { return m_state; }
+ QMediaPlayer::State pendingState() const { return m_pendingState; }
+
+ qint64 duration() const;
+ qint64 position() const;
+
+ bool isBuffering() const;
+
+ int bufferingProgress() const;
+
+ int volume() const;
+ bool isMuted() const;
+
+ bool isAudioAvailable() const;
+
+ void setVideoRenderer(QObject *renderer);
+ bool isVideoAvailable() const;
+
+ bool isSeekable() const;
+
+ qreal playbackRate() const;
+ void setPlaybackRate(qreal rate);
+
+ QMediaTimeRange availablePlaybackRanges() const;
+
+ QMap<QByteArray ,QVariant> tags() const { return m_tags; }
+ QMap<QtMultimediaKit::MetaData,QVariant> streamProperties(int streamNumber) const { return m_streamProperties[streamNumber]; }
+ int streamCount() const { return m_streamProperties.count(); }
+ QMediaStreamsControl::StreamType streamType(int streamNumber) { return m_streamTypes.value(streamNumber, QMediaStreamsControl::UnknownStream); }
+
+ int activeStream(QMediaStreamsControl::StreamType streamType) const;
+ void setActiveStream(QMediaStreamsControl::StreamType streamType, int streamNumber);
+
+ bool processSyncMessage(const QGstreamerMessage &message);
+
+#if defined(HAVE_GST_APPSRC)
+ QGstAppSrc *appsrc() const { return m_appSrc; }
+ static void configureAppSrcElement(GObject*, GObject*, GParamSpec*,QGstreamerPlayerSession* _this);
+#endif
+
+public slots:
+ void loadFromUri(const QNetworkRequest &url);
+ void loadFromStream(const QNetworkRequest &url, QIODevice *stream);
+ bool play();
+ bool pause();
+ void stop();
+
+ bool seek(qint64 pos);
+
+ void setVolume(int volume);
+ void setMuted(bool muted);
+
+signals:
+ void durationChanged(qint64 duration);
+ void positionChanged(qint64 position);
+ void stateChanged(QMediaPlayer::State state);
+ void volumeChanged(int volume);
+ void mutedStateChanged(bool muted);
+ void audioAvailableChanged(bool audioAvailable);
+ void videoAvailableChanged(bool videoAvailable);
+ void bufferingChanged(bool buffering);
+ void bufferingProgressChanged(int percentFilled);
+ void playbackFinished();
+ void tagsChanged();
+ void streamsChanged();
+ void seekableChanged(bool);
+ void error(int error, const QString &errorString);
+ void invalidMedia();
+ void playbackRateChanged(qreal);
+
+private slots:
+ void busMessage(const QGstreamerMessage &message);
+ void getStreamsInfo();
+ void setSeekable(bool);
+ void finishVideoOutputChange();
+ void updateVideoRenderer();
+ void updateVideoResolutionTag();
+ void updateVolume();
+ void updateMuted();
+ void updateDuration();
+
+private:
+ static void playbinNotifySource(GObject *o, GParamSpec *p, gpointer d);
+ static void handleVolumeChange(GObject *o, GParamSpec *p, gpointer d);
+ static void handleMutedChange(GObject *o, GParamSpec *p, gpointer d);
+ static void insertColorSpaceElement(GstElement *element, gpointer data);
+ static void handleElementAdded(GstBin *bin, GstElement *element, QGstreamerPlayerSession *session);
+ void processInvalidMedia(QMediaPlayer::Error errorCode, const QString& errorString);
+
+ QNetworkRequest m_request;
+ QMediaPlayer::State m_state;
+ QMediaPlayer::State m_pendingState;
+ QGstreamerBusHelper* m_busHelper;
+ GstElement* m_playbin;
+ bool m_usePlaybin2;
+
+ GstElement* m_videoOutputBin;
+ GstElement* m_videoIdentity;
+ GstElement* m_colorSpace;
+ bool m_usingColorspaceElement;
+ GstElement* m_videoSink;
+ GstElement* m_pendingVideoSink;
+ GstElement* m_nullVideoSink;
+
+ GstBus* m_bus;
+ QObject *m_videoOutput;
+ QGstreamerVideoRendererInterface *m_renderer;
+
+ bool m_haveQueueElement;
+
+#if defined(HAVE_GST_APPSRC)
+ QGstAppSrc *m_appSrc;
+#endif
+
+ QMap<QByteArray, QVariant> m_tags;
+ QList< QMap<QtMultimediaKit::MetaData,QVariant> > m_streamProperties;
+ QList<QMediaStreamsControl::StreamType> m_streamTypes;
+ QMap<QMediaStreamsControl::StreamType, int> m_playbin2StreamOffset;
+
+
+ int m_volume;
+ qreal m_playbackRate;
+ bool m_muted;
+ bool m_audioAvailable;
+ bool m_videoAvailable;
+ bool m_seekable;
+
+ mutable qint64 m_lastPosition;
+ qint64 m_duration;
+ int m_durationQueries;
+
+ enum SourceType
+ {
+ UnknownSrc,
+ SoupHTTPSrc,
+ UDPSrc,
+ MMSSrc
+ };
+ SourceType m_sourceType;
+ bool m_everPlayed;
+};
+
+#endif // QGSTREAMERPLAYERSESSION_H
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp
new file mode 100644
index 000000000..0ab93022b
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamerstreamscontrol.h"
+#include "qgstreamerplayersession.h"
+
+QGstreamerStreamsControl::QGstreamerStreamsControl(QGstreamerPlayerSession *session, QObject *parent)
+ :QMediaStreamsControl(parent), m_session(session)
+{
+ connect(m_session, SIGNAL(streamsChanged()), SIGNAL(streamsChanged()));
+}
+
+QGstreamerStreamsControl::~QGstreamerStreamsControl()
+{
+}
+
+int QGstreamerStreamsControl::streamCount()
+{
+ return m_session->streamCount();
+}
+
+QMediaStreamsControl::StreamType QGstreamerStreamsControl::streamType(int streamNumber)
+{
+ return m_session->streamType(streamNumber);
+}
+
+QVariant QGstreamerStreamsControl::metaData(int streamNumber, QtMultimediaKit::MetaData key)
+{
+ return m_session->streamProperties(streamNumber).value(key);
+}
+
+bool QGstreamerStreamsControl::isActive(int streamNumber)
+{
+ return streamNumber != -1 && streamNumber == m_session->activeStream(streamType(streamNumber));
+}
+
+void QGstreamerStreamsControl::setActive(int streamNumber, bool state)
+{
+ QMediaStreamsControl::StreamType type = m_session->streamType(streamNumber);
+ if (type == QMediaStreamsControl::UnknownStream)
+ return;
+
+ if (state)
+ m_session->setActiveStream(type, streamNumber);
+ else {
+ //only one active stream of certain type is supported
+ if (m_session->activeStream(type) == streamNumber)
+ m_session->setActiveStream(type, -1);
+ }
+}
+
diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.h b/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.h
new file mode 100644
index 000000000..1213455b9
--- /dev/null
+++ b/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.h
@@ -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$
+** 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 QGSTREAMERSTREAMSCONTROL_H
+#define QGSTREAMERSTREAMSCONTROL_H
+
+#include <qmediastreamscontrol.h>
+
+QT_USE_NAMESPACE
+
+class QGstreamerPlayerSession;
+
+class QGstreamerStreamsControl : public QMediaStreamsControl
+{
+ Q_OBJECT
+public:
+ QGstreamerStreamsControl(QGstreamerPlayerSession *session, QObject *parent);
+ virtual ~QGstreamerStreamsControl();
+
+ virtual int streamCount();
+ virtual StreamType streamType(int streamNumber);
+
+ virtual QVariant metaData(int streamNumber, QtMultimediaKit::MetaData key);
+
+ virtual bool isActive(int streamNumber);
+ virtual void setActive(int streamNumber, bool state);
+
+private:
+ QGstreamerPlayerSession *m_session;
+};
+
+#endif // QGSTREAMERSTREAMSCONTROL_H
+
diff --git a/src/plugins/gstreamer/qabstractgstbufferpool.h b/src/plugins/gstreamer/qabstractgstbufferpool.h
new file mode 100644
index 000000000..8681dac71
--- /dev/null
+++ b/src/plugins/gstreamer/qabstractgstbufferpool.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTBUFFERPOOL_H
+#define QGSTBUFFERPOOL_H
+
+#include <qabstractvideobuffer.h>
+#include <qvideosurfaceformat.h>
+
+#include <gst/gst.h>
+
+/*!
+ Abstract interface for video buffers allocation.
+*/
+class QAbstractGstBufferPool
+{
+public:
+ virtual ~QAbstractGstBufferPool() {}
+
+ virtual bool isFormatSupported(const QVideoSurfaceFormat &format) const = 0;
+
+ virtual GType bufferType() const = 0;
+ virtual GstBuffer *takeBuffer(const QVideoSurfaceFormat &format, GstCaps *caps) = 0;
+ virtual void clear() = 0;
+
+ virtual QAbstractVideoBuffer::HandleType handleType() const = 0;
+
+ /*!
+ Build an QAbstractVideoBuffer instance from compatible (mathcing gst buffer type)
+ GstBuffer.
+
+ This method is called from gstreamer video sink thread.
+ */
+ virtual QAbstractVideoBuffer *prepareVideoBuffer(GstBuffer *buffer, int bytesPerLine) = 0;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/qgstreameraudioinputendpointselector.cpp b/src/plugins/gstreamer/qgstreameraudioinputendpointselector.cpp
new file mode 100644
index 000000000..606f06052
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreameraudioinputendpointselector.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qgstreameraudioinputendpointselector.h"
+
+#include <QtGui/QIcon>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+
+#include <gst/gst.h>
+
+#ifdef HAVE_ALSA
+#include <alsa/asoundlib.h>
+#endif
+
+QGstreamerAudioInputEndpointSelector::QGstreamerAudioInputEndpointSelector(QObject *parent)
+ :QAudioEndpointSelector(parent)
+{
+ update();
+}
+
+QGstreamerAudioInputEndpointSelector::~QGstreamerAudioInputEndpointSelector()
+{
+}
+
+QList<QString> QGstreamerAudioInputEndpointSelector::availableEndpoints() const
+{
+ return m_names;
+}
+
+QString QGstreamerAudioInputEndpointSelector::endpointDescription(const QString& name) const
+{
+ QString desc;
+
+ for (int i = 0; i < m_names.size(); i++) {
+ if (m_names.at(i).compare(name) == 0) {
+ desc = m_descriptions.at(i);
+ break;
+ }
+ }
+ return desc;
+}
+
+QString QGstreamerAudioInputEndpointSelector::defaultEndpoint() const
+{
+ if (m_names.size() > 0)
+ return m_names.at(0);
+
+ return QString();
+}
+
+QString QGstreamerAudioInputEndpointSelector::activeEndpoint() const
+{
+ return m_audioInput;
+}
+
+void QGstreamerAudioInputEndpointSelector::setActiveEndpoint(const QString& name)
+{
+ if (m_audioInput.compare(name) != 0) {
+ m_audioInput = name;
+ emit activeEndpointChanged(name);
+ }
+}
+
+void QGstreamerAudioInputEndpointSelector::update()
+{
+ m_names.clear();
+ m_descriptions.clear();
+#ifndef Q_WS_MAEMO_5
+ updateAlsaDevices();
+ updateOssDevices();
+#endif
+ updatePulseDevices();
+ if (m_names.size() > 0)
+ m_audioInput = m_names.at(0);
+}
+
+void QGstreamerAudioInputEndpointSelector::updateAlsaDevices()
+{
+#ifdef HAVE_ALSA
+ void **hints, **n;
+ if (snd_device_name_hint(-1, "pcm", &hints) < 0) {
+ qWarning()<<"no alsa devices available";
+ return;
+ }
+ n = hints;
+
+ while (*n != NULL) {
+ char *name = snd_device_name_get_hint(*n, "NAME");
+ char *descr = snd_device_name_get_hint(*n, "DESC");
+ char *io = snd_device_name_get_hint(*n, "IOID");
+
+ if ((name != NULL) && (descr != NULL)) {
+ if ( io == NULL || qstrcmp(io,"Input") == 0 ) {
+ m_names.append(QLatin1String("alsa:")+QString::fromUtf8(name));
+ m_descriptions.append(QString::fromUtf8(descr));
+ }
+ }
+
+ if (name != NULL)
+ free(name);
+ if (descr != NULL)
+ free(descr);
+ if (io != NULL)
+ free(io);
+ n++;
+ }
+ snd_device_name_free_hint(hints);
+#endif
+}
+
+void QGstreamerAudioInputEndpointSelector::updateOssDevices()
+{
+ QDir devDir("/dev");
+ devDir.setFilter(QDir::System);
+#ifndef QT_QWS_N810
+ QFileInfoList entries = devDir.entryInfoList(QStringList() << "dsp*");
+ foreach(const QFileInfo& entryInfo, entries) {
+ m_names.append(QLatin1String("oss:")+entryInfo.filePath());
+ m_descriptions.append(QString("OSS device %1").arg(entryInfo.fileName()));
+ }
+#else
+ m_names.append("dsppcm");
+ m_descriptions.append("PCM audio input");
+#endif
+}
+
+void QGstreamerAudioInputEndpointSelector::updatePulseDevices()
+{
+ GstElementFactory *factory = gst_element_factory_find("pulsesrc");
+ if (factory) {
+ m_names.append("pulseaudio:");
+ m_descriptions.append("PulseAudio device.");
+ gst_object_unref(GST_OBJECT(factory));
+ }
+}
diff --git a/src/plugins/gstreamer/qgstreameraudioinputendpointselector.h b/src/plugins/gstreamer/qgstreameraudioinputendpointselector.h
new file mode 100644
index 000000000..c9587fcb8
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreameraudioinputendpointselector.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERAUDIOINPUTENDPOINTSELECTOR_H
+#define QGSTREAMERAUDIOINPUTENDPOINTSELECTOR_H
+
+#include <qaudioendpointselector.h>
+#include <QtCore/qstringlist.h>
+
+QT_USE_NAMESPACE
+
+class QGstreamerAudioInputEndpointSelector : public QAudioEndpointSelector
+{
+Q_OBJECT
+public:
+ QGstreamerAudioInputEndpointSelector(QObject *parent);
+ ~QGstreamerAudioInputEndpointSelector();
+
+ QList<QString> availableEndpoints() const;
+ QString endpointDescription(const QString& name) const;
+ QString defaultEndpoint() const;
+ QString activeEndpoint() const;
+
+public Q_SLOTS:
+ void setActiveEndpoint(const QString& name);
+
+private:
+ void update();
+ void updateAlsaDevices();
+ void updateOssDevices();
+ void updatePulseDevices();
+
+ QString m_audioInput;
+ QList<QString> m_names;
+ QList<QString> m_descriptions;
+};
+
+#endif // QGSTREAMERAUDIOINPUTENDPOINTSELECTOR_H
diff --git a/src/plugins/gstreamer/qgstreamerbushelper.cpp b/src/plugins/gstreamer/qgstreamerbushelper.cpp
new file mode 100644
index 000000000..a60ec7fab
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamerbushelper.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QMap>
+#include <QTimer>
+#include <QMutex>
+
+#include "qgstreamerbushelper.h"
+
+
+#ifndef QT_NO_GLIB
+class QGstreamerBusHelperPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ void addWatch(GstBus* bus, QGstreamerBusHelper* helper)
+ {
+ setParent(helper);
+ m_tag = gst_bus_add_watch_full(bus, 0, busCallback, this, NULL);
+ m_helper = helper;
+ filter = 0;
+ }
+
+ void removeWatch(QGstreamerBusHelper* helper)
+ {
+ Q_UNUSED(helper);
+ g_source_remove(m_tag);
+ }
+
+ static QGstreamerBusHelperPrivate* instance()
+ {
+ return new QGstreamerBusHelperPrivate;
+ }
+
+private:
+ void processMessage(GstBus* bus, GstMessage* message)
+ {
+ Q_UNUSED(bus);
+ emit m_helper->message(message);
+ }
+
+ static gboolean busCallback(GstBus *bus, GstMessage *message, gpointer data)
+ {
+ reinterpret_cast<QGstreamerBusHelperPrivate*>(data)->processMessage(bus, message);
+ return TRUE;
+ }
+
+ guint m_tag;
+ QGstreamerBusHelper* m_helper;
+
+public:
+ GstBus* bus;
+ QGstreamerSyncEventFilter *filter;
+ QMutex filterMutex;
+};
+
+#else
+
+class QGstreamerBusHelperPrivate : public QObject
+{
+ Q_OBJECT
+ typedef QMap<QGstreamerBusHelper*, GstBus*> HelperMap;
+
+public:
+ void addWatch(GstBus* bus, QGstreamerBusHelper* helper)
+ {
+ m_helperMap.insert(helper, bus);
+
+ if (m_helperMap.size() == 1)
+ m_intervalTimer->start();
+ }
+
+ void removeWatch(QGstreamerBusHelper* helper)
+ {
+ m_helperMap.remove(helper);
+
+ if (m_helperMap.size() == 0)
+ m_intervalTimer->stop();
+ }
+
+ static QGstreamerBusHelperPrivate* instance()
+ {
+ static QGstreamerBusHelperPrivate self;
+
+ return &self;
+ }
+
+private slots:
+ void interval()
+ {
+ for (HelperMap::iterator it = m_helperMap.begin(); it != m_helperMap.end(); ++it) {
+ GstMessage* message;
+
+ while ((message = gst_bus_poll(it.value(), GST_MESSAGE_ANY, 0)) != 0) {
+ emit it.key()->message(message);
+ gst_message_unref(message);
+ }
+
+ emit it.key()->message(QGstreamerMessage());
+ }
+ }
+
+private:
+ QGstreamerBusHelperPrivate()
+ {
+ m_intervalTimer = new QTimer(this);
+ m_intervalTimer->setInterval(250);
+
+ connect(m_intervalTimer, SIGNAL(timeout()), SLOT(interval()));
+ }
+
+ HelperMap m_helperMap;
+ QTimer* m_intervalTimer;
+
+public:
+ GstBus* bus;
+ QGstreamerSyncEventFilter *filter;
+ QMutex filterMutex;
+};
+#endif
+
+
+static GstBusSyncReply syncGstBusFilter(GstBus* bus, GstMessage* message, QGstreamerBusHelperPrivate *d)
+{
+ Q_UNUSED(bus);
+ QMutexLocker lock(&d->filterMutex);
+
+ bool res = false;
+
+ if (d->filter)
+ res = d->filter->processSyncMessage(QGstreamerMessage(message));
+
+ return res ? GST_BUS_DROP : GST_BUS_PASS;
+}
+
+
+/*!
+ \class gstreamer::QGstreamerBusHelper
+ \internal
+*/
+
+QGstreamerBusHelper::QGstreamerBusHelper(GstBus* bus, QObject* parent):
+ QObject(parent),
+ d(QGstreamerBusHelperPrivate::instance())
+{
+ d->bus = bus;
+ d->addWatch(bus, this);
+
+ gst_bus_set_sync_handler(bus, (GstBusSyncHandler)syncGstBusFilter, d);
+}
+
+QGstreamerBusHelper::~QGstreamerBusHelper()
+{
+ d->removeWatch(this);
+ gst_bus_set_sync_handler(d->bus,0,0);
+}
+
+void QGstreamerBusHelper::installSyncEventFilter(QGstreamerSyncEventFilter *filter)
+{
+ QMutexLocker lock(&d->filterMutex);
+ d->filter = filter;
+}
+
+#include "qgstreamerbushelper.moc"
diff --git a/src/plugins/gstreamer/qgstreamerbushelper.h b/src/plugins/gstreamer/qgstreamerbushelper.h
new file mode 100644
index 000000000..5375c44ae
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamerbushelper.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERBUSHELPER_H
+#define QGSTREAMERBUSHELPER_H
+
+#include <QObject>
+
+#include <qgstreamermessage.h>
+#include <gst/gst.h>
+
+class QGstreamerSyncEventFilter {
+public:
+ //returns true if message was processed and should be dropped, false otherwise
+ virtual bool processSyncMessage(const QGstreamerMessage &message) = 0;
+};
+
+class QGstreamerBusHelperPrivate;
+
+class QGstreamerBusHelper : public QObject
+{
+ Q_OBJECT
+ friend class QGstreamerBusHelperPrivate;
+
+public:
+ QGstreamerBusHelper(GstBus* bus, QObject* parent = 0);
+ ~QGstreamerBusHelper();
+
+ void installSyncEventFilter(QGstreamerSyncEventFilter *filter);
+
+signals:
+ void message(QGstreamerMessage const& message);
+
+
+private:
+ QGstreamerBusHelperPrivate* d;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/qgstreamergltexturerenderer.cpp b/src/plugins/gstreamer/qgstreamergltexturerenderer.cpp
new file mode 100644
index 000000000..5d1a11ffb
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamergltexturerenderer.cpp
@@ -0,0 +1,578 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qvideosurfacegstsink.h"
+#include "qabstractvideosurface.h"
+#include "qgstutils.h"
+
+#include <QtGui/qevent.h>
+#include <QtGui/qapplication.h>
+#include <QtGui/qx11info_x11.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qthread.h>
+
+#include <QtOpenGL/qgl.h>
+
+#include <gst/gst.h>
+#include <gst/interfaces/xoverlay.h>
+#include <gst/interfaces/propertyprobe.h>
+#include <gst/interfaces/meegovideotexture.h>
+#include <gst/interfaces/meegovideorenderswitch.h>
+
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "qgstreamergltexturerenderer.h"
+
+//#define GL_TEXTURE_SINK_DEBUG 1
+
+//from extdefs.h
+typedef void *EGLSyncKHR;
+typedef khronos_utime_nanoseconds_t EGLTimeKHR;
+
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#define EGL_SYNC_FENCE_KHR 0x30F9
+
+typedef EGLSyncKHR (EGLAPIENTRYP _PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy,
+ EGLenum type, const EGLint * attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP _PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy,
+ EGLSyncKHR sync);
+
+
+const QAbstractVideoBuffer::HandleType EGLImageTextureHandle =
+ QAbstractVideoBuffer::HandleType(QAbstractVideoBuffer::UserHandle+3434);
+
+// EGLSync functions
+_PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR;
+_PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR;
+
+class QGStreamerGLTextureBuffer : public QAbstractVideoBuffer
+{
+public:
+ QGStreamerGLTextureBuffer(MeegoGstVideoTexture *textureSink, int frameNumber) :
+ QAbstractVideoBuffer(EGLImageTextureHandle),
+ m_textureSink(MEEGO_GST_VIDEO_TEXTURE(textureSink)),
+ m_frameNumber(frameNumber)
+ {
+ }
+
+ ~QGStreamerGLTextureBuffer()
+ {
+ }
+
+
+ MapMode mapMode() const { return NotMapped; }
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine)
+ {
+ Q_UNUSED(mode);
+ Q_UNUSED(numBytes);
+ Q_UNUSED(bytesPerLine);
+
+ //acquire_frame should really be called at buffer construction time
+ //but it conflicts with id-less implementation of gst texture sink.
+#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1
+ qDebug() << "acquire frame" << m_frameNumber;
+#endif
+ if (!meego_gst_video_texture_acquire_frame(m_textureSink,m_frameNumber))
+ qWarning() << Q_FUNC_INFO << "acquire-frame failed" << m_frameNumber;
+
+
+#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1
+ qDebug() << "map frame" << m_frameNumber;
+#endif
+
+ gboolean bind_status = meego_gst_video_texture_bind_frame(m_textureSink, GL_TEXTURE_EXTERNAL_OES, m_frameNumber);
+ if (!bind_status)
+ qWarning() << Q_FUNC_INFO << "bind-frame failed";
+
+ return (uchar*)1;
+ }
+
+ void unmap()
+ {
+ gboolean bind_status = meego_gst_video_texture_bind_frame(m_textureSink, GL_TEXTURE_EXTERNAL_OES, -1);
+
+#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1
+ qDebug() << "unmap frame" << m_frameNumber;
+#endif
+
+ if (!bind_status)
+ qWarning() << Q_FUNC_INFO << "unbind-frame failed";
+
+ //release_frame should really be called in destructor
+ //but this conflicts with id-less implementation of gst texture sink.
+#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1
+ qDebug() << "release frame" << m_frameNumber;
+#endif
+ EGLSyncKHR sync = eglCreateSyncKHR(eglGetDisplay((EGLNativeDisplayType)QX11Info::display()), EGL_SYNC_FENCE_KHR, NULL);
+ meego_gst_video_texture_release_frame(m_textureSink, m_frameNumber, sync);
+ }
+
+ QVariant handle() const
+ {
+ return m_frameNumber;
+ }
+
+private:
+ MeegoGstVideoTexture *m_textureSink;
+ int m_frameNumber;
+};
+
+
+QGstreamerGLTextureRenderer::QGstreamerGLTextureRenderer(QObject *parent) :
+ QVideoRendererControl(parent),
+ m_videoSink(0),
+ m_surface(0),
+ m_context(0),
+ m_winId(0),
+ m_colorKey(49,0,49),
+ m_overlayEnabled(false),
+ m_bufferProbeId(-1)
+{
+ eglCreateSyncKHR =
+ (_PFNEGLCREATESYNCKHRPROC)eglGetProcAddress("eglCreateSyncKHR");
+ eglDestroySyncKHR =
+ (_PFNEGLDESTROYSYNCKHRPROC)eglGetProcAddress("eglDestroySyncKHR");
+}
+
+QGstreamerGLTextureRenderer::~QGstreamerGLTextureRenderer()
+{
+ if (m_surface && m_surface->isActive())
+ m_surface->stop();
+
+ if (m_videoSink)
+ gst_object_unref(GST_OBJECT(m_videoSink));
+}
+
+GstElement *QGstreamerGLTextureRenderer::videoSink()
+{
+ if (!m_videoSink && isReady()) {
+ if (m_context && !m_surface->supportedPixelFormats(EGLImageTextureHandle).isEmpty()) {
+#ifdef GL_TEXTURE_SINK_DEBUG
+ qDebug() << Q_FUNC_INFO << ": using gltexture sink";
+#endif
+ if (m_context)
+ m_context->makeCurrent();
+ m_videoSink = gst_element_factory_make("gltexturesink", "egl-texture-sink");
+ g_object_set(G_OBJECT(m_videoSink),
+ "x-display", QX11Info::display(),
+ "egl-display", eglGetDisplay((EGLNativeDisplayType)QX11Info::display()),
+ "egl-context", eglGetCurrentContext(),
+ "colorkey", m_colorKey.rgb(),
+ "autopaint-colorkey", false,
+ "use-framebuffer-memory", true,
+ "render-mode", m_overlayEnabled ? VIDEO_RENDERSWITCH_XOVERLAY_MODE
+ : VIDEO_RENDERSWITCH_TEXTURE_STREAMING_MODE,
+ (char*)NULL);
+
+ g_signal_connect(G_OBJECT(m_videoSink), "frame-ready", G_CALLBACK(handleFrameReady), (gpointer)this);
+ } else {
+ qWarning() << Q_FUNC_INFO << ": Fallback to QVideoSurfaceGstSink since EGLImageTextureHandle is not supported";
+ m_videoSink = reinterpret_cast<GstElement*>(QVideoSurfaceGstSink::createSink(m_surface));
+ }
+
+ if (m_videoSink) {
+ gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership
+ gst_object_sink(GST_OBJECT(m_videoSink));
+
+ GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
+ m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this);
+ }
+ }
+
+ return m_videoSink;
+}
+
+QAbstractVideoSurface *QGstreamerGLTextureRenderer::surface() const
+{
+ return m_surface;
+}
+
+void QGstreamerGLTextureRenderer::setSurface(QAbstractVideoSurface *surface)
+{
+ if (m_surface != surface) {
+#ifdef GL_TEXTURE_SINK_DEBUG
+ qDebug() << Q_FUNC_INFO << surface;
+#endif
+
+ bool oldReady = isReady();
+
+ m_context = const_cast<QGLContext*>(QGLContext::currentContext());
+
+ if (m_videoSink)
+ gst_object_unref(GST_OBJECT(m_videoSink));
+
+ m_videoSink = 0;
+
+ if (m_surface) {
+ disconnect(m_surface, SIGNAL(supportedFormatsChanged()),
+ this, SLOT(handleFormatChange()));
+ }
+
+ m_surface = surface;
+
+ if (oldReady != isReady())
+ emit readyChanged(!oldReady);
+
+ if (m_surface) {
+ connect(m_surface, SIGNAL(supportedFormatsChanged()),
+ this, SLOT(handleFormatChange()));
+ }
+
+ emit sinkChanged();
+ }
+}
+
+void QGstreamerGLTextureRenderer::handleFormatChange()
+{
+ if (m_videoSink)
+ gst_object_unref(GST_OBJECT(m_videoSink));
+
+ m_videoSink = 0;
+ emit sinkChanged();
+}
+
+void QGstreamerGLTextureRenderer::handleFrameReady(GstElement *sink, gint frame, gpointer data)
+{
+ Q_UNUSED(sink);
+ QGstreamerGLTextureRenderer* renderer = reinterpret_cast<QGstreamerGLTextureRenderer*>(data);
+
+ QMutexLocker locker(&renderer->m_mutex);
+ QMetaObject::invokeMethod(renderer, "renderGLFrame",
+ Qt::QueuedConnection,
+ Q_ARG(int, frame));
+
+ //we have to wait to ensure the frame is not reused,
+ //timeout is added to avoid deadlocks when the main thread is
+ //waiting for rendering to complete, this is possible for example during state chages.
+ //If frame is not rendered during 60ms (~1-2 frames interval) it's better to unblock and drop it if necessary
+ renderer->m_renderCondition.wait(&renderer->m_mutex, 60);
+}
+
+void QGstreamerGLTextureRenderer::renderGLFrame(int frame)
+{
+#if defined(GL_TEXTURE_SINK_DEBUG) && GL_TEXTURE_SINK_DEBUG > 1
+ qDebug() << Q_FUNC_INFO << "frame:" << frame << "surface active:" << m_surface->isActive();
+#endif
+ QMutexLocker locker(&m_mutex);
+
+ if (!m_surface) {
+ m_renderCondition.wakeAll();
+ return;
+ }
+
+ MeegoGstVideoTexture *textureSink = MEEGO_GST_VIDEO_TEXTURE(m_videoSink);
+
+ if (m_context)
+ m_context->makeCurrent();
+
+ //don't try to render the frame if state is changed to NULL or READY
+ GstState pendingState = GST_STATE_NULL;
+ GstState newState = GST_STATE_NULL;
+ GstStateChangeReturn res = gst_element_get_state(m_videoSink,
+ &newState,
+ &pendingState,
+ 0);//don't block and return immediately
+
+ if (res == GST_STATE_CHANGE_FAILURE ||
+ newState == GST_STATE_NULL ||
+ pendingState == GST_STATE_NULL) {
+ stopRenderer();
+ m_renderCondition.wakeAll();
+ return;
+ }
+
+ if (!m_surface->isActive()) {
+ //find the native video size
+ GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
+ GstCaps *caps = gst_pad_get_negotiated_caps(pad);
+
+ if (caps) {
+ QSize newNativeSize = QGstUtils::capsCorrectedResolution(caps);
+ if (m_nativeSize != newNativeSize) {
+ m_nativeSize = newNativeSize;
+ emit nativeSizeChanged();
+ }
+ gst_caps_unref(caps);
+ }
+
+ //start the surface...
+ QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32, EGLImageTextureHandle);
+ if (!m_surface->start(format)) {
+ qWarning() << Q_FUNC_INFO << "failed to start video surface" << format;
+ m_renderCondition.wakeAll();
+ return;
+ }
+ }
+
+ QGStreamerGLTextureBuffer *buffer = new QGStreamerGLTextureBuffer(textureSink, frame);
+ QVideoFrame videoFrame(buffer,
+ m_surface->surfaceFormat().frameSize(),
+ m_surface->surfaceFormat().pixelFormat());
+ m_surface->present(videoFrame);
+ m_renderCondition.wakeAll();
+}
+
+bool QGstreamerGLTextureRenderer::isReady() const
+{
+ if (!m_surface)
+ return false;
+
+ if (m_winId > 0)
+ return true;
+
+ //winId is required only for EGLImageTextureHandle compatible surfaces
+ return m_surface->supportedPixelFormats(EGLImageTextureHandle).isEmpty();
+}
+
+void QGstreamerGLTextureRenderer::handleBusMessage(GstMessage* gm)
+{
+#ifdef GL_TEXTURE_SINK_DEBUG
+ qDebug() << Q_FUNC_INFO << GST_MESSAGE_TYPE_NAME(gm);
+#endif
+
+ if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_STATE_CHANGED) {
+ GstState oldState;
+ GstState newState;
+ gst_message_parse_state_changed(gm, &oldState, &newState, 0);
+
+#ifdef GL_TEXTURE_SINK_DEBUG
+ qDebug() << Q_FUNC_INFO << "State changed:" << oldState << newState;
+#endif
+
+ if (newState == GST_STATE_READY || newState == GST_STATE_NULL) {
+ stopRenderer();
+ }
+
+ if (oldState == GST_STATE_READY && newState == GST_STATE_PAUSED) {
+ updateNativeVideoSize();
+ }
+ }
+}
+
+void QGstreamerGLTextureRenderer::handleSyncMessage(GstMessage* gm)
+{
+#ifdef GL_TEXTURE_SINK_DEBUG
+ qDebug() << Q_FUNC_INFO;
+#endif
+
+ if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT &&
+ gst_structure_has_name(gm->structure, "prepare-xwindow-id"))
+ precessNewStream();
+}
+
+void QGstreamerGLTextureRenderer::precessNewStream()
+{
+ if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
+ GstXOverlay *overlay = GST_X_OVERLAY(m_videoSink);
+
+ gst_x_overlay_set_xwindow_id(overlay, m_winId);
+
+ if (!m_displayRect.isEmpty()) {
+ gst_x_overlay_set_render_rectangle(overlay,
+ m_displayRect.x(),
+ m_displayRect.y(),
+ m_displayRect.width(),
+ m_displayRect.height());
+ }
+
+ GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
+ m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this);
+ }
+}
+
+void QGstreamerGLTextureRenderer::stopRenderer()
+{
+#ifdef GL_TEXTURE_SINK_DEBUG
+ qDebug() << Q_FUNC_INFO;
+#endif
+
+ if (m_surface && m_surface->isActive())
+ m_surface->stop();
+
+ if (!m_nativeSize.isEmpty()) {
+ m_nativeSize = QSize();
+ emit nativeSizeChanged();
+ }
+}
+
+bool QGstreamerGLTextureRenderer::overlayEnabled() const
+{
+ return m_overlayEnabled;
+}
+
+void QGstreamerGLTextureRenderer::setOverlayEnabled(bool enabled)
+{
+
+ if (m_videoSink && (m_overlayEnabled != enabled)) {
+ qDebug() << Q_FUNC_INFO << enabled;
+ g_object_set(G_OBJECT(m_videoSink),
+ "render-mode",
+ enabled ? VIDEO_RENDERSWITCH_XOVERLAY_MODE : VIDEO_RENDERSWITCH_TEXTURE_STREAMING_MODE,
+ (char *)NULL);
+ }
+
+ m_overlayEnabled = enabled;
+}
+
+
+WId QGstreamerGLTextureRenderer::winId() const
+{
+ return m_winId;
+}
+
+void QGstreamerGLTextureRenderer::setWinId(WId id)
+{
+#ifdef GL_TEXTURE_SINK_DEBUG
+ qDebug() << Q_FUNC_INFO << id;
+#endif
+
+ if (m_winId == id)
+ return;
+
+ bool oldReady = isReady();
+
+ m_winId = id;
+
+ if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
+ //don't set winId in NULL state,
+ //texture sink opens xvideo port on set_xwindow_id,
+ //this fails if video resource is not granted by resource policy yet.
+ //state is changed to READY/PAUSED/PLAYING only after resource is granted.
+ GstState pendingState = GST_STATE_NULL;
+ GstState newState = GST_STATE_NULL;
+ GstStateChangeReturn res = gst_element_get_state(m_videoSink,
+ &newState,
+ &pendingState,
+ 0);//don't block and return immediately
+
+ if (res != GST_STATE_CHANGE_FAILURE &&
+ newState != GST_STATE_NULL &&
+ pendingState != GST_STATE_NULL)
+ gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), m_winId);
+ }
+
+ if (oldReady != isReady())
+ emit readyChanged(!oldReady);
+}
+
+QRect QGstreamerGLTextureRenderer::overlayGeometry() const
+{
+ return m_displayRect;
+}
+
+void QGstreamerGLTextureRenderer::setOverlayGeometry(const QRect &geometry)
+{
+ if (m_displayRect != geometry) {
+#ifdef GL_TEXTURE_SINK_DEBUG
+ qDebug() << Q_FUNC_INFO << geometry;
+#endif
+ m_displayRect = geometry;
+
+ if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
+ if (m_displayRect.isEmpty())
+ gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink), -1, -1, -1, -1);
+ else
+ gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink),
+ m_displayRect.x(),
+ m_displayRect.y(),
+ m_displayRect.width(),
+ m_displayRect.height());
+ repaintOverlay();
+ }
+ }
+}
+
+QColor QGstreamerGLTextureRenderer::colorKey() const
+{
+ return m_colorKey;
+}
+
+void QGstreamerGLTextureRenderer::repaintOverlay()
+{
+ if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
+ //don't call gst_x_overlay_expose if the sink is in null state
+ GstState state = GST_STATE_NULL;
+ GstStateChangeReturn res = gst_element_get_state(m_videoSink, &state, NULL, 1000000);
+ if (res != GST_STATE_CHANGE_FAILURE && state != GST_STATE_NULL) {
+ gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink));
+ }
+ }
+}
+
+QSize QGstreamerGLTextureRenderer::nativeSize() const
+{
+ return m_nativeSize;
+}
+
+gboolean QGstreamerGLTextureRenderer::padBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data)
+{
+ QGstreamerGLTextureRenderer *control = reinterpret_cast<QGstreamerGLTextureRenderer*>(user_data);
+ QMetaObject::invokeMethod(control, "updateNativeVideoSize", Qt::QueuedConnection);
+ gst_pad_remove_buffer_probe(pad, control->m_bufferProbeId);
+
+ return TRUE;
+}
+
+void QGstreamerGLTextureRenderer::updateNativeVideoSize()
+{
+ const QSize oldSize = m_nativeSize;
+
+ if (m_videoSink) {
+ //find video native size to update video widget size hint
+ GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
+ GstCaps *caps = gst_pad_get_negotiated_caps(pad);
+
+ if (caps) {
+ m_nativeSize = QGstUtils::capsCorrectedResolution(caps);
+ gst_caps_unref(caps);
+ }
+ } else {
+ m_nativeSize = QSize();
+ }
+#ifdef GL_TEXTURE_SINK_DEBUG
+ qDebug() << Q_FUNC_INFO << oldSize << m_nativeSize << m_videoSink;
+#endif
+
+ if (m_nativeSize != oldSize)
+ emit nativeSizeChanged();
+}
diff --git a/src/plugins/gstreamer/qgstreamergltexturerenderer.h b/src/plugins/gstreamer/qgstreamergltexturerenderer.h
new file mode 100644
index 000000000..92beb1a17
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamergltexturerenderer.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERGLTEXTURERENDERER_H
+#define QGSTREAMERGLTEXTURERENDERER_H
+
+#include <qvideorenderercontrol.h>
+#include "qvideosurfacegstsink.h"
+
+#include "qgstreamervideorendererinterface.h"
+#include <QtGui/qcolor.h>
+
+#include <X11/extensions/Xv.h>
+
+QT_USE_NAMESPACE
+
+class QGLContext;
+
+class QGstreamerGLTextureRenderer : public QVideoRendererControl, public QGstreamerVideoRendererInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QGstreamerVideoRendererInterface)
+
+ Q_PROPERTY(bool overlayEnabled READ overlayEnabled WRITE setOverlayEnabled)
+ Q_PROPERTY(qulonglong winId READ winId WRITE setWinId)
+ Q_PROPERTY(QRect overlayGeometry READ overlayGeometry WRITE setOverlayGeometry)
+ Q_PROPERTY(QColor colorKey READ colorKey)
+ Q_PROPERTY(QSize nativeSize READ nativeSize NOTIFY nativeSizeChanged)
+
+public:
+ QGstreamerGLTextureRenderer(QObject *parent = 0);
+ virtual ~QGstreamerGLTextureRenderer();
+
+ QAbstractVideoSurface *surface() const;
+ void setSurface(QAbstractVideoSurface *surface);
+
+ GstElement *videoSink();
+
+ bool isReady() const;
+ void handleBusMessage(GstMessage* gm);
+ void handleSyncMessage(GstMessage* gm);
+ void precessNewStream();
+ void stopRenderer();
+
+ int framebufferNumber() const;
+
+ bool overlayEnabled() const;
+ WId winId() const;
+ QRect overlayGeometry() const;
+ QColor colorKey() const;
+ QSize nativeSize() const;
+
+public slots:
+ void renderGLFrame(int);
+
+ void setOverlayEnabled(bool);
+ void setWinId(WId id);
+ void setOverlayGeometry(const QRect &geometry);
+ void repaintOverlay();
+
+signals:
+ void sinkChanged();
+ void readyChanged(bool);
+ void nativeSizeChanged();
+
+private slots:
+ void handleFormatChange();
+ void updateNativeVideoSize();
+
+private:
+ static void handleFrameReady(GstElement *sink, gint frame, gpointer data);
+ static gboolean padBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data);
+
+ GstElement *m_videoSink;
+ QAbstractVideoSurface *m_surface;
+ QGLContext *m_context;
+ QSize m_nativeSize;
+
+ WId m_winId;
+ QColor m_colorKey;
+ QRect m_displayRect;
+ bool m_overlayEnabled;
+ int m_bufferProbeId;
+
+ QMutex m_mutex;
+ QWaitCondition m_renderCondition;
+};
+
+#endif // QGSTREAMERVIDEORENDRER_H
diff --git a/src/plugins/gstreamer/qgstreamermessage.cpp b/src/plugins/gstreamer/qgstreamermessage.cpp
new file mode 100644
index 000000000..3b8057e09
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamermessage.cpp
@@ -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$
+** 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 <gst/gst.h>
+
+#include "qgstreamermessage.h"
+
+
+static int wuchi = qRegisterMetaType<QGstreamerMessage>();
+
+
+/*!
+ \class gstreamer::QGstreamerMessage
+ \internal
+*/
+
+QGstreamerMessage::QGstreamerMessage():
+ m_message(0)
+{
+}
+
+QGstreamerMessage::QGstreamerMessage(GstMessage* message):
+ m_message(message)
+{
+ gst_message_ref(m_message);
+}
+
+QGstreamerMessage::QGstreamerMessage(QGstreamerMessage const& m):
+ m_message(m.m_message)
+{
+ gst_message_ref(m_message);
+}
+
+
+QGstreamerMessage::~QGstreamerMessage()
+{
+ if (m_message != 0)
+ gst_message_unref(m_message);
+}
+
+GstMessage* QGstreamerMessage::rawMessage() const
+{
+ return m_message;
+}
+
+QGstreamerMessage& QGstreamerMessage::operator=(QGstreamerMessage const& rhs)
+{
+ if (m_message != 0)
+ gst_message_unref(m_message);
+
+ if ((m_message = rhs.m_message) != 0)
+ gst_message_ref(m_message);
+
+ return *this;
+}
diff --git a/src/plugins/gstreamer/qgstreamermessage.h b/src/plugins/gstreamer/qgstreamermessage.h
new file mode 100644
index 000000000..2bdc2a9c8
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamermessage.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERMESSAGE_H
+#define QGSTREAMERMESSAGE_H
+
+#include <QMetaType>
+
+#include <gst/gst.h>
+
+
+class QGstreamerMessage
+{
+public:
+ QGstreamerMessage();
+ QGstreamerMessage(GstMessage* message);
+ QGstreamerMessage(QGstreamerMessage const& m);
+ ~QGstreamerMessage();
+
+ GstMessage* rawMessage() const;
+
+ QGstreamerMessage& operator=(QGstreamerMessage const& rhs);
+
+private:
+ GstMessage* m_message;
+};
+
+Q_DECLARE_METATYPE(QGstreamerMessage);
+
+#endif
diff --git a/src/plugins/gstreamer/qgstreamerserviceplugin.cpp b/src/plugins/gstreamer/qgstreamerserviceplugin.cpp
new file mode 100644
index 000000000..e74085664
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamerserviceplugin.cpp
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qstring.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/QIcon>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+
+#include "qgstreamerserviceplugin.h"
+
+//#define QT_SUPPORTEDMIMETYPES_DEBUG
+
+#ifdef QMEDIA_GSTREAMER_PLAYER
+#include "qgstreamerplayerservice.h"
+#endif
+
+#if defined(QMEDIA_GSTREAMER_CAPTURE)
+#include "qgstreamercaptureservice.h"
+#endif
+
+#ifdef QMEDIA_GSTREAMER_CAMERABIN
+#include "camerabinservice.h"
+#endif
+
+#include <qmediaserviceprovider.h>
+
+#include <linux/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <linux/videodev2.h>
+
+
+QStringList QGstreamerServicePlugin::keys() const
+{
+ return QStringList()
+#ifdef QMEDIA_GSTREAMER_PLAYER
+ << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)
+#endif
+
+#ifdef QMEDIA_GSTREAMER_CAPTURE
+ << QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE)
+ << QLatin1String(Q_MEDIASERVICE_CAMERA)
+#elif defined(QMEDIA_GSTREAMER_CAMERABIN)
+ << QLatin1String(Q_MEDIASERVICE_CAMERA)
+#endif
+ ;
+
+}
+
+QMediaService* QGstreamerServicePlugin::create(const QString &key)
+{
+ static bool initialized = false;
+ if (!initialized) {
+ initialized = true;
+ gst_init(NULL, NULL);
+ }
+
+#ifdef QMEDIA_GSTREAMER_PLAYER
+ if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER))
+ return new QGstreamerPlayerService;
+#endif
+
+#ifdef QMEDIA_GSTREAMER_CAMERABIN
+ if (key == QLatin1String(Q_MEDIASERVICE_CAMERA) && CameraBinService::isCameraBinAvailable())
+ return new CameraBinService(key);
+#endif
+
+#ifdef QMEDIA_GSTREAMER_CAPTURE
+ if (key == QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE))
+ return new QGstreamerCaptureService(key);
+
+ if (key == QLatin1String(Q_MEDIASERVICE_CAMERA))
+ return new QGstreamerCaptureService(key);
+#endif
+
+ qWarning() << "Gstreamer service plugin: unsupported key:" << key;
+ return 0;
+}
+
+void QGstreamerServicePlugin::release(QMediaService *service)
+{
+ delete service;
+}
+
+QMediaServiceProviderHint::Features QGstreamerServicePlugin::supportedFeatures(
+ const QByteArray &service) const
+{
+ if (service == Q_MEDIASERVICE_MEDIAPLAYER)
+ return QMediaServiceProviderHint::StreamPlayback | QMediaServiceProviderHint::VideoSurface;
+ else if (service == Q_MEDIASERVICE_CAMERA)
+ return QMediaServiceProviderHint::VideoSurface;
+ else
+ return QMediaServiceProviderHint::Features();
+}
+
+QList<QByteArray> QGstreamerServicePlugin::devices(const QByteArray &service) const
+{
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ if (m_cameraDevices.isEmpty())
+ updateDevices();
+
+ return m_cameraDevices;
+ }
+
+ return QList<QByteArray>();
+}
+
+QString QGstreamerServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
+{
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ if (m_cameraDevices.isEmpty())
+ updateDevices();
+
+ for (int i=0; i<m_cameraDevices.count(); i++)
+ if (m_cameraDevices[i] == device)
+ return m_cameraDescriptions[i];
+ }
+
+ return QString();
+}
+
+QVariant QGstreamerServicePlugin::deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property)
+{
+ Q_UNUSED(service);
+ Q_UNUSED(device);
+ Q_UNUSED(property);
+ return QVariant();
+}
+
+void QGstreamerServicePlugin::updateDevices() const
+{
+ m_cameraDevices.clear();
+ m_cameraDescriptions.clear();
+
+#ifdef Q_WS_MAEMO_5
+ m_cameraDevices << "/dev/video0" << "/dev/video1";
+ m_cameraDescriptions << tr("Main Camera") << tr("Front Camera");
+ return;
+#endif
+
+#ifdef Q_WS_MAEMO_6
+ m_cameraDevices << "primary" << "secondary";
+ m_cameraDescriptions << tr("Main camera") << tr("Front camera");
+ return;
+#endif
+
+ QDir devDir("/dev");
+ devDir.setFilter(QDir::System);
+
+ QFileInfoList entries = devDir.entryInfoList(QStringList() << "video*");
+
+ foreach( const QFileInfo &entryInfo, entries ) {
+ //qDebug() << "Try" << entryInfo.filePath();
+
+ int fd = ::open(entryInfo.filePath().toLatin1().constData(), O_RDWR );
+ if (fd == -1)
+ continue;
+
+ bool isCamera = false;
+
+ v4l2_input input;
+ memset(&input, 0, sizeof(input));
+ for (; ::ioctl(fd, VIDIOC_ENUMINPUT, &input) >= 0; ++input.index) {
+ if(input.type == V4L2_INPUT_TYPE_CAMERA || input.type == 0) {
+ isCamera = ::ioctl(fd, VIDIOC_S_INPUT, input.index) != 0;
+ break;
+ }
+ }
+
+ if (isCamera) {
+ // find out its driver "name"
+ QString name;
+ struct v4l2_capability vcap;
+ memset(&vcap, 0, sizeof(struct v4l2_capability));
+
+ if (ioctl(fd, VIDIOC_QUERYCAP, &vcap) != 0)
+ name = entryInfo.fileName();
+ else
+ name = QString((const char*)vcap.card);
+ //qDebug() << "found camera: " << name;
+
+ m_cameraDevices.append(entryInfo.filePath().toLocal8Bit());
+ m_cameraDescriptions.append(name);
+ }
+ ::close(fd);
+ }
+}
+
+namespace {
+ const char* getCodecAlias(const QString &codec)
+ {
+ if (codec.startsWith("avc1."))
+ return "video/x-h264";
+
+ if (codec.startsWith("mp4a."))
+ return "audio/mpeg4";
+
+ if (codec.startsWith("mp4v.20."))
+ return "video/mpeg4";
+
+ if (codec == "samr")
+ return "audio/amr";
+
+ return 0;
+ }
+
+ const char* getMimeTypeAlias(const QString &mimeType)
+ {
+ if (mimeType == "video/mp4")
+ return "video/mpeg4";
+
+ if (mimeType == "audio/mp4")
+ return "audio/mpeg4";
+
+ if (mimeType == "video/ogg"
+ || mimeType == "audio/ogg")
+ return "application/ogg";
+
+ return 0;
+ }
+}
+
+QtMultimediaKit::SupportEstimate QGstreamerServicePlugin::hasSupport(const QString &mimeType,
+ const QStringList& codecs) const
+{
+ if (m_supportedMimeTypeSet.isEmpty())
+ updateSupportedMimeTypes();
+
+ QString mimeTypeLowcase = mimeType.toLower();
+ bool containsMimeType = m_supportedMimeTypeSet.contains(mimeTypeLowcase);
+ if (!containsMimeType) {
+ const char* mimeTypeAlias = getMimeTypeAlias(mimeTypeLowcase);
+ containsMimeType = m_supportedMimeTypeSet.contains(mimeTypeAlias);
+ if (!containsMimeType) {
+ containsMimeType = m_supportedMimeTypeSet.contains("video/" + mimeTypeLowcase)
+ || m_supportedMimeTypeSet.contains("video/x-" + mimeTypeLowcase)
+ || m_supportedMimeTypeSet.contains("audio/" + mimeTypeLowcase)
+ || m_supportedMimeTypeSet.contains("audio/x-" + mimeTypeLowcase);
+ }
+ }
+
+ int supportedCodecCount = 0;
+ foreach(const QString &codec, codecs) {
+ QString codecLowcase = codec.toLower();
+ const char* codecAlias = getCodecAlias(codecLowcase);
+ if (codecAlias) {
+ if (m_supportedMimeTypeSet.contains(codecAlias))
+ supportedCodecCount++;
+ } else if (m_supportedMimeTypeSet.contains("video/" + codecLowcase)
+ || m_supportedMimeTypeSet.contains("video/x-" + codecLowcase)
+ || m_supportedMimeTypeSet.contains("audio/" + codecLowcase)
+ || m_supportedMimeTypeSet.contains("audio/x-" + codecLowcase)) {
+ supportedCodecCount++;
+ }
+ }
+ if (supportedCodecCount > 0 && supportedCodecCount == codecs.size())
+ return QtMultimediaKit::ProbablySupported;
+
+ if (supportedCodecCount == 0 && !containsMimeType)
+ return QtMultimediaKit::NotSupported;
+
+ return QtMultimediaKit::MaybeSupported;
+}
+
+void QGstreamerServicePlugin::updateSupportedMimeTypes() const
+{
+ //enumerate supported mime types
+ gst_init(NULL, NULL);
+
+ GList *plugins, *orig_plugins;
+ orig_plugins = plugins = gst_default_registry_get_plugin_list ();
+
+ while (plugins) {
+ GList *features, *orig_features;
+
+ GstPlugin *plugin = (GstPlugin *) (plugins->data);
+ plugins = g_list_next (plugins);
+
+ if (plugin->flags & (1<<1)) //GST_PLUGIN_FLAG_BLACKLISTED
+ continue;
+
+ orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get_default (),
+ plugin->desc.name);
+ while (features) {
+ if (!G_UNLIKELY(features->data == NULL)) {
+ GstPluginFeature *feature = GST_PLUGIN_FEATURE(features->data);
+ if (GST_IS_ELEMENT_FACTORY (feature)) {
+ GstElementFactory *factory = GST_ELEMENT_FACTORY(gst_plugin_feature_load(feature));
+ if (factory
+ && factory->numpadtemplates > 0
+ && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0
+ || qstrcmp(factory->details.klass, "Codec/Decoder/Video") == 0
+ || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )) {
+ const GList *pads = factory->staticpadtemplates;
+ while (pads) {
+ GstStaticPadTemplate *padtemplate = (GstStaticPadTemplate*)(pads->data);
+ pads = g_list_next (pads);
+ if (padtemplate->direction != GST_PAD_SINK)
+ continue;
+ if (padtemplate->static_caps.string) {
+ GstCaps *caps = gst_static_caps_get(&padtemplate->static_caps);
+ if (!gst_caps_is_any (caps) && ! gst_caps_is_empty (caps)) {
+ for (guint i = 0; i < gst_caps_get_size(caps); i++) {
+ GstStructure *structure = gst_caps_get_structure(caps, i);
+ QString nameLowcase = QString(gst_structure_get_name (structure)).toLower();
+
+ m_supportedMimeTypeSet.insert(nameLowcase);
+ if (nameLowcase.contains("mpeg")) {
+ //Because mpeg version number is only included in the detail
+ //description, it is necessary to manually extract this information
+ //in order to match the mime type of mpeg4.
+ const GValue *value = gst_structure_get_value(structure, "mpegversion");
+ if (value) {
+ gchar *str = gst_value_serialize (value);
+ QString versions(str);
+ QStringList elements = versions.split(QRegExp("\\D+"), QString::SkipEmptyParts);
+ foreach(const QString &e, elements)
+ m_supportedMimeTypeSet.insert(nameLowcase + e);
+ g_free (str);
+ }
+ }
+ }
+ }
+ }
+ }
+ gst_object_unref (factory);
+ }
+ } else if (GST_IS_TYPE_FIND_FACTORY(feature)) {
+ QString name(gst_plugin_feature_get_name(feature));
+ if (name.contains('/')) //filter out any string without '/' which is obviously not a mime type
+ m_supportedMimeTypeSet.insert(name.toLower());
+ }
+ }
+ features = g_list_next (features);
+ }
+ gst_plugin_feature_list_free (orig_features);
+ }
+ gst_plugin_list_free (orig_plugins);
+
+#if defined QT_SUPPORTEDMIMETYPES_DEBUG
+ QStringList list = m_supportedMimeTypeSet.toList();
+ list.sort();
+ if (qgetenv("QT_DEBUG_PLUGINS").toInt() > 0) {
+ foreach(const QString &type, list)
+ qDebug() << type;
+ }
+#endif
+}
+
+QStringList QGstreamerServicePlugin::supportedMimeTypes() const
+{
+ return QStringList();
+}
+
+Q_EXPORT_PLUGIN2(qtmedia_gstengine, QGstreamerServicePlugin);
diff --git a/src/plugins/gstreamer/qgstreamerserviceplugin.h b/src/plugins/gstreamer/qgstreamerserviceplugin.h
new file mode 100644
index 000000000..0ce0bbd84
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamerserviceplugin.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QGSTREAMERSERVICEPLUGIN_H
+#define QGSTREAMERSERVICEPLUGIN_H
+
+#include <qmediaserviceproviderplugin.h>
+#include <QtCore/qset.h>
+
+QT_USE_NAMESPACE
+
+
+class QGstreamerServicePlugin
+ : public QMediaServiceProviderPlugin
+ , public QMediaServiceSupportedDevicesInterface
+ , public QMediaServiceFeaturesInterface
+ , public QMediaServiceSupportedFormatsInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
+ Q_INTERFACES(QMediaServiceFeaturesInterface)
+ Q_INTERFACES(QMediaServiceSupportedFormatsInterface)
+public:
+ QStringList keys() const;
+ QMediaService* create(QString const& key);
+ void release(QMediaService *service);
+
+ QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const;
+
+ QList<QByteArray> devices(const QByteArray &service) const;
+ QString deviceDescription(const QByteArray &service, const QByteArray &device);
+ QVariant deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property);
+
+ QtMultimediaKit::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const;
+ QStringList supportedMimeTypes() const;
+
+private:
+ void updateDevices() const;
+
+ mutable QList<QByteArray> m_cameraDevices;
+ mutable QStringList m_cameraDescriptions;
+ mutable QSet<QString> m_supportedMimeTypeSet; //for fast access
+
+ void updateSupportedMimeTypes() const;
+};
+
+#endif // QGSTREAMERSERVICEPLUGIN_H
diff --git a/src/plugins/gstreamer/qgstreamervideoinputdevicecontrol.cpp b/src/plugins/gstreamer/qgstreamervideoinputdevicecontrol.cpp
new file mode 100644
index 000000000..d53497d30
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamervideoinputdevicecontrol.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamervideoinputdevicecontrol.h"
+
+#include <QtGui/QIcon>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+
+#include <linux/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <linux/videodev2.h>
+
+QGstreamerVideoInputDeviceControl::QGstreamerVideoInputDeviceControl(QObject *parent)
+ :QVideoDeviceControl(parent), m_selectedDevice(0)
+{
+ update();
+}
+
+QGstreamerVideoInputDeviceControl::~QGstreamerVideoInputDeviceControl()
+{
+}
+
+int QGstreamerVideoInputDeviceControl::deviceCount() const
+{
+ return m_names.size();
+}
+
+QString QGstreamerVideoInputDeviceControl::deviceName(int index) const
+{
+ return m_names[index];
+}
+
+QString QGstreamerVideoInputDeviceControl::deviceDescription(int index) const
+{
+ return m_descriptions[index];
+}
+
+QIcon QGstreamerVideoInputDeviceControl::deviceIcon(int index) const
+{
+ Q_UNUSED(index);
+ return QIcon();
+}
+
+int QGstreamerVideoInputDeviceControl::defaultDevice() const
+{
+ return 0;
+}
+
+int QGstreamerVideoInputDeviceControl::selectedDevice() const
+{
+ return m_selectedDevice;
+}
+
+
+void QGstreamerVideoInputDeviceControl::setSelectedDevice(int index)
+{
+ if (index != m_selectedDevice) {
+ m_selectedDevice = index;
+ emit selectedDeviceChanged(index);
+ emit selectedDeviceChanged(deviceName(index));
+ }
+}
+
+
+void QGstreamerVideoInputDeviceControl::update()
+{
+ m_names.clear();
+ m_descriptions.clear();
+
+#ifdef Q_WS_MAEMO_6
+ m_names << QLatin1String("primary") << QLatin1String("secondary");
+ m_descriptions << tr("Main camera") << tr("Front camera");
+#else
+ QDir devDir("/dev");
+ devDir.setFilter(QDir::System);
+
+ QFileInfoList entries = devDir.entryInfoList(QStringList() << "video*");
+
+ foreach( const QFileInfo &entryInfo, entries ) {
+ //qDebug() << "Try" << entryInfo.filePath();
+
+ int fd = ::open(entryInfo.filePath().toLatin1().constData(), O_RDWR );
+ if (fd == -1)
+ continue;
+
+ bool isCamera = false;
+
+ v4l2_input input;
+ memset(&input, 0, sizeof(input));
+ for (; ::ioctl(fd, VIDIOC_ENUMINPUT, &input) >= 0; ++input.index) {
+ if(input.type == V4L2_INPUT_TYPE_CAMERA || input.type == 0) {
+ isCamera = ::ioctl(fd, VIDIOC_S_INPUT, input.index) != 0;
+ break;
+ }
+ }
+
+ if (isCamera) {
+ // find out its driver "name"
+ QString name;
+ struct v4l2_capability vcap;
+ memset(&vcap, 0, sizeof(struct v4l2_capability));
+
+ if (ioctl(fd, VIDIOC_QUERYCAP, &vcap) != 0)
+ name = entryInfo.fileName();
+ else
+ name = QString((const char*)vcap.card);
+ //qDebug() << "found camera: " << name;
+
+ m_names.append(entryInfo.filePath());
+ m_descriptions.append(name);
+ }
+ ::close(fd);
+ }
+#endif
+}
diff --git a/src/plugins/gstreamer/qgstreamervideoinputdevicecontrol.h b/src/plugins/gstreamer/qgstreamervideoinputdevicecontrol.h
new file mode 100644
index 000000000..a31636239
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamervideoinputdevicecontrol.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERVIDEOINPUTDEVICECONTROL_H
+#define QGSTREAMERVIDEOINPUTDEVICECONTROL_H
+
+#include <qvideodevicecontrol.h>
+#include <QtCore/qstringlist.h>
+
+QT_USE_NAMESPACE
+
+class QGstreamerVideoInputDeviceControl : public QVideoDeviceControl
+{
+Q_OBJECT
+public:
+ QGstreamerVideoInputDeviceControl(QObject *parent);
+ ~QGstreamerVideoInputDeviceControl();
+
+ int deviceCount() const;
+
+ QString deviceName(int index) const;
+ QString deviceDescription(int index) const;
+ QIcon deviceIcon(int index) const;
+
+ int defaultDevice() const;
+ int selectedDevice() const;
+
+public Q_SLOTS:
+ void setSelectedDevice(int index);
+
+private:
+ void update();
+
+ int m_selectedDevice;
+ QStringList m_names;
+ QStringList m_descriptions;
+};
+
+#endif // QGSTREAMERAUDIOINPUTDEVICECONTROL_H
diff --git a/src/plugins/gstreamer/qgstreamervideooverlay.cpp b/src/plugins/gstreamer/qgstreamervideooverlay.cpp
new file mode 100644
index 000000000..3e19dd075
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamervideooverlay.cpp
@@ -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$
+** 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 "qgstreamervideooverlay.h"
+#include "qvideosurfacegstsink.h"
+
+#include <qvideosurfaceformat.h>
+
+#include "qx11videosurface.h"
+
+#ifndef QT_NO_XVIDEO
+
+QGstreamerVideoOverlay::QGstreamerVideoOverlay(QObject *parent)
+ : QVideoWindowControl(parent)
+ , m_surface(new QX11VideoSurface)
+ , m_videoSink(reinterpret_cast<GstElement*>(QVideoSurfaceGstSink::createSink(m_surface)))
+ , m_aspectRatioMode(Qt::KeepAspectRatio)
+ , m_fullScreen(false)
+{
+ if (m_videoSink) {
+ gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership
+ gst_object_sink(GST_OBJECT(m_videoSink));
+ }
+
+ connect(m_surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
+ this, SLOT(surfaceFormatChanged()));
+}
+
+QGstreamerVideoOverlay::~QGstreamerVideoOverlay()
+{
+ if (m_videoSink)
+ gst_object_unref(GST_OBJECT(m_videoSink));
+
+ delete m_surface;
+}
+
+WId QGstreamerVideoOverlay::winId() const
+{
+ return m_surface->winId();
+}
+
+void QGstreamerVideoOverlay::setWinId(WId id)
+{
+ bool wasReady = isReady();
+ m_surface->setWinId(id);
+
+ if (isReady() != wasReady)
+ emit readyChanged(!wasReady);
+}
+
+QRect QGstreamerVideoOverlay::displayRect() const
+{
+ return m_displayRect;
+}
+
+void QGstreamerVideoOverlay::setDisplayRect(const QRect &rect)
+{
+ m_displayRect = rect;
+
+ setScaledDisplayRect();
+}
+
+Qt::AspectRatioMode QGstreamerVideoOverlay::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void QGstreamerVideoOverlay::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_aspectRatioMode = mode;
+
+ setScaledDisplayRect();
+}
+
+void QGstreamerVideoOverlay::repaint()
+{
+}
+
+int QGstreamerVideoOverlay::brightness() const
+{
+ return m_surface->brightness();
+}
+
+void QGstreamerVideoOverlay::setBrightness(int brightness)
+{
+ m_surface->setBrightness(brightness);
+
+ emit brightnessChanged(m_surface->brightness());
+}
+
+int QGstreamerVideoOverlay::contrast() const
+{
+ return m_surface->contrast();
+}
+
+void QGstreamerVideoOverlay::setContrast(int contrast)
+{
+ m_surface->setContrast(contrast);
+
+ emit contrastChanged(m_surface->contrast());
+}
+
+int QGstreamerVideoOverlay::hue() const
+{
+ return m_surface->hue();
+}
+
+void QGstreamerVideoOverlay::setHue(int hue)
+{
+ m_surface->setHue(hue);
+
+ emit hueChanged(m_surface->hue());
+}
+
+int QGstreamerVideoOverlay::saturation() const
+{
+ return m_surface->saturation();
+}
+
+void QGstreamerVideoOverlay::setSaturation(int saturation)
+{
+ m_surface->setSaturation(saturation);
+
+ emit saturationChanged(m_surface->saturation());
+}
+
+bool QGstreamerVideoOverlay::isFullScreen() const
+{
+ return m_fullScreen;
+}
+
+void QGstreamerVideoOverlay::setFullScreen(bool fullScreen)
+{
+ emit fullScreenChanged(m_fullScreen = fullScreen);
+}
+
+QSize QGstreamerVideoOverlay::nativeSize() const
+{
+ return m_surface->surfaceFormat().sizeHint();
+}
+
+QAbstractVideoSurface *QGstreamerVideoOverlay::surface() const
+{
+ return m_surface;
+}
+
+GstElement *QGstreamerVideoOverlay::videoSink()
+{
+ return m_videoSink;
+}
+
+void QGstreamerVideoOverlay::surfaceFormatChanged()
+{
+ setScaledDisplayRect();
+
+ emit nativeSizeChanged();
+}
+
+void QGstreamerVideoOverlay::setScaledDisplayRect()
+{
+ QRect formatViewport = m_surface->surfaceFormat().viewport();
+
+ switch (m_aspectRatioMode) {
+ case Qt::KeepAspectRatio:
+ {
+ QSize size = m_surface->surfaceFormat().sizeHint();
+ size.scale(m_displayRect.size(), Qt::KeepAspectRatio);
+
+ QRect rect(QPoint(0, 0), size);
+ rect.moveCenter(m_displayRect.center());
+
+ m_surface->setDisplayRect(rect);
+ m_surface->setViewport(formatViewport);
+ }
+ break;
+ case Qt::IgnoreAspectRatio:
+ m_surface->setDisplayRect(m_displayRect);
+ m_surface->setViewport(formatViewport);
+ break;
+ case Qt::KeepAspectRatioByExpanding:
+ {
+ QSize size = m_displayRect.size();
+ size.scale(m_surface->surfaceFormat().sizeHint(), Qt::KeepAspectRatio);
+
+ QRect viewport(QPoint(0, 0), size);
+ viewport.moveCenter(formatViewport.center());
+ m_surface->setDisplayRect(m_displayRect);
+ m_surface->setViewport(viewport);
+ }
+ break;
+ };
+}
+
+#endif //QT_NO_XVIDEO
diff --git a/src/plugins/gstreamer/qgstreamervideooverlay.h b/src/plugins/gstreamer/qgstreamervideooverlay.h
new file mode 100644
index 000000000..194c4ea32
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamervideooverlay.h
@@ -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$
+** 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 QGSTREAMERVIDEOOVERLAY_H
+#define QGSTREAMERVIDEOOVERLAY_H
+
+#include <qvideowindowcontrol.h>
+
+#include "qgstreamervideorendererinterface.h"
+
+QT_BEGIN_NAMESPACE
+class QAbstractVideoSurface;
+QT_END_NAMESPACE
+class QX11VideoSurface;
+
+#if defined(Q_WS_X11) && !defined(QT_NO_XVIDEO)
+
+QT_USE_NAMESPACE
+
+class QGstreamerVideoOverlay : public QVideoWindowControl, public QGstreamerVideoRendererInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QGstreamerVideoRendererInterface)
+public:
+ QGstreamerVideoOverlay(QObject *parent = 0);
+ ~QGstreamerVideoOverlay();
+
+ WId winId() const;
+ void setWinId(WId id);
+
+ QRect displayRect() const;
+ void setDisplayRect(const QRect &rect);
+
+ bool isFullScreen() const;
+ void setFullScreen(bool fullScreen);
+
+ QSize nativeSize() const;
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ void repaint();
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ QAbstractVideoSurface *surface() const;
+
+ GstElement *videoSink();
+
+ bool isReady() const { return winId() != 0; }
+
+signals:
+ void sinkChanged();
+ void readyChanged(bool);
+
+private slots:
+ void surfaceFormatChanged();
+
+private:
+ void setScaledDisplayRect();
+
+ QX11VideoSurface *m_surface;
+ GstElement *m_videoSink;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QRect m_displayRect;
+ bool m_fullScreen;
+};
+
+#endif //QT_NO_XVIDEO
+
+#endif
diff --git a/src/plugins/gstreamer/qgstreamervideorenderer.cpp b/src/plugins/gstreamer/qgstreamervideorenderer.cpp
new file mode 100644
index 000000000..6c4e6b90c
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamervideorenderer.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qgstreamervideorenderer.h"
+#include "qvideosurfacegstsink.h"
+#include "qabstractvideosurface.h"
+
+#include <QEvent>
+#include <QApplication>
+#include <QDebug>
+
+#include <gst/gst.h>
+
+QGstreamerVideoRenderer::QGstreamerVideoRenderer(QObject *parent)
+ :QVideoRendererControl(parent),m_videoSink(0), m_surface(0)
+{
+}
+
+QGstreamerVideoRenderer::~QGstreamerVideoRenderer()
+{
+ if (m_videoSink)
+ gst_object_unref(GST_OBJECT(m_videoSink));
+}
+
+GstElement *QGstreamerVideoRenderer::videoSink()
+{
+ if (!m_videoSink && m_surface) {
+ m_videoSink = QVideoSurfaceGstSink::createSink(m_surface);
+ gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership
+ gst_object_sink(GST_OBJECT(m_videoSink));
+ }
+
+ return reinterpret_cast<GstElement*>(m_videoSink);
+}
+
+
+QAbstractVideoSurface *QGstreamerVideoRenderer::surface() const
+{
+ return m_surface;
+}
+
+void QGstreamerVideoRenderer::setSurface(QAbstractVideoSurface *surface)
+{
+ if (m_surface != surface) {
+ //qDebug() << Q_FUNC_INFO << surface;
+ if (m_videoSink)
+ gst_object_unref(GST_OBJECT(m_videoSink));
+
+ m_videoSink = 0;
+
+ if (m_surface) {
+ disconnect(m_surface, SIGNAL(supportedFormatsChanged()),
+ this, SLOT(handleFormatChange()));
+ }
+
+ m_surface = surface;
+
+ if (surface && !m_surface)
+ emit readyChanged(true);
+
+ if (!surface && m_surface)
+ emit readyChanged(false);
+
+ if (m_surface) {
+ connect(m_surface, SIGNAL(supportedFormatsChanged()),
+ this, SLOT(handleFormatChange()));
+ }
+
+ emit sinkChanged();
+ }
+}
+
+void QGstreamerVideoRenderer::handleFormatChange()
+{
+ //qDebug() << "Supported formats list has changed, reload video output";
+
+ if (m_videoSink)
+ gst_object_unref(GST_OBJECT(m_videoSink));
+
+ m_videoSink = 0;
+ emit sinkChanged();
+}
diff --git a/src/plugins/gstreamer/qgstreamervideorenderer.h b/src/plugins/gstreamer/qgstreamervideorenderer.h
new file mode 100644
index 000000000..b6c23ba51
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamervideorenderer.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QGSTREAMERVIDEORENDERER_H
+#define QGSTREAMERVIDEORENDERER_H
+
+#include <qvideorenderercontrol.h>
+#include "qvideosurfacegstsink.h"
+
+#include "qgstreamervideorendererinterface.h"
+
+QT_USE_NAMESPACE
+
+class QGstreamerVideoRenderer : public QVideoRendererControl, public QGstreamerVideoRendererInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QGstreamerVideoRendererInterface)
+public:
+ QGstreamerVideoRenderer(QObject *parent = 0);
+ virtual ~QGstreamerVideoRenderer();
+
+ QAbstractVideoSurface *surface() const;
+ void setSurface(QAbstractVideoSurface *surface);
+
+ GstElement *videoSink();
+ void precessNewStream() {}
+
+ bool isReady() const { return m_surface != 0; }
+
+signals:
+ void sinkChanged();
+ void readyChanged(bool);
+
+private slots:
+ void handleFormatChange();
+
+private:
+ QVideoSurfaceGstSink *m_videoSink;
+ QAbstractVideoSurface *m_surface;
+};
+
+#endif // QGSTREAMERVIDEORENDRER_H
diff --git a/src/plugins/gstreamer/qgstreamervideorendererinterface.cpp b/src/plugins/gstreamer/qgstreamervideorendererinterface.cpp
new file mode 100644
index 000000000..b8358ba1c
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamervideorendererinterface.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamervideorendererinterface.h"
+
+QGstreamerVideoRendererInterface::~QGstreamerVideoRendererInterface()
+{
+}
diff --git a/src/plugins/gstreamer/qgstreamervideorendererinterface.h b/src/plugins/gstreamer/qgstreamervideorendererinterface.h
new file mode 100644
index 000000000..08b046d9b
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamervideorendererinterface.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERVIDEOOUTPUTCONTROL_H
+#define QGSTREAMERVIDEOOUTPUTCONTROL_H
+
+#include <gst/gst.h>
+
+#include <QtCore/qobject.h>
+
+class QGstreamerVideoRendererInterface
+{
+public:
+ virtual ~QGstreamerVideoRendererInterface();
+ virtual GstElement *videoSink() = 0;
+ virtual void precessNewStream() {}
+
+ //stopRenderer() is called when the renderer element is stopped.
+ //it can be reimplemented when video renderer can't detect
+ //changes to NULL state but has to free video resources.
+ virtual void stopRenderer() {}
+
+ //the video output is configured, usually after the first paint event
+ //(winId is known,
+ virtual bool isReady() const { return true; }
+
+ //video renderer may handle video sink specific gstreamer messages.
+ virtual void handleBusMessage(GstMessage*) {};
+ virtual void handleSyncMessage(GstMessage*) {};
+
+ //signals:
+ //void sinkChanged();
+ //void readyChanged(bool);
+};
+
+#define QGstreamerVideoRendererInterface_iid "com.nokia.Qt.QGstreamerVideoRendererInterface/1.0"
+QT_BEGIN_NAMESPACE
+Q_DECLARE_INTERFACE(QGstreamerVideoRendererInterface, QGstreamerVideoRendererInterface_iid)
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/gstreamer/qgstreamervideowidget.cpp b/src/plugins/gstreamer/qgstreamervideowidget.cpp
new file mode 100644
index 000000000..38fa5ba8e
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamervideowidget.cpp
@@ -0,0 +1,331 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamervideowidget.h"
+#include "qgstutils.h"
+
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/qapplication.h>
+#include <QtGui/qpainter.h>
+
+#ifdef Q_WS_X11
+# include <X11/Xlib.h>
+#endif
+#include <gst/gst.h>
+#include <gst/interfaces/xoverlay.h>
+#include <gst/interfaces/propertyprobe.h>
+
+class QGstreamerVideoWidget : public QWidget
+{
+public:
+ QGstreamerVideoWidget(QWidget *parent = 0)
+ :QWidget(parent)
+ {
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ QPalette palette;
+ palette.setColor(QPalette::Background, Qt::black);
+ setPalette(palette);
+ }
+
+ virtual ~QGstreamerVideoWidget() {}
+
+ QSize sizeHint() const
+ {
+ return m_nativeSize;
+ }
+
+ void setNativeSize( const QSize &size)
+ {
+ if (size != m_nativeSize) {
+ m_nativeSize = size;
+ if (size.isEmpty())
+ setMinimumSize(0,0);
+ else
+ setMinimumSize(160,120);
+
+ updateGeometry();
+ }
+ }
+
+protected:
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter painter(this);
+ painter.fillRect(rect(), palette().background());
+ }
+
+ QSize m_nativeSize;
+};
+
+QGstreamerVideoWidgetControl::QGstreamerVideoWidgetControl(QObject *parent)
+ : QVideoWidgetControl(parent)
+ , m_videoSink(0)
+ , m_widget(0)
+ , m_fullScreen(false)
+{
+}
+
+QGstreamerVideoWidgetControl::~QGstreamerVideoWidgetControl()
+{
+ if (m_videoSink)
+ gst_object_unref(GST_OBJECT(m_videoSink));
+
+ delete m_widget;
+}
+
+void QGstreamerVideoWidgetControl::createVideoWidget()
+{
+ if (m_widget)
+ return;
+
+ m_widget = new QGstreamerVideoWidget;
+
+ m_widget->installEventFilter(this);
+ m_windowId = m_widget->winId();
+
+ m_videoSink = gst_element_factory_make ("xvimagesink", NULL);
+ if (m_videoSink) {
+ // Check if the xv sink is usable
+ if (gst_element_set_state(m_videoSink, GST_STATE_READY) != GST_STATE_CHANGE_SUCCESS) {
+ gst_object_unref(GST_OBJECT(m_videoSink));
+ m_videoSink = 0;
+ } else {
+ gst_element_set_state(m_videoSink, GST_STATE_NULL);
+
+ g_object_set(G_OBJECT(m_videoSink), "force-aspect-ratio", 1, (const char*)NULL);
+#ifdef Q_WS_MAEMO_5
+ //the overlay xvideo adapter fails to switch winId,
+ //use "SGX Textured Video" adapter instead
+ g_object_set(G_OBJECT(m_videoSink), "device", "1", NULL);
+#endif
+ }
+ }
+
+ if (!m_videoSink)
+ m_videoSink = gst_element_factory_make ("ximagesink", NULL);
+
+ gst_object_ref (GST_OBJECT (m_videoSink)); //Take ownership
+ gst_object_sink (GST_OBJECT (m_videoSink));
+
+
+}
+
+GstElement *QGstreamerVideoWidgetControl::videoSink()
+{
+ createVideoWidget();
+ return m_videoSink;
+}
+
+bool QGstreamerVideoWidgetControl::eventFilter(QObject *object, QEvent *e)
+{
+ if (m_widget && object == m_widget) {
+ if (e->type() == QEvent::ParentChange || e->type() == QEvent::Show) {
+ WId newWId = m_widget->winId();
+ if (newWId != m_windowId) {
+ m_windowId = newWId;
+ // Even if we have created a winId at this point, other X applications
+ // need to be aware of it.
+ QApplication::syncX();
+ setOverlay();
+ }
+ }
+
+ if (e->type() == QEvent::Show) {
+ // Setting these values ensures smooth resizing since it
+ // will prevent the system from clearing the background
+ m_widget->setAttribute(Qt::WA_NoSystemBackground, true);
+ m_widget->setAttribute(Qt::WA_PaintOnScreen, true);
+ } else if (e->type() == QEvent::Resize) {
+ // This is a workaround for missing background repaints
+ // when reducing window size
+ windowExposed();
+ }
+ }
+
+ return false;
+}
+
+void QGstreamerVideoWidgetControl::precessNewStream()
+{
+ setOverlay();
+ QMetaObject::invokeMethod(this, "updateNativeVideoSize", Qt::QueuedConnection);
+}
+
+void QGstreamerVideoWidgetControl::setOverlay()
+{
+ if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
+ gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), m_windowId);
+ }
+}
+
+void QGstreamerVideoWidgetControl::updateNativeVideoSize()
+{
+ if (m_videoSink) {
+ //find video native size to update video widget size hint
+ GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
+ GstCaps *caps = gst_pad_get_negotiated_caps(pad);
+
+ if (caps) {
+ m_widget->setNativeSize(QGstUtils::capsCorrectedResolution(caps));
+ gst_caps_unref(caps);
+ }
+ } else {
+ if (m_widget)
+ m_widget->setNativeSize(QSize());
+ }
+}
+
+
+void QGstreamerVideoWidgetControl::windowExposed()
+{
+ if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink))
+ gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink));
+}
+
+QWidget *QGstreamerVideoWidgetControl::videoWidget()
+{
+ createVideoWidget();
+ return m_widget;
+}
+
+Qt::AspectRatioMode QGstreamerVideoWidgetControl::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void QGstreamerVideoWidgetControl::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ if (m_videoSink) {
+ g_object_set(G_OBJECT(m_videoSink),
+ "force-aspect-ratio",
+ (mode == Qt::KeepAspectRatio),
+ (const char*)NULL);
+ }
+
+ m_aspectRatioMode = mode;
+}
+
+bool QGstreamerVideoWidgetControl::isFullScreen() const
+{
+ return m_fullScreen;
+}
+
+void QGstreamerVideoWidgetControl::setFullScreen(bool fullScreen)
+{
+ emit fullScreenChanged(m_fullScreen = fullScreen);
+}
+
+int QGstreamerVideoWidgetControl::brightness() const
+{
+ int brightness = 0;
+
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "brightness"))
+ g_object_get(G_OBJECT(m_videoSink), "brightness", &brightness, NULL);
+
+ return brightness / 10;
+}
+
+void QGstreamerVideoWidgetControl::setBrightness(int brightness)
+{
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "brightness")) {
+ g_object_set(G_OBJECT(m_videoSink), "brightness", brightness * 10, NULL);
+
+ emit brightnessChanged(brightness);
+ }
+}
+
+int QGstreamerVideoWidgetControl::contrast() const
+{
+ int contrast = 0;
+
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "contrast"))
+ g_object_get(G_OBJECT(m_videoSink), "contrast", &contrast, NULL);
+
+ return contrast / 10;
+}
+
+void QGstreamerVideoWidgetControl::setContrast(int contrast)
+{
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "contrast")) {
+ g_object_set(G_OBJECT(m_videoSink), "contrast", contrast * 10, NULL);
+
+ emit contrastChanged(contrast);
+ }
+}
+
+int QGstreamerVideoWidgetControl::hue() const
+{
+ int hue = 0;
+
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "hue"))
+ g_object_get(G_OBJECT(m_videoSink), "hue", &hue, NULL);
+
+ return hue / 10;
+}
+
+void QGstreamerVideoWidgetControl::setHue(int hue)
+{
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "hue")) {
+ g_object_set(G_OBJECT(m_videoSink), "hue", hue * 10, NULL);
+
+ emit hueChanged(hue);
+ }
+}
+
+int QGstreamerVideoWidgetControl::saturation() const
+{
+ int saturation = 0;
+
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "saturation"))
+ g_object_get(G_OBJECT(m_videoSink), "saturation", &saturation, NULL);
+
+ return saturation / 10;
+}
+
+void QGstreamerVideoWidgetControl::setSaturation(int saturation)
+{
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "saturation")) {
+ g_object_set(G_OBJECT(m_videoSink), "saturation", saturation * 10, NULL);
+
+ emit saturationChanged(saturation);
+ }
+}
diff --git a/src/plugins/gstreamer/qgstreamervideowidget.h b/src/plugins/gstreamer/qgstreamervideowidget.h
new file mode 100644
index 000000000..3342351d1
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamervideowidget.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERVIDEOWIDGET_H
+#define QGSTREAMERVIDEOWIDGET_H
+
+#include <qvideowidgetcontrol.h>
+
+#include "qgstreamervideorendererinterface.h"
+
+QT_USE_NAMESPACE
+
+class QGstreamerVideoWidget;
+
+class QGstreamerVideoWidgetControl
+ : public QVideoWidgetControl
+ , public QGstreamerVideoRendererInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QGstreamerVideoRendererInterface)
+public:
+ QGstreamerVideoWidgetControl(QObject *parent = 0);
+ virtual ~QGstreamerVideoWidgetControl();
+
+ GstElement *videoSink();
+ void precessNewStream();
+
+ QWidget *videoWidget();
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ bool isFullScreen() const;
+ void setFullScreen(bool fullScreen);
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ void setOverlay();
+
+ bool eventFilter(QObject *object, QEvent *event);
+
+public slots:
+ void updateNativeVideoSize();
+
+signals:
+ void sinkChanged();
+ void readyChanged(bool);
+
+private:
+ void createVideoWidget();
+ void windowExposed();
+
+ GstElement *m_videoSink;
+ QGstreamerVideoWidget *m_widget;
+ WId m_windowId;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ bool m_fullScreen;
+};
+
+#endif // QGSTREAMERVIDEOWIDGET_H
diff --git a/src/plugins/gstreamer/qgstreamervideowindow.cpp b/src/plugins/gstreamer/qgstreamervideowindow.cpp
new file mode 100644
index 000000000..565000176
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamervideowindow.cpp
@@ -0,0 +1,342 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstreamervideowindow.h"
+#include "qgstutils.h"
+
+#include <QtCore/qdebug.h>
+
+#include <gst/gst.h>
+#include <gst/interfaces/xoverlay.h>
+#include <gst/interfaces/propertyprobe.h>
+
+
+#ifndef QT_NO_XVIDEO
+
+/*
+ QGstreamerVideoWindow is similar to QGstreamerVideoOverlay,
+ but uses xvimagesink like gstreamer element instead of QX11VideoSurface.
+
+ This allows to use the accelerated elements if available on the target platform,
+ but requires at least 0.10.29 gstreamer version
+ with gst_x_overlay_set_render_rectangle to set display rect.
+*/
+
+QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elementName)
+ : QVideoWindowControl(parent)
+ , m_videoSink(0)
+ , m_windowId(0)
+ , m_aspectRatioMode(Qt::KeepAspectRatio)
+ , m_fullScreen(false)
+ , m_colorKey(QColor::Invalid)
+{
+ if (elementName)
+ m_videoSink = gst_element_factory_make(elementName, NULL);
+ else
+ m_videoSink = gst_element_factory_make("xvimagesink", NULL);
+
+ if (m_videoSink) {
+ gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership
+ gst_object_sink(GST_OBJECT(m_videoSink));
+
+ GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
+ m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this);
+ }
+}
+
+QGstreamerVideoWindow::~QGstreamerVideoWindow()
+{
+ if (m_videoSink)
+ gst_object_unref(GST_OBJECT(m_videoSink));
+}
+
+WId QGstreamerVideoWindow::winId() const
+{
+ return m_windowId;
+}
+
+void QGstreamerVideoWindow::setWinId(WId id)
+{
+ if (m_windowId == id)
+ return;
+
+ qDebug() << Q_FUNC_INFO << id;
+
+ WId oldId = m_windowId;
+
+ m_windowId = id;
+
+ if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
+ gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), m_windowId);
+ }
+
+ if (!oldId)
+ emit readyChanged(true);
+
+ if (!id)
+ emit readyChanged(false);
+}
+
+void QGstreamerVideoWindow::precessNewStream()
+{
+ if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
+ gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), m_windowId);
+
+ GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
+ m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this);
+ }
+}
+
+QRect QGstreamerVideoWindow::displayRect() const
+{
+ return m_displayRect;
+}
+
+void QGstreamerVideoWindow::setDisplayRect(const QRect &rect)
+{
+ m_displayRect = rect;
+
+ if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
+#if GST_VERSION_MICRO >= 29
+ if (m_displayRect.isEmpty())
+ gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink), -1, -1, -1, -1);
+ else
+ gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink),
+ m_displayRect.x(),
+ m_displayRect.y(),
+ m_displayRect.width(),
+ m_displayRect.height());
+ repaint();
+#endif
+ }
+}
+
+Qt::AspectRatioMode QGstreamerVideoWindow::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void QGstreamerVideoWindow::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_aspectRatioMode = mode;
+
+ if (m_videoSink) {
+ g_object_set(G_OBJECT(m_videoSink),
+ "force-aspect-ratio",
+ (m_aspectRatioMode == Qt::KeepAspectRatio),
+ (const char*)NULL);
+ }
+}
+
+void QGstreamerVideoWindow::repaint()
+{
+ if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
+ //don't call gst_x_overlay_expose if the sink is in null state
+ GstState state = GST_STATE_NULL;
+ GstStateChangeReturn res = gst_element_get_state(m_videoSink, &state, NULL, 1000000);
+ if (res != GST_STATE_CHANGE_FAILURE && state != GST_STATE_NULL) {
+ gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink));
+ }
+ }
+}
+
+QColor QGstreamerVideoWindow::colorKey() const
+{
+ if (!m_colorKey.isValid()) {
+ gint colorkey = 0;
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "colorkey"))
+ g_object_get(G_OBJECT(m_videoSink), "colorkey", &colorkey, NULL);
+
+ if (colorkey > 0)
+ m_colorKey.setRgb(colorkey);
+ }
+
+ return m_colorKey;
+}
+
+void QGstreamerVideoWindow::setColorKey(const QColor &color)
+{
+ m_colorKey = color;
+
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "colorkey"))
+ g_object_set(G_OBJECT(m_videoSink), "colorkey", color.rgba(), NULL);
+}
+
+bool QGstreamerVideoWindow::autopaintColorKey() const
+{
+ bool enabled = true;
+
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "autopaint-colorkey"))
+ g_object_get(G_OBJECT(m_videoSink), "autopaint-colorkey", &enabled, NULL);
+
+ return enabled;
+}
+
+void QGstreamerVideoWindow::setAutopaintColorKey(bool enabled)
+{
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "autopaint-colorkey"))
+ g_object_set(G_OBJECT(m_videoSink), "autopaint-colorkey", enabled, NULL);
+}
+
+int QGstreamerVideoWindow::brightness() const
+{
+ int brightness = 0;
+
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "brightness"))
+ g_object_get(G_OBJECT(m_videoSink), "brightness", &brightness, NULL);
+
+ return brightness / 10;
+}
+
+void QGstreamerVideoWindow::setBrightness(int brightness)
+{
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "brightness")) {
+ g_object_set(G_OBJECT(m_videoSink), "brightness", brightness * 10, NULL);
+
+ emit brightnessChanged(brightness);
+ }
+}
+
+int QGstreamerVideoWindow::contrast() const
+{
+ int contrast = 0;
+
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "contrast"))
+ g_object_get(G_OBJECT(m_videoSink), "contrast", &contrast, NULL);
+
+ return contrast / 10;
+}
+
+void QGstreamerVideoWindow::setContrast(int contrast)
+{
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "contrast")) {
+ g_object_set(G_OBJECT(m_videoSink), "contrast", contrast * 10, NULL);
+
+ emit contrastChanged(contrast);
+ }
+}
+
+int QGstreamerVideoWindow::hue() const
+{
+ int hue = 0;
+
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "hue"))
+ g_object_get(G_OBJECT(m_videoSink), "hue", &hue, NULL);
+
+ return hue / 10;
+}
+
+void QGstreamerVideoWindow::setHue(int hue)
+{
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "hue")) {
+ g_object_set(G_OBJECT(m_videoSink), "hue", hue * 10, NULL);
+
+ emit hueChanged(hue);
+ }
+}
+
+int QGstreamerVideoWindow::saturation() const
+{
+ int saturation = 0;
+
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "saturation"))
+ g_object_get(G_OBJECT(m_videoSink), "saturation", &saturation, NULL);
+
+ return saturation / 10;
+}
+
+void QGstreamerVideoWindow::setSaturation(int saturation)
+{
+ if (m_videoSink && g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "saturation")) {
+ g_object_set(G_OBJECT(m_videoSink), "saturation", saturation * 10, NULL);
+
+ emit saturationChanged(saturation);
+ }
+}
+
+bool QGstreamerVideoWindow::isFullScreen() const
+{
+ return m_fullScreen;
+}
+
+void QGstreamerVideoWindow::setFullScreen(bool fullScreen)
+{
+ emit fullScreenChanged(m_fullScreen = fullScreen);
+}
+
+QSize QGstreamerVideoWindow::nativeSize() const
+{
+ return m_nativeSize;
+}
+
+void QGstreamerVideoWindow::padBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data)
+{
+ QGstreamerVideoWindow *control = reinterpret_cast<QGstreamerVideoWindow*>(user_data);
+ QMetaObject::invokeMethod(control, "updateNativeVideoSize", Qt::QueuedConnection);
+ gst_pad_remove_buffer_probe(pad, control->m_bufferProbeId);
+}
+
+void QGstreamerVideoWindow::updateNativeVideoSize()
+{
+ const QSize oldSize = m_nativeSize;
+ m_nativeSize = QSize();
+
+ if (m_videoSink) {
+ //find video native size to update video widget size hint
+ GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink");
+ GstCaps *caps = gst_pad_get_negotiated_caps(pad);
+
+ if (caps) {
+ m_nativeSize = QGstUtils::capsCorrectedResolution(caps);
+ gst_caps_unref(caps);
+ }
+ }
+
+ if (m_nativeSize != oldSize)
+ emit nativeSizeChanged();
+}
+
+GstElement *QGstreamerVideoWindow::videoSink()
+{
+ return m_videoSink;
+}
+
+#endif //QT_NO_XVIDEO
diff --git a/src/plugins/gstreamer/qgstreamervideowindow.h b/src/plugins/gstreamer/qgstreamervideowindow.h
new file mode 100644
index 000000000..e2229ae9e
--- /dev/null
+++ b/src/plugins/gstreamer/qgstreamervideowindow.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTREAMERVIDEOWINDOW_H
+#define QGSTREAMERVIDEOWINDOW_H
+
+#include <qvideowindowcontrol.h>
+
+#include "qgstreamervideorendererinterface.h"
+
+QT_BEGIN_NAMESPACE
+class QAbstractVideoSurface;
+QT_END_NAMESPACE
+class QX11VideoSurface;
+
+#if defined(Q_WS_X11) && !defined(QT_NO_XVIDEO)
+
+QT_USE_NAMESPACE
+
+class QGstreamerVideoWindow : public QVideoWindowControl, public QGstreamerVideoRendererInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QGstreamerVideoRendererInterface)
+ Q_PROPERTY(QColor colorKey READ colorKey WRITE setColorKey)
+ Q_PROPERTY(bool autopaintColorKey READ autopaintColorKey WRITE setAutopaintColorKey)
+public:
+ QGstreamerVideoWindow(QObject *parent = 0, const char *elementName = 0);
+ ~QGstreamerVideoWindow();
+
+ WId winId() const;
+ void setWinId(WId id);
+
+ QRect displayRect() const;
+ void setDisplayRect(const QRect &rect);
+
+ bool isFullScreen() const;
+ void setFullScreen(bool fullScreen);
+
+ QSize nativeSize() const;
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ QColor colorKey() const;
+ void setColorKey(const QColor &);
+
+ bool autopaintColorKey() const;
+ void setAutopaintColorKey(bool);
+
+ void repaint();
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ QAbstractVideoSurface *surface() const;
+
+ GstElement *videoSink();
+
+ void precessNewStream();
+ bool isReady() const { return m_windowId != 0; }
+
+signals:
+ void sinkChanged();
+ void readyChanged(bool);
+
+private slots:
+ void updateNativeVideoSize();
+
+private:
+ static void padBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data);
+
+ GstElement *m_videoSink;
+ WId m_windowId;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QRect m_displayRect;
+ bool m_fullScreen;
+ QSize m_nativeSize;
+ mutable QColor m_colorKey;
+ int m_bufferProbeId;
+};
+
+#endif //QT_NO_XVIDEO
+
+#endif
diff --git a/src/plugins/gstreamer/qgstutils.cpp b/src/plugins/gstreamer/qgstutils.cpp
new file mode 100644
index 000000000..a0f2a9832
--- /dev/null
+++ b/src/plugins/gstreamer/qgstutils.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qgstutils.h"
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qsize.h>
+
+//internal
+static void addTagToMap(const GstTagList *list,
+ const gchar *tag,
+ gpointer user_data)
+{
+ QMap<QByteArray, QVariant> *map = reinterpret_cast<QMap<QByteArray, QVariant>* >(user_data);
+
+ GValue val;
+ val.g_type = 0;
+ gst_tag_list_copy_value(&val,list,tag);
+
+ switch( G_VALUE_TYPE(&val) ) {
+ case G_TYPE_STRING:
+ {
+ const gchar *str_value = g_value_get_string(&val);
+ map->insert(QByteArray(tag), QString::fromUtf8(str_value));
+ break;
+ }
+ case G_TYPE_INT:
+ map->insert(QByteArray(tag), g_value_get_int(&val));
+ break;
+ case G_TYPE_UINT:
+ map->insert(QByteArray(tag), g_value_get_uint(&val));
+ break;
+ case G_TYPE_LONG:
+ map->insert(QByteArray(tag), qint64(g_value_get_long(&val)));
+ break;
+ case G_TYPE_BOOLEAN:
+ map->insert(QByteArray(tag), g_value_get_boolean(&val));
+ break;
+ case G_TYPE_CHAR:
+ map->insert(QByteArray(tag), g_value_get_char(&val));
+ break;
+ case G_TYPE_DOUBLE:
+ map->insert(QByteArray(tag), g_value_get_double(&val));
+ break;
+ default:
+ // GST_TYPE_DATE is a function, not a constant, so pull it out of the switch
+ if (G_VALUE_TYPE(&val) == GST_TYPE_DATE) {
+ const GDate *date = gst_value_get_date(&val);
+ if (g_date_valid(date)) {
+ int year = g_date_get_year(date);
+ int month = g_date_get_month(date);
+ int day = g_date_get_day(date);
+ map->insert(QByteArray(tag), QDate(year,month,day));
+ if (!map->contains("year"))
+ map->insert("year", year);
+ }
+ } else if (G_VALUE_TYPE(&val) == GST_TYPE_FRACTION) {
+ int nom = gst_value_get_fraction_numerator(&val);
+ int denom = gst_value_get_fraction_denominator(&val);
+
+ if (denom > 0) {
+ map->insert(QByteArray(tag), double(nom)/denom);
+ }
+ }
+ break;
+ }
+
+ g_value_unset(&val);
+}
+
+/*!
+ Convert GstTagList structure to QMap<QByteArray, QVariant>.
+
+ Mapping to int, bool, char, string, fractions and date are supported.
+ Fraction values are converted to doubles.
+*/
+QMap<QByteArray, QVariant> QGstUtils::gstTagListToMap(const GstTagList *tags)
+{
+ QMap<QByteArray, QVariant> res;
+ gst_tag_list_foreach(tags, addTagToMap, &res);
+
+ return res;
+}
+
+/*!
+ Returns resolution of \a caps.
+ If caps doesn't have a valid size, and ampty QSize is returned.
+*/
+QSize QGstUtils::capsResolution(const GstCaps *caps)
+{
+ QSize size;
+
+ if (caps) {
+ const GstStructure *structure = gst_caps_get_structure(caps, 0);
+ gst_structure_get_int(structure, "width", &size.rwidth());
+ gst_structure_get_int(structure, "height", &size.rheight());
+ }
+
+ return size;
+}
+
+/*!
+ Returns aspect ratio corrected resolution of \a caps.
+ If caps doesn't have a valid size, and ampty QSize is returned.
+*/
+QSize QGstUtils::capsCorrectedResolution(const GstCaps *caps)
+{
+ QSize size;
+
+ if (caps) {
+ const GstStructure *structure = gst_caps_get_structure(caps, 0);
+ gst_structure_get_int(structure, "width", &size.rwidth());
+ gst_structure_get_int(structure, "height", &size.rheight());
+
+ gint aspectNum = 0;
+ gint aspectDenum = 0;
+ if (!size.isEmpty() && gst_structure_get_fraction(
+ structure, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) {
+ if (aspectDenum > 0)
+ size.setWidth(qRound(size.width()*aspectNum/aspectDenum));
+ }
+ }
+
+ return size;
+}
diff --git a/src/plugins/gstreamer/qgstutils.h b/src/plugins/gstreamer/qgstutils.h
new file mode 100644
index 000000000..396b32b98
--- /dev/null
+++ b/src/plugins/gstreamer/qgstutils.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTUTILS_H
+#define QGSTUTILS_H
+
+#include <QtCore/qmap.h>
+#include <gst/gst.h>
+
+class QSize;
+class QVariant;
+class QByteArray;
+
+namespace QGstUtils {
+ QMap<QByteArray, QVariant> gstTagListToMap(const GstTagList *list);
+
+ QSize capsResolution(const GstCaps *caps);
+ QSize capsCorrectedResolution(const GstCaps *caps);
+}
+
+#endif
diff --git a/src/plugins/gstreamer/qgstvideobuffer.cpp b/src/plugins/gstreamer/qgstvideobuffer.cpp
new file mode 100644
index 000000000..4ea6a7004
--- /dev/null
+++ b/src/plugins/gstreamer/qgstvideobuffer.cpp
@@ -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$
+** 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 "qgstvideobuffer.h"
+
+
+QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine)
+ : QAbstractVideoBuffer(NoHandle)
+ , m_buffer(buffer)
+ , m_bytesPerLine(bytesPerLine)
+ , m_mode(NotMapped)
+{
+ gst_buffer_ref(m_buffer);
+}
+
+QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine,
+ QGstVideoBuffer::HandleType handleType,
+ const QVariant &handle)
+ : QAbstractVideoBuffer(handleType)
+ , m_buffer(buffer)
+ , m_bytesPerLine(bytesPerLine)
+ , m_mode(NotMapped)
+ , m_handle(handle)
+{
+ gst_buffer_ref(m_buffer);
+}
+
+QGstVideoBuffer::~QGstVideoBuffer()
+{
+ gst_buffer_unref(m_buffer);
+}
+
+
+QAbstractVideoBuffer::MapMode QGstVideoBuffer::mapMode() const
+{
+ return m_mode;
+}
+
+uchar *QGstVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine)
+{
+ if (mode != NotMapped && m_mode == NotMapped) {
+ if (numBytes)
+ *numBytes = m_buffer->size;
+
+ if (bytesPerLine)
+ *bytesPerLine = m_bytesPerLine;
+
+ m_mode = mode;
+
+ return m_buffer->data;
+ } else {
+ return 0;
+ }
+}
+void QGstVideoBuffer::unmap()
+{
+ m_mode = NotMapped;
+}
+
diff --git a/src/plugins/gstreamer/qgstvideobuffer.h b/src/plugins/gstreamer/qgstvideobuffer.h
new file mode 100644
index 000000000..8d5a36e53
--- /dev/null
+++ b/src/plugins/gstreamer/qgstvideobuffer.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTVIDEOBUFFER_H
+#define QGSTVIDEOBUFFER_H
+
+#include <qabstractvideobuffer.h>
+#include <QtCore/qvariant.h>
+
+#include <gst/gst.h>
+
+class QGstVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine);
+ QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine,
+ HandleType handleType, const QVariant &handle);
+ ~QGstVideoBuffer();
+
+ MapMode mapMode() const;
+
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine);
+ void unmap();
+
+ QVariant handle() const { return m_handle; }
+private:
+ GstBuffer *m_buffer;
+ int m_bytesPerLine;
+ MapMode m_mode;
+ QVariant m_handle;
+};
+
+
+#endif
diff --git a/src/plugins/gstreamer/qgstxvimagebuffer.cpp b/src/plugins/gstreamer/qgstxvimagebuffer.cpp
new file mode 100644
index 000000000..393456291
--- /dev/null
+++ b/src/plugins/gstreamer/qgstxvimagebuffer.cpp
@@ -0,0 +1,311 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qdebug.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qvariant.h>
+#include <QtGui/qx11info_x11.h>
+
+#include "qgstxvimagebuffer.h"
+#include "qvideosurfacegstsink.h"
+#include "qgstvideobuffer.h"
+
+#ifndef QT_NO_XVIDEO
+
+GstBufferClass *QGstXvImageBuffer::parent_class = NULL;
+
+GType QGstXvImageBuffer::get_type(void)
+{
+ static GType buffer_type = 0;
+
+ if (buffer_type == 0) {
+ static const GTypeInfo buffer_info = {
+ sizeof (GstBufferClass),
+ NULL,
+ NULL,
+ QGstXvImageBuffer::class_init,
+ NULL,
+ NULL,
+ sizeof(QGstXvImageBuffer),
+ 0,
+ (GInstanceInitFunc)QGstXvImageBuffer::buffer_init,
+ NULL
+ };
+ buffer_type = g_type_register_static(GST_TYPE_BUFFER,
+ "QGstXvImageBuffer", &buffer_info, GTypeFlags(0));
+ }
+ return buffer_type;
+}
+
+void QGstXvImageBuffer::class_init(gpointer g_class, gpointer class_data)
+{
+ Q_UNUSED(class_data);
+ GST_MINI_OBJECT_CLASS(g_class)->finalize =
+ (GstMiniObjectFinalizeFunction)buffer_finalize;
+ parent_class = (GstBufferClass*)g_type_class_peek_parent(g_class);
+}
+
+void QGstXvImageBuffer::buffer_init(QGstXvImageBuffer *xvImage, gpointer g_class)
+{
+ Q_UNUSED(g_class);
+ xvImage->pool = 0;
+ xvImage->shmInfo.shmaddr = ((char *) -1);
+ xvImage->shmInfo.shmid = -1;
+ xvImage->markedForDeletion = false;
+}
+
+void QGstXvImageBuffer::buffer_finalize(QGstXvImageBuffer * xvImage)
+{
+ if (xvImage->pool) {
+ if (xvImage->markedForDeletion)
+ xvImage->pool->destroyBuffer(xvImage);
+ else
+ xvImage->pool->recycleBuffer(xvImage);
+ }
+}
+
+
+QGstXvImageBufferPool::QGstXvImageBufferPool(QObject *parent)
+ :QObject(parent)
+{
+ m_threadId = QThread::currentThreadId();
+}
+
+QGstXvImageBufferPool::~QGstXvImageBufferPool()
+{
+}
+
+bool QGstXvImageBufferPool::isFormatSupported(const QVideoSurfaceFormat &surfaceFormat) const
+{
+ bool ok = true;
+ surfaceFormat.property("portId").toULongLong(&ok);
+ if (!ok)
+ return false;
+
+ int xvFormatId = surfaceFormat.property("xvFormatId").toInt(&ok);
+ if (!ok || xvFormatId < 0)
+ return false;
+
+ int dataSize = surfaceFormat.property("dataSize").toInt(&ok);
+ if (!ok || dataSize<=0)
+ return false;
+
+ return true;
+}
+
+GType QGstXvImageBufferPool::bufferType() const
+{
+ return QGstXvImageBuffer::get_type();
+}
+
+GstBuffer *QGstXvImageBufferPool::takeBuffer(
+ const QVideoSurfaceFormat &format, GstCaps *caps)
+{
+ m_poolMutex.lock();
+
+ m_caps = caps;
+ if (format != m_format) {
+ doClear();
+ m_format = format;
+ }
+
+
+ if (m_pool.isEmpty()) {
+ //qDebug() << "QGstXvImageBufferPool::takeBuffer: no buffer available, allocate the new one" << QThread::currentThreadId() << m_threadId;
+ if (QThread::currentThreadId() == m_threadId) {
+ doAlloc();
+ } else {
+ QMetaObject::invokeMethod(this, "queuedAlloc", Qt::QueuedConnection);
+ m_allocWaitCondition.wait(&m_poolMutex, 300);
+ }
+ }
+ QGstXvImageBuffer *res = 0;
+
+ if (!m_pool.isEmpty()) {
+ res = m_pool.takeLast();
+ }
+
+ m_poolMutex.unlock();
+
+ return GST_BUFFER(res);
+}
+
+QAbstractVideoBuffer::HandleType QGstXvImageBufferPool::handleType() const
+{
+ return QAbstractVideoBuffer::XvShmImageHandle;
+}
+
+QAbstractVideoBuffer *QGstXvImageBufferPool::prepareVideoBuffer(GstBuffer *buffer, int bytesPerLine)
+{
+ QGstXvImageBuffer *xvBuffer = reinterpret_cast<QGstXvImageBuffer *>(buffer);
+ QVariant handle = QVariant::fromValue(xvBuffer->xvImage);
+ return new QGstVideoBuffer(buffer, bytesPerLine, QAbstractVideoBuffer::XvShmImageHandle, handle);
+}
+
+void QGstXvImageBufferPool::queuedAlloc()
+{
+ QMutexLocker lock(&m_poolMutex);
+ doAlloc();
+ m_allocWaitCondition.wakeOne();
+}
+
+void QGstXvImageBufferPool::doAlloc()
+{
+ //should be always called from the main thread with m_poolMutex locked
+ //Q_ASSERT(QThread::currentThread() == thread());
+
+ XSync(QX11Info::display(), false);
+
+ QGstXvImageBuffer *xvBuffer = (QGstXvImageBuffer *)gst_mini_object_new(QGstXvImageBuffer::get_type());
+
+ quint64 portId = m_format.property("portId").toULongLong();
+ int xvFormatId = m_format.property("xvFormatId").toInt();
+
+ xvBuffer->xvImage = XvShmCreateImage(
+ QX11Info::display(),
+ portId,
+ xvFormatId,
+ 0,
+ m_format.frameWidth(),
+ m_format.frameHeight(),
+ &xvBuffer->shmInfo
+ );
+
+ if (!xvBuffer->xvImage) {
+ qWarning() << "QGstXvImageBufferPool: XvShmCreateImage failed";
+ return;
+ }
+
+ XSync(QX11Info::display(), false);
+
+ xvBuffer->shmInfo.shmid = shmget(IPC_PRIVATE, xvBuffer->xvImage->data_size, IPC_CREAT | 0777);
+ xvBuffer->shmInfo.shmaddr = xvBuffer->xvImage->data = (char*)shmat(xvBuffer->shmInfo.shmid, 0, 0);
+ xvBuffer->shmInfo.readOnly = False;
+
+ if (!XShmAttach(QX11Info::display(), &xvBuffer->shmInfo)) {
+ qWarning() << "QGstXvImageBufferPool: XShmAttach failed";
+ return;
+ }
+
+ XSync(QX11Info::display(), false);
+
+ shmctl (xvBuffer->shmInfo.shmid, IPC_RMID, NULL);
+
+ xvBuffer->pool = this;
+ GST_MINI_OBJECT_CAST(xvBuffer)->flags = 0;
+ gst_buffer_set_caps(GST_BUFFER_CAST(xvBuffer), m_caps);
+ GST_BUFFER_DATA(xvBuffer) = (uchar*)xvBuffer->xvImage->data;
+ GST_BUFFER_SIZE(xvBuffer) = xvBuffer->xvImage->data_size;
+
+ m_allBuffers.append(xvBuffer);
+ m_pool.append(xvBuffer);
+
+ XSync(QX11Info::display(), false);
+}
+
+
+void QGstXvImageBufferPool::clear()
+{
+ QMutexLocker lock(&m_poolMutex);
+ doClear();
+}
+
+void QGstXvImageBufferPool::doClear()
+{
+ foreach (QGstXvImageBuffer *xvBuffer, m_allBuffers) {
+ xvBuffer->markedForDeletion = true;
+ }
+ m_allBuffers.clear();
+
+ foreach (QGstXvImageBuffer *xvBuffer, m_pool) {
+ gst_buffer_unref(GST_BUFFER(xvBuffer));
+ }
+ m_pool.clear();
+
+ m_format = QVideoSurfaceFormat();
+}
+
+void QGstXvImageBufferPool::queuedDestroy()
+{
+ QMutexLocker lock(&m_destroyMutex);
+
+ XSync(QX11Info::display(), false);
+
+ foreach(XvShmImage xvImage, m_imagesToDestroy) {
+ if (xvImage.shmInfo.shmaddr != ((void *) -1)) {
+ XShmDetach(QX11Info::display(), &xvImage.shmInfo);
+ XSync(QX11Info::display(), false);
+
+ shmdt(xvImage.shmInfo.shmaddr);
+ }
+
+ if (xvImage.xvImage)
+ XFree(xvImage.xvImage);
+ }
+
+ m_imagesToDestroy.clear();
+
+ XSync(QX11Info::display(), false);
+}
+
+void QGstXvImageBufferPool::recycleBuffer(QGstXvImageBuffer *xvBuffer)
+{
+ QMutexLocker lock(&m_poolMutex);
+ gst_buffer_ref(GST_BUFFER_CAST(xvBuffer));
+ m_pool.append(xvBuffer);
+}
+
+void QGstXvImageBufferPool::destroyBuffer(QGstXvImageBuffer *xvBuffer)
+{
+ XvShmImage imageToDestroy;
+ imageToDestroy.xvImage = xvBuffer->xvImage;
+ imageToDestroy.shmInfo = xvBuffer->shmInfo;
+
+ m_destroyMutex.lock();
+ m_imagesToDestroy.append(imageToDestroy);
+ m_destroyMutex.unlock();
+
+ if (m_imagesToDestroy.size() == 1)
+ QMetaObject::invokeMethod(this, "queuedDestroy", Qt::QueuedConnection);
+}
+
+#endif //QT_NO_XVIDEO
+
diff --git a/src/plugins/gstreamer/qgstxvimagebuffer.h b/src/plugins/gstreamer/qgstxvimagebuffer.h
new file mode 100644
index 000000000..2ab5ea03b
--- /dev/null
+++ b/src/plugins/gstreamer/qgstxvimagebuffer.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** 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$
+** 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 QGSTXVIMAGEBUFFER_H
+#define QGSTXVIMAGEBUFFER_H
+
+#include <qabstractvideobuffer.h>
+#include <qvideosurfaceformat.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qwaitcondition.h>
+#include <QtCore/qqueue.h>
+
+#ifndef QT_NO_XVIDEO
+
+#include <X11/Xlib.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/extensions/XShm.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+
+
+#include <gst/gst.h>
+#include "qabstractgstbufferpool.h"
+
+class QGstXvImageBufferPool;
+
+struct QGstXvImageBuffer {
+ GstBuffer buffer;
+ QGstXvImageBufferPool *pool;
+ XvImage *xvImage;
+ XShmSegmentInfo shmInfo;
+ bool markedForDeletion;
+
+ static GType get_type(void);
+ static void class_init(gpointer g_class, gpointer class_data);
+ static void buffer_init(QGstXvImageBuffer *xvimage, gpointer g_class);
+ static void buffer_finalize(QGstXvImageBuffer * xvimage);
+ static GstBufferClass *parent_class;
+};
+
+Q_DECLARE_METATYPE(XvImage*)
+
+class QGstXvImageBufferPool : public QObject, public QAbstractGstBufferPool {
+Q_OBJECT
+friend class QGstXvImageBuffer;
+public:
+ QGstXvImageBufferPool(QObject *parent = 0);
+ virtual ~QGstXvImageBufferPool();
+
+ bool isFormatSupported(const QVideoSurfaceFormat &format) const;
+
+ GType bufferType() const;
+ GstBuffer *takeBuffer(const QVideoSurfaceFormat &format, GstCaps *caps);
+ void clear();
+
+ QAbstractVideoBuffer::HandleType handleType() const;
+ QAbstractVideoBuffer *prepareVideoBuffer(GstBuffer *buffer, int bytesPerLine);
+
+private slots:
+ void queuedAlloc();
+ void queuedDestroy();
+
+ void doClear();
+
+ void recycleBuffer(QGstXvImageBuffer *);
+ void destroyBuffer(QGstXvImageBuffer *);
+
+private:
+ void doAlloc();
+
+ struct XvShmImage {
+ XvImage *xvImage;
+ XShmSegmentInfo shmInfo;
+ };
+
+ QMutex m_poolMutex;
+ QMutex m_allocMutex;
+ QWaitCondition m_allocWaitCondition;
+ QMutex m_destroyMutex;
+ QVideoSurfaceFormat m_format;
+ GstCaps *m_caps;
+ QList<QGstXvImageBuffer*> m_pool;
+ QList<QGstXvImageBuffer*> m_allBuffers;
+ QList<XvShmImage> m_imagesToDestroy;
+ Qt::HANDLE m_threadId;
+};
+
+#endif //QT_NO_XVIDEO
+
+#endif
diff --git a/src/plugins/gstreamer/qvideosurfacegstsink.cpp b/src/plugins/gstreamer/qvideosurfacegstsink.cpp
new file mode 100644
index 000000000..f3c0e3468
--- /dev/null
+++ b/src/plugins/gstreamer/qvideosurfacegstsink.cpp
@@ -0,0 +1,772 @@
+/****************************************************************************
+**
+** 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$
+** 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 <qabstractvideosurface.h>
+#include <qvideoframe.h>
+#include <QDebug>
+#include <QMap>
+#include <QDebug>
+#include <QThread>
+
+#include "qgstvideobuffer.h"
+
+#if defined(Q_WS_X11) && !defined(QT_NO_XVIDEO)
+#include <QtGui/qx11info_x11.h>
+#include "qgstxvimagebuffer.h"
+#endif
+
+#include "qvideosurfacegstsink.h"
+
+//#define DEBUG_VIDEO_SURFACE_SINK
+
+
+Q_DECLARE_METATYPE(QVideoSurfaceFormat)
+
+QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate(
+ QAbstractVideoSurface *surface)
+ : m_surface(surface)
+ , m_pool(0)
+ , m_renderReturn(GST_FLOW_ERROR)
+ , m_bytesPerLine(0)
+{
+ if (m_surface) {
+#if defined(Q_WS_X11) && !defined(QT_NO_XVIDEO)
+ m_pools.append(new QGstXvImageBufferPool());
+#endif
+ updateSupportedFormats();
+ connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(updateSupportedFormats()));
+ }
+}
+
+QVideoSurfaceGstDelegate::~QVideoSurfaceGstDelegate()
+{
+ qDeleteAll(m_pools);
+}
+
+QList<QVideoFrame::PixelFormat> QVideoSurfaceGstDelegate::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
+{
+ QMutexLocker locker(const_cast<QMutex *>(&m_mutex));
+
+ if (!m_surface)
+ return QList<QVideoFrame::PixelFormat>();
+ else if (handleType == QAbstractVideoBuffer::NoHandle)
+ return m_supportedPixelFormats;
+ else if (handleType == m_pool->handleType())
+ return m_supportedPoolPixelFormats;
+ else
+ return m_surface->supportedPixelFormats(handleType);
+}
+
+QVideoSurfaceFormat QVideoSurfaceGstDelegate::surfaceFormat() const
+{
+ QMutexLocker locker(const_cast<QMutex *>(&m_mutex));
+ return m_format;
+}
+
+bool QVideoSurfaceGstDelegate::start(const QVideoSurfaceFormat &format, int bytesPerLine)
+{
+ if (!m_surface)
+ return false;
+
+ QMutexLocker locker(&m_mutex);
+
+ m_format = format;
+ m_bytesPerLine = bytesPerLine;
+
+ if (QThread::currentThread() == thread()) {
+ m_started = !m_surface.isNull() ? m_surface->start(m_format) : false;
+ } else {
+ QMetaObject::invokeMethod(this, "queuedStart", Qt::QueuedConnection);
+
+ m_setupCondition.wait(&m_mutex);
+ }
+
+ m_format = m_surface->surfaceFormat();
+
+ return m_started;
+}
+
+void QVideoSurfaceGstDelegate::stop()
+{
+ if (!m_surface)
+ return;
+
+ QMutexLocker locker(&m_mutex);
+
+ if (QThread::currentThread() == thread()) {
+ if (!m_surface.isNull())
+ m_surface->stop();
+ } else {
+ QMetaObject::invokeMethod(this, "queuedStop", Qt::QueuedConnection);
+
+ m_setupCondition.wait(&m_mutex);
+ }
+
+ m_started = false;
+}
+
+bool QVideoSurfaceGstDelegate::isActive()
+{
+ QMutexLocker locker(&m_mutex);
+ return !m_surface.isNull() && m_surface->isActive();
+}
+
+GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
+{
+ if (!m_surface) {
+ qWarning() << "Rendering video frame to deleted surface, skip.";
+ //return GST_FLOW_NOT_NEGOTIATED;
+ return GST_FLOW_OK;
+ }
+
+ QMutexLocker locker(&m_mutex);
+
+ QAbstractVideoBuffer *videoBuffer = 0;
+
+ if (m_pool && G_TYPE_CHECK_INSTANCE_TYPE(buffer, m_pool->bufferType()))
+ videoBuffer = m_pool->prepareVideoBuffer(buffer, m_bytesPerLine);
+ else
+ videoBuffer = new QGstVideoBuffer(buffer, m_bytesPerLine);
+
+ m_frame = QVideoFrame(
+ videoBuffer,
+ m_format.frameSize(),
+ m_format.pixelFormat());
+
+ qint64 startTime = GST_BUFFER_TIMESTAMP(buffer);
+
+ if (startTime >= 0) {
+ m_frame.setStartTime(startTime/G_GINT64_CONSTANT (1000000));
+
+ qint64 duration = GST_BUFFER_DURATION(buffer);
+
+ if (duration >= 0)
+ m_frame.setEndTime((startTime + duration)/G_GINT64_CONSTANT (1000000));
+ }
+
+ QMetaObject::invokeMethod(this, "queuedRender", Qt::QueuedConnection);
+
+ if (!m_renderCondition.wait(&m_mutex, 300)) {
+ m_frame = QVideoFrame();
+
+ return GST_FLOW_OK;
+ } else {
+ return m_renderReturn;
+ }
+}
+
+void QVideoSurfaceGstDelegate::queuedStart()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_started = m_surface->start(m_format);
+
+ m_setupCondition.wakeAll();
+}
+
+void QVideoSurfaceGstDelegate::queuedStop()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_surface->stop();
+
+ m_setupCondition.wakeAll();
+}
+
+void QVideoSurfaceGstDelegate::queuedRender()
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (m_surface.isNull()) {
+ qWarning() << "Rendering video frame to deleted surface, skip the frame";
+ m_renderReturn = GST_FLOW_OK;
+ } else if (m_surface->present(m_frame)) {
+ m_renderReturn = GST_FLOW_OK;
+ } else {
+ switch (m_surface->error()) {
+ case QAbstractVideoSurface::NoError:
+ m_renderReturn = GST_FLOW_OK;
+ break;
+ case QAbstractVideoSurface::StoppedError:
+ //It's likely we are in process of changing video output
+ //and the surface is already stopped, ignore the frame
+ m_renderReturn = GST_FLOW_OK;
+ break;
+ default:
+ qWarning() << "Failed to render video frame:" << m_surface->error();
+ m_renderReturn = GST_FLOW_OK;
+ break;
+ }
+ }
+
+ m_renderCondition.wakeAll();
+}
+
+void QVideoSurfaceGstDelegate::updateSupportedFormats()
+{
+ QAbstractGstBufferPool *newPool = 0;
+ foreach (QAbstractGstBufferPool *pool, m_pools) {
+ if (!m_surface->supportedPixelFormats(pool->handleType()).isEmpty()) {
+ newPool = pool;
+ break;
+ }
+ }
+
+ if (newPool != m_pool) {
+ QMutexLocker lock(&m_poolMutex);
+
+ if (m_pool)
+ m_pool->clear();
+ m_pool = newPool;
+ }
+
+ QMutexLocker locker(&m_mutex);
+
+ m_supportedPixelFormats.clear();
+ m_supportedPoolPixelFormats.clear();
+ if (m_surface) {
+ m_supportedPixelFormats = m_surface->supportedPixelFormats();
+ if (m_pool)
+ m_supportedPoolPixelFormats = m_surface->supportedPixelFormats(m_pool->handleType());
+ }
+}
+
+struct YuvFormat
+{
+ QVideoFrame::PixelFormat pixelFormat;
+ guint32 fourcc;
+ int bitsPerPixel;
+};
+
+static const YuvFormat qt_yuvColorLookup[] =
+{
+ { QVideoFrame::Format_YUV420P, GST_MAKE_FOURCC('I','4','2','0'), 8 },
+ { QVideoFrame::Format_YV12, GST_MAKE_FOURCC('Y','V','1','2'), 8 },
+ { QVideoFrame::Format_UYVY, GST_MAKE_FOURCC('U','Y','V','Y'), 16 },
+ { QVideoFrame::Format_YUYV, GST_MAKE_FOURCC('Y','U','Y','2'), 16 },
+ { QVideoFrame::Format_NV12, GST_MAKE_FOURCC('N','V','1','2'), 8 },
+ { QVideoFrame::Format_NV21, GST_MAKE_FOURCC('N','V','2','1'), 8 },
+ { QVideoFrame::Format_AYUV444, GST_MAKE_FOURCC('A','Y','U','V'), 32 }
+};
+
+static int indexOfYuvColor(QVideoFrame::PixelFormat format)
+{
+ const int count = sizeof(qt_yuvColorLookup) / sizeof(YuvFormat);
+
+ for (int i = 0; i < count; ++i)
+ if (qt_yuvColorLookup[i].pixelFormat == format)
+ return i;
+
+ return -1;
+}
+
+static int indexOfYuvColor(guint32 fourcc)
+{
+ const int count = sizeof(qt_yuvColorLookup) / sizeof(YuvFormat);
+
+ for (int i = 0; i < count; ++i)
+ if (qt_yuvColorLookup[i].fourcc == fourcc)
+ return i;
+
+ return -1;
+}
+
+struct RgbFormat
+{
+ QVideoFrame::PixelFormat pixelFormat;
+ int bitsPerPixel;
+ int depth;
+ int endianness;
+ int red;
+ int green;
+ int blue;
+ int alpha;
+};
+
+static const RgbFormat qt_rgbColorLookup[] =
+{
+ { QVideoFrame::Format_RGB32 , 32, 24, 4321, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 },
+ { QVideoFrame::Format_RGB32 , 32, 24, 1234, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 },
+ { QVideoFrame::Format_BGR32 , 32, 24, 4321, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 },
+ { QVideoFrame::Format_BGR32 , 32, 24, 1234, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 },
+ { QVideoFrame::Format_ARGB32, 32, 24, 4321, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF },
+ { QVideoFrame::Format_ARGB32, 32, 24, 1234, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 },
+ { QVideoFrame::Format_RGB24 , 24, 24, 4321, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 },
+ { QVideoFrame::Format_BGR24 , 24, 24, 4321, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 },
+ { QVideoFrame::Format_RGB565, 16, 16, 1234, 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }
+};
+
+static int indexOfRgbColor(
+ int bits, int depth, int endianness, int red, int green, int blue, int alpha)
+{
+ const int count = sizeof(qt_rgbColorLookup) / sizeof(RgbFormat);
+
+ for (int i = 0; i < count; ++i) {
+ if (qt_rgbColorLookup[i].bitsPerPixel == bits
+ && qt_rgbColorLookup[i].depth == depth
+ && qt_rgbColorLookup[i].endianness == endianness
+ && qt_rgbColorLookup[i].red == red
+ && qt_rgbColorLookup[i].green == green
+ && qt_rgbColorLookup[i].blue == blue
+ && qt_rgbColorLookup[i].alpha == alpha) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static GstVideoSinkClass *sink_parent_class;
+
+#define VO_SINK(s) QVideoSurfaceGstSink *sink(reinterpret_cast<QVideoSurfaceGstSink *>(s))
+
+QVideoSurfaceGstSink *QVideoSurfaceGstSink::createSink(QAbstractVideoSurface *surface)
+{
+ QVideoSurfaceGstSink *sink = reinterpret_cast<QVideoSurfaceGstSink *>(
+ g_object_new(QVideoSurfaceGstSink::get_type(), 0));
+
+ sink->delegate = new QVideoSurfaceGstDelegate(surface);
+
+ return sink;
+}
+
+GType QVideoSurfaceGstSink::get_type()
+{
+ static GType type = 0;
+
+ if (type == 0) {
+ static const GTypeInfo info =
+ {
+ sizeof(QVideoSurfaceGstSinkClass), // class_size
+ base_init, // base_init
+ NULL, // base_finalize
+ class_init, // class_init
+ NULL, // class_finalize
+ NULL, // class_data
+ sizeof(QVideoSurfaceGstSink), // instance_size
+ 0, // n_preallocs
+ instance_init, // instance_init
+ 0 // value_table
+ };
+
+ type = g_type_register_static(
+ GST_TYPE_VIDEO_SINK, "QVideoSurfaceGstSink", &info, GTypeFlags(0));
+ }
+
+ return type;
+}
+
+void QVideoSurfaceGstSink::class_init(gpointer g_class, gpointer class_data)
+{
+ Q_UNUSED(class_data);
+
+ sink_parent_class = reinterpret_cast<GstVideoSinkClass *>(g_type_class_peek_parent(g_class));
+
+ GstBaseSinkClass *base_sink_class = reinterpret_cast<GstBaseSinkClass *>(g_class);
+ base_sink_class->get_caps = QVideoSurfaceGstSink::get_caps;
+ base_sink_class->set_caps = QVideoSurfaceGstSink::set_caps;
+ base_sink_class->buffer_alloc = QVideoSurfaceGstSink::buffer_alloc;
+ base_sink_class->start = QVideoSurfaceGstSink::start;
+ base_sink_class->stop = QVideoSurfaceGstSink::stop;
+ // base_sink_class->unlock = QVideoSurfaceGstSink::unlock; // Not implemented.
+ // base_sink_class->event = QVideoSurfaceGstSink::event; // Not implemented.
+ base_sink_class->preroll = QVideoSurfaceGstSink::preroll;
+ base_sink_class->render = QVideoSurfaceGstSink::render;
+
+ GstElementClass *element_class = reinterpret_cast<GstElementClass *>(g_class);
+ element_class->change_state = QVideoSurfaceGstSink::change_state;
+
+ GObjectClass *object_class = reinterpret_cast<GObjectClass *>(g_class);
+ object_class->finalize = QVideoSurfaceGstSink::finalize;
+}
+
+void QVideoSurfaceGstSink::base_init(gpointer g_class)
+{
+ static GstStaticPadTemplate sink_pad_template = GST_STATIC_PAD_TEMPLATE(
+ "sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS(
+ "video/x-raw-rgb, "
+ "framerate = (fraction) [ 0, MAX ], "
+ "width = (int) [ 1, MAX ], "
+ "height = (int) [ 1, MAX ]; "
+ "video/x-raw-yuv, "
+ "framerate = (fraction) [ 0, MAX ], "
+ "width = (int) [ 1, MAX ], "
+ "height = (int) [ 1, MAX ]"));
+
+ gst_element_class_add_pad_template(
+ GST_ELEMENT_CLASS(g_class), gst_static_pad_template_get(&sink_pad_template));
+}
+
+void QVideoSurfaceGstSink::instance_init(GTypeInstance *instance, gpointer g_class)
+{
+ VO_SINK(instance);
+
+ Q_UNUSED(g_class);
+
+ sink->delegate = 0;
+
+ sink->lastRequestedCaps = 0;
+ sink->lastBufferCaps = 0;
+ sink->lastSurfaceFormat = new QVideoSurfaceFormat;
+}
+
+void QVideoSurfaceGstSink::finalize(GObject *object)
+{
+ VO_SINK(object);
+
+ delete sink->lastSurfaceFormat;
+ sink->lastSurfaceFormat = 0;
+
+ if (sink->lastBufferCaps)
+ gst_caps_unref(sink->lastBufferCaps);
+ sink->lastBufferCaps = 0;
+
+ if (sink->lastRequestedCaps)
+ gst_caps_unref(sink->lastRequestedCaps);
+ sink->lastRequestedCaps = 0;
+}
+
+GstStateChangeReturn QVideoSurfaceGstSink::change_state(
+ GstElement *element, GstStateChange transition)
+{
+ Q_UNUSED(element);
+
+ return GST_ELEMENT_CLASS(sink_parent_class)->change_state(
+ element, transition);
+}
+
+GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base)
+{
+ VO_SINK(base);
+
+ GstCaps *caps = gst_caps_new_empty();
+
+ foreach (QVideoFrame::PixelFormat format, sink->delegate->supportedPixelFormats()) {
+ int index = indexOfYuvColor(format);
+
+ if (index != -1) {
+ gst_caps_append_structure(caps, gst_structure_new(
+ "video/x-raw-yuv",
+ "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1,
+ "width" , GST_TYPE_INT_RANGE, 1, INT_MAX,
+ "height" , GST_TYPE_INT_RANGE, 1, INT_MAX,
+ "format" , GST_TYPE_FOURCC, qt_yuvColorLookup[index].fourcc,
+ NULL));
+ continue;
+ }
+
+ const int count = sizeof(qt_rgbColorLookup) / sizeof(RgbFormat);
+
+ for (int i = 0; i < count; ++i) {
+ if (qt_rgbColorLookup[i].pixelFormat == format) {
+ GstStructure *structure = gst_structure_new(
+ "video/x-raw-rgb",
+ "framerate" , GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1,
+ "width" , GST_TYPE_INT_RANGE, 1, INT_MAX,
+ "height" , GST_TYPE_INT_RANGE, 1, INT_MAX,
+ "bpp" , G_TYPE_INT, qt_rgbColorLookup[i].bitsPerPixel,
+ "depth" , G_TYPE_INT, qt_rgbColorLookup[i].depth,
+ "endianness", G_TYPE_INT, qt_rgbColorLookup[i].endianness,
+ "red_mask" , G_TYPE_INT, qt_rgbColorLookup[i].red,
+ "green_mask", G_TYPE_INT, qt_rgbColorLookup[i].green,
+ "blue_mask" , G_TYPE_INT, qt_rgbColorLookup[i].blue,
+ NULL);
+
+ if (qt_rgbColorLookup[i].alpha != 0) {
+ gst_structure_set(
+ structure, "alpha_mask", G_TYPE_INT, qt_rgbColorLookup[i].alpha, NULL);
+ }
+ gst_caps_append_structure(caps, structure);
+ }
+ }
+ }
+
+ return caps;
+}
+
+gboolean QVideoSurfaceGstSink::set_caps(GstBaseSink *base, GstCaps *caps)
+{
+ VO_SINK(base);
+
+#ifdef DEBUG_VIDEO_SURFACE_SINK
+ qDebug() << "set_caps:";
+ qDebug() << gst_caps_to_string(caps);
+#endif
+
+ if (!caps) {
+ sink->delegate->stop();
+
+ return TRUE;
+ } else {
+ int bytesPerLine = 0;
+ QVideoSurfaceFormat format = formatForCaps(caps, &bytesPerLine);
+
+ if (sink->delegate->isActive()) {
+ QVideoSurfaceFormat surfaceFormst = sink->delegate->surfaceFormat();
+
+ if (format.pixelFormat() == surfaceFormst.pixelFormat() &&
+ format.frameSize() == surfaceFormst.frameSize())
+ return TRUE;
+ else
+ sink->delegate->stop();
+ }
+
+ if (sink->lastRequestedCaps)
+ gst_caps_unref(sink->lastRequestedCaps);
+ sink->lastRequestedCaps = 0;
+
+#ifdef DEBUG_VIDEO_SURFACE_SINK
+ qDebug() << "Staring video surface, format:";
+ qDebug() << format;
+ qDebug() << "bytesPerLine:" << bytesPerLine;
+#endif
+
+ if (sink->delegate->start(format, bytesPerLine))
+ return TRUE;
+ else
+ qWarning() << "Failed to start video surface";
+ }
+
+ return FALSE;
+}
+
+QVideoSurfaceFormat QVideoSurfaceGstSink::formatForCaps(GstCaps *caps, int *bytesPerLine)
+{
+ const GstStructure *structure = gst_caps_get_structure(caps, 0);
+
+ QVideoFrame::PixelFormat pixelFormat = QVideoFrame::Format_Invalid;
+ int bitsPerPixel = 0;
+
+ QSize size;
+ gst_structure_get_int(structure, "width", &size.rwidth());
+ gst_structure_get_int(structure, "height", &size.rheight());
+
+ if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) {
+ guint32 fourcc = 0;
+ gst_structure_get_fourcc(structure, "format", &fourcc);
+
+ int index = indexOfYuvColor(fourcc);
+ if (index != -1) {
+ pixelFormat = qt_yuvColorLookup[index].pixelFormat;
+ bitsPerPixel = qt_yuvColorLookup[index].bitsPerPixel;
+ }
+ } else if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) {
+ int depth = 0;
+ int endianness = 0;
+ int red = 0;
+ int green = 0;
+ int blue = 0;
+ int alpha = 0;
+
+ gst_structure_get_int(structure, "bpp", &bitsPerPixel);
+ gst_structure_get_int(structure, "depth", &depth);
+ gst_structure_get_int(structure, "endianness", &endianness);
+ gst_structure_get_int(structure, "red_mask", &red);
+ gst_structure_get_int(structure, "green_mask", &green);
+ gst_structure_get_int(structure, "blue_mask", &blue);
+ gst_structure_get_int(structure, "alpha_mask", &alpha);
+
+ int index = indexOfRgbColor(bitsPerPixel, depth, endianness, red, green, blue, alpha);
+
+ if (index != -1)
+ pixelFormat = qt_rgbColorLookup[index].pixelFormat;
+ }
+
+ if (pixelFormat != QVideoFrame::Format_Invalid) {
+ QVideoSurfaceFormat format(size, pixelFormat);
+
+ QPair<int, int> rate;
+ gst_structure_get_fraction(structure, "framerate", &rate.first, &rate.second);
+
+ if (rate.second)
+ format.setFrameRate(qreal(rate.first)/rate.second);
+
+ gint aspectNum = 0;
+ gint aspectDenum = 0;
+ if (gst_structure_get_fraction(
+ structure, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) {
+ if (aspectDenum > 0)
+ format.setPixelAspectRatio(aspectNum, aspectDenum);
+ }
+
+ if (bytesPerLine)
+ *bytesPerLine = ((size.width() * bitsPerPixel / 8) + 3) & ~3;
+
+ return format;
+ }
+
+ return QVideoSurfaceFormat();
+}
+
+
+GstFlowReturn QVideoSurfaceGstSink::buffer_alloc(
+ GstBaseSink *base, guint64 offset, guint size, GstCaps *caps, GstBuffer **buffer)
+{
+ VO_SINK(base);
+
+ Q_UNUSED(offset);
+ Q_UNUSED(size);
+
+ if (!buffer)
+ return GST_FLOW_ERROR;
+
+ *buffer = NULL;
+
+ if (!sink->delegate->pool())
+ return GST_FLOW_OK;
+
+ QMutexLocker poolLock(sink->delegate->poolMutex());
+ QAbstractGstBufferPool *pool = sink->delegate->pool();
+
+ if (!pool)
+ return GST_FLOW_OK;
+
+ if (sink->lastRequestedCaps && gst_caps_is_equal(sink->lastRequestedCaps, caps)) {
+ //qDebug() << "reusing last caps";
+ *buffer = GST_BUFFER(pool->takeBuffer(*sink->lastSurfaceFormat, sink->lastBufferCaps));
+ return GST_FLOW_OK;
+ }
+
+ if (sink->delegate->supportedPixelFormats(pool->handleType()).isEmpty()) {
+ //qDebug() << "sink doesn't support native pool buffers, skip buffers allocation";
+ return GST_FLOW_OK;
+ }
+
+ GstCaps *intersection = gst_caps_intersect(get_caps(GST_BASE_SINK(sink)), caps);
+
+ if (gst_caps_is_empty (intersection)) {
+ gst_caps_unref(intersection);
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
+
+ poolLock.unlock();
+
+ if (sink->delegate->isActive()) {
+ //if format was changed, restart the surface
+ QVideoSurfaceFormat format = formatForCaps(intersection);
+ QVideoSurfaceFormat surfaceFormat = sink->delegate->surfaceFormat();
+
+ if (format.pixelFormat() != surfaceFormat.pixelFormat() ||
+ format.frameSize() != surfaceFormat.frameSize()) {
+#ifdef DEBUG_VIDEO_SURFACE_SINK
+ qDebug() << "new format requested, restart video surface";
+#endif
+ sink->delegate->stop();
+ }
+ }
+
+ if (!sink->delegate->isActive()) {
+ int bytesPerLine = 0;
+ QVideoSurfaceFormat format = formatForCaps(intersection, &bytesPerLine);
+
+ if (!sink->delegate->start(format, bytesPerLine)) {
+ qWarning() << "failed to start video surface";
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
+ }
+
+ poolLock.relock();
+ pool = sink->delegate->pool();
+
+ QVideoSurfaceFormat surfaceFormat = sink->delegate->surfaceFormat();
+
+ if (!pool->isFormatSupported(surfaceFormat)) {
+ //qDebug() << "sink doesn't support native pool format, skip custom buffers allocation";
+ return GST_FLOW_OK;
+ }
+
+ if (sink->lastRequestedCaps)
+ gst_caps_unref(sink->lastRequestedCaps);
+ sink->lastRequestedCaps = caps;
+ gst_caps_ref(sink->lastRequestedCaps);
+
+ if (sink->lastBufferCaps)
+ gst_caps_unref(sink->lastBufferCaps);
+ sink->lastBufferCaps = intersection;
+ gst_caps_ref(sink->lastBufferCaps);
+
+ *sink->lastSurfaceFormat = surfaceFormat;
+
+ *buffer = GST_BUFFER(pool->takeBuffer(surfaceFormat, intersection));
+
+ return GST_FLOW_OK;
+}
+
+gboolean QVideoSurfaceGstSink::start(GstBaseSink *base)
+{
+ Q_UNUSED(base);
+
+ return TRUE;
+}
+
+gboolean QVideoSurfaceGstSink::stop(GstBaseSink *base)
+{
+ Q_UNUSED(base);
+
+ return TRUE;
+}
+
+gboolean QVideoSurfaceGstSink::unlock(GstBaseSink *base)
+{
+ Q_UNUSED(base);
+
+ return TRUE;
+}
+
+gboolean QVideoSurfaceGstSink::event(GstBaseSink *base, GstEvent *event)
+{
+ Q_UNUSED(base);
+ Q_UNUSED(event);
+
+ return TRUE;
+}
+
+GstFlowReturn QVideoSurfaceGstSink::preroll(GstBaseSink *base, GstBuffer *buffer)
+{
+ VO_SINK(base);
+ return sink->delegate->render(buffer);
+}
+
+GstFlowReturn QVideoSurfaceGstSink::render(GstBaseSink *base, GstBuffer *buffer)
+{
+ VO_SINK(base);
+ return sink->delegate->render(buffer);
+}
+
diff --git a/src/plugins/gstreamer/qvideosurfacegstsink.h b/src/plugins/gstreamer/qvideosurfacegstsink.h
new file mode 100644
index 000000000..531a76e0f
--- /dev/null
+++ b/src/plugins/gstreamer/qvideosurfacegstsink.h
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** 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$
+** 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 VIDEOSURFACEGSTSINK_H
+#define VIDEOSURFACEGSTSINK_H
+
+#include <gst/video/gstvideosink.h>
+
+#include <QtCore/qlist.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qqueue.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/qwaitcondition.h>
+#include <qvideosurfaceformat.h>
+#include <qvideoframe.h>
+#include <qabstractvideobuffer.h>
+
+#include "qabstractgstbufferpool.h"
+
+QT_BEGIN_NAMESPACE
+class QAbstractVideoSurface;
+QT_END_NAMESPACE
+
+#if defined(Q_WS_X11) && !defined(QT_NO_XVIDEO)
+class QGstXvImageBuffer;
+class QGstXvImageBufferPool;
+#endif
+
+class QVideoSurfaceGstDelegate : public QObject
+{
+ Q_OBJECT
+public:
+ QVideoSurfaceGstDelegate(QAbstractVideoSurface *surface);
+ ~QVideoSurfaceGstDelegate();
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
+
+ QVideoSurfaceFormat surfaceFormat() const;
+
+ bool start(const QVideoSurfaceFormat &format, int bytesPerLine);
+ void stop();
+
+ bool isActive();
+
+ QAbstractGstBufferPool *pool() { return m_pool; }
+ QMutex *poolMutex() { return &m_poolMutex; }
+
+ GstFlowReturn render(GstBuffer *buffer);
+
+private slots:
+ void queuedStart();
+ void queuedStop();
+ void queuedRender();
+
+ void updateSupportedFormats();
+
+private:
+ QPointer<QAbstractVideoSurface> m_surface;
+ QList<QVideoFrame::PixelFormat> m_supportedPixelFormats;
+ //pixel formats of buffers pool native type
+ QList<QVideoFrame::PixelFormat> m_supportedPoolPixelFormats;
+ QAbstractGstBufferPool *m_pool;
+ QList<QAbstractGstBufferPool *> m_pools;
+ QMutex m_poolMutex;
+ QMutex m_mutex;
+ QWaitCondition m_setupCondition;
+ QWaitCondition m_renderCondition;
+ QVideoSurfaceFormat m_format;
+ QVideoFrame m_frame;
+ GstFlowReturn m_renderReturn;
+ int m_bytesPerLine;
+ bool m_started;
+};
+
+class QVideoSurfaceGstSink
+{
+public:
+ GstVideoSink parent;
+
+ static QVideoSurfaceGstSink *createSink(QAbstractVideoSurface *surface);
+ static QVideoSurfaceFormat formatForCaps(GstCaps *caps, int *bytesPerLine = 0);
+
+private:
+ static GType get_type();
+ static void class_init(gpointer g_class, gpointer class_data);
+ static void base_init(gpointer g_class);
+ static void instance_init(GTypeInstance *instance, gpointer g_class);
+
+ static void finalize(GObject *object);
+
+ static GstStateChangeReturn change_state(GstElement *element, GstStateChange transition);
+
+ static GstCaps *get_caps(GstBaseSink *sink);
+ static gboolean set_caps(GstBaseSink *sink, GstCaps *caps);
+
+ static GstFlowReturn buffer_alloc(
+ GstBaseSink *sink, guint64 offset, guint size, GstCaps *caps, GstBuffer **buffer);
+
+ static gboolean start(GstBaseSink *sink);
+ static gboolean stop(GstBaseSink *sink);
+
+ static gboolean unlock(GstBaseSink *sink);
+
+ static gboolean event(GstBaseSink *sink, GstEvent *event);
+ static GstFlowReturn preroll(GstBaseSink *sink, GstBuffer *buffer);
+ static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer);
+
+private:
+ QVideoSurfaceGstDelegate *delegate;
+
+ GstCaps *lastRequestedCaps;
+ GstCaps *lastBufferCaps;
+ QVideoSurfaceFormat *lastSurfaceFormat;
+};
+
+
+class QVideoSurfaceGstSinkClass
+{
+public:
+ GstVideoSinkClass parent_class;
+};
+
+#endif
diff --git a/src/plugins/gstreamer/qx11videosurface.cpp b/src/plugins/gstreamer/qx11videosurface.cpp
new file mode 100644
index 000000000..ea2a1a3a2
--- /dev/null
+++ b/src/plugins/gstreamer/qx11videosurface.cpp
@@ -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$
+** 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 <QtCore/qvariant.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/qx11info_x11.h>
+#include <qvideosurfaceformat.h>
+
+#ifndef QT_NO_XVIDEO
+
+#include "qx11videosurface.h"
+
+Q_DECLARE_METATYPE(XvImage*);
+
+struct XvFormatRgb
+{
+ QVideoFrame::PixelFormat pixelFormat;
+ int bits_per_pixel;
+ int format;
+ int num_planes;
+
+ int depth;
+ unsigned int red_mask;
+ unsigned int green_mask;
+ unsigned int blue_mask;
+
+};
+
+bool operator ==(const XvImageFormatValues &format, const XvFormatRgb &rgb)
+{
+ return format.type == XvRGB
+ && format.bits_per_pixel == rgb.bits_per_pixel
+ && format.format == rgb.format
+ && format.num_planes == rgb.num_planes
+ && format.depth == rgb.depth
+ && format.red_mask == rgb.red_mask
+ && format.blue_mask == rgb.blue_mask;
+}
+
+static const XvFormatRgb qt_xvRgbLookup[] =
+{
+ { QVideoFrame::Format_ARGB32, 32, XvPacked, 1, 32, 0x00FF0000, 0x0000FF00, 0x000000FF },
+ { QVideoFrame::Format_RGB32 , 32, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF },
+ { QVideoFrame::Format_RGB24 , 24, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF },
+ { QVideoFrame::Format_RGB565, 16, XvPacked, 1, 16, 0x0000F800, 0x000007E0, 0x0000001F },
+ { QVideoFrame::Format_BGRA32, 32, XvPacked, 1, 32, 0xFF000000, 0x00FF0000, 0x0000FF00 },
+ { QVideoFrame::Format_BGR32 , 32, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF },
+ { QVideoFrame::Format_BGR24 , 24, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF },
+ { QVideoFrame::Format_BGR565, 16, XvPacked, 1, 16, 0x0000F800, 0x000007E0, 0x0000001F }
+};
+
+struct XvFormatYuv
+{
+ QVideoFrame::PixelFormat pixelFormat;
+ int bits_per_pixel;
+ int format;
+ int num_planes;
+
+ unsigned int y_sample_bits;
+ unsigned int u_sample_bits;
+ unsigned int v_sample_bits;
+ unsigned int horz_y_period;
+ unsigned int horz_u_period;
+ unsigned int horz_v_period;
+ unsigned int vert_y_period;
+ unsigned int vert_u_period;
+ unsigned int vert_v_period;
+ char component_order[32];
+};
+
+bool operator ==(const XvImageFormatValues &format, const XvFormatYuv &yuv)
+{
+ return format.type == XvYUV
+ && format.bits_per_pixel == yuv.bits_per_pixel
+ && format.format == yuv.format
+ && format.num_planes == yuv.num_planes
+ && format.y_sample_bits == yuv.y_sample_bits
+ && format.u_sample_bits == yuv.u_sample_bits
+ && format.v_sample_bits == yuv.v_sample_bits
+ && format.horz_y_period == yuv.horz_y_period
+ && format.horz_u_period == yuv.horz_u_period
+ && format.horz_v_period == yuv.horz_v_period
+ && format.horz_y_period == yuv.vert_y_period
+ && format.vert_u_period == yuv.vert_u_period
+ && format.vert_v_period == yuv.vert_v_period
+ && qstrncmp(format.component_order, yuv.component_order, 32) == 0;
+}
+
+static const XvFormatYuv qt_xvYuvLookup[] =
+{
+ { QVideoFrame::Format_YUV444 , 24, XvPacked, 1, 8, 8, 8, 1, 1, 1, 1, 1, 1, "YUV" },
+ { QVideoFrame::Format_YUV420P, 12, XvPlanar, 3, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YUV" },
+ { QVideoFrame::Format_YV12 , 12, XvPlanar, 3, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU" },
+ { QVideoFrame::Format_UYVY , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "UYVY" },
+ { QVideoFrame::Format_YUYV , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "YUY2" },
+ { QVideoFrame::Format_YUYV , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "YUYV" },
+ { QVideoFrame::Format_NV12 , 12, XvPlanar, 2, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YUV" },
+ { QVideoFrame::Format_NV12 , 12, XvPlanar, 2, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU" },
+ { QVideoFrame::Format_Y8 , 8 , XvPlanar, 1, 8, 0, 0, 1, 0, 0, 1, 0, 0, "Y" }
+};
+
+QX11VideoSurface::QX11VideoSurface(QObject *parent)
+ : QAbstractVideoSurface(parent)
+ , m_winId(0)
+ , m_portId(0)
+ , m_gc(0)
+ , m_image(0)
+{
+}
+
+QX11VideoSurface::~QX11VideoSurface()
+{
+ if (m_gc)
+ XFreeGC(QX11Info::display(), m_gc);
+
+ if (m_portId != 0)
+ XvUngrabPort(QX11Info::display(), m_portId, 0);
+}
+
+WId QX11VideoSurface::winId() const
+{
+ return m_winId;
+}
+
+void QX11VideoSurface::setWinId(WId id)
+{
+ //qDebug() << "setWinID:" << id;
+
+ if (id == m_winId)
+ return;
+
+ if (m_image)
+ XFree(m_image);
+
+ if (m_gc) {
+ XFreeGC(QX11Info::display(), m_gc);
+ m_gc = 0;
+ }
+
+ if (m_portId != 0)
+ XvUngrabPort(QX11Info::display(), m_portId, 0);
+
+ m_supportedPixelFormats.clear();
+ m_formatIds.clear();
+
+ m_winId = id;
+
+ if (m_winId && findPort()) {
+ querySupportedFormats();
+
+ m_gc = XCreateGC(QX11Info::display(), m_winId, 0, 0);
+
+ if (m_image) {
+ m_image = 0;
+
+ if (!start(surfaceFormat())) {
+ QAbstractVideoSurface::stop();
+ qWarning() << "Failed to start video surface with format" << surfaceFormat();
+ }
+ }
+ } else {
+ qWarning() << "Failed to find XVideo port";
+ if (m_image) {
+ m_image = 0;
+
+ QAbstractVideoSurface::stop();
+ }
+ }
+
+ emit supportedFormatsChanged();
+}
+
+QRect QX11VideoSurface::displayRect() const
+{
+ return m_displayRect;
+}
+
+void QX11VideoSurface::setDisplayRect(const QRect &rect)
+{
+ m_displayRect = rect;
+}
+
+QRect QX11VideoSurface::viewport() const
+{
+ return m_viewport;
+}
+
+void QX11VideoSurface::setViewport(const QRect &rect)
+{
+ m_viewport = rect;
+}
+
+int QX11VideoSurface::brightness() const
+{
+ return getAttribute("XV_BRIGHTNESS", m_brightnessRange.first, m_brightnessRange.second);
+}
+
+void QX11VideoSurface::setBrightness(int brightness)
+{
+ setAttribute("XV_BRIGHTNESS", brightness, m_brightnessRange.first, m_brightnessRange.second);
+}
+
+int QX11VideoSurface::contrast() const
+{
+ return getAttribute("XV_CONTRAST", m_contrastRange.first, m_contrastRange.second);
+}
+
+void QX11VideoSurface::setContrast(int contrast)
+{
+ setAttribute("XV_CONTRAST", contrast, m_contrastRange.first, m_contrastRange.second);
+}
+
+int QX11VideoSurface::hue() const
+{
+ return getAttribute("XV_HUE", m_hueRange.first, m_hueRange.second);
+}
+
+void QX11VideoSurface::setHue(int hue)
+{
+ setAttribute("XV_HUE", hue, m_hueRange.first, m_hueRange.second);
+}
+
+int QX11VideoSurface::saturation() const
+{
+ return getAttribute("XV_SATURATION", m_saturationRange.first, m_saturationRange.second);
+}
+
+void QX11VideoSurface::setSaturation(int saturation)
+{
+ setAttribute("XV_SATURATION", saturation, m_saturationRange.first, m_saturationRange.second);
+}
+
+int QX11VideoSurface::getAttribute(const char *attribute, int minimum, int maximum) const
+{
+ if (m_portId != 0) {
+ Display *display = QX11Info::display();
+
+ Atom atom = XInternAtom(display, attribute, True);
+
+ int value = 0;
+
+ XvGetPortAttribute(display, m_portId, atom, &value);
+
+ return redistribute(value, minimum, maximum, -100, 100);
+ } else {
+ return 0;
+ }
+}
+
+void QX11VideoSurface::setAttribute(const char *attribute, int value, int minimum, int maximum)
+{
+ if (m_portId != 0) {
+ Display *display = QX11Info::display();
+
+ Atom atom = XInternAtom(display, attribute, True);
+
+ XvSetPortAttribute(
+ display, m_portId, atom, redistribute(value, -100, 100, minimum, maximum));
+ }
+}
+
+int QX11VideoSurface::redistribute(
+ int value, int fromLower, int fromUpper, int toLower, int toUpper)
+{
+ return fromUpper != fromLower
+ ? ((value - fromLower) * (toUpper - toLower) / (fromUpper - fromLower)) + toLower
+ : 0;
+}
+
+QList<QVideoFrame::PixelFormat> QX11VideoSurface::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ return handleType == QAbstractVideoBuffer::NoHandle || handleType == QAbstractVideoBuffer::XvShmImageHandle
+ ? m_supportedPixelFormats
+ : QList<QVideoFrame::PixelFormat>();
+}
+
+bool QX11VideoSurface::start(const QVideoSurfaceFormat &format)
+{
+ if (m_image)
+ XFree(m_image);
+
+ int xvFormatId = 0;
+ for (int i = 0; i < m_supportedPixelFormats.count(); ++i) {
+ if (m_supportedPixelFormats.at(i) == format.pixelFormat()) {
+ xvFormatId = m_formatIds.at(i);
+ break;
+ }
+ }
+
+ if (xvFormatId == 0) {
+ setError(UnsupportedFormatError);
+ } else {
+ XvImage *image = XvCreateImage(
+ QX11Info::display(),
+ m_portId,
+ xvFormatId,
+ 0,
+ format.frameWidth(),
+ format.frameHeight());
+
+ if (!image) {
+ setError(ResourceError);
+ } else {
+ m_viewport = format.viewport();
+ m_image = image;
+
+ QVideoSurfaceFormat newFormat = format;
+ newFormat.setProperty("portId", QVariant(quint64(m_portId)));
+ newFormat.setProperty("xvFormatId", xvFormatId);
+ newFormat.setProperty("dataSize", image->data_size);
+
+ return QAbstractVideoSurface::start(newFormat);
+ }
+ }
+
+ if (m_image) {
+ m_image = 0;
+
+ QAbstractVideoSurface::stop();
+ }
+
+ return false;
+}
+
+void QX11VideoSurface::stop()
+{
+ if (m_image) {
+ XFree(m_image);
+ m_image = 0;
+
+ QAbstractVideoSurface::stop();
+ }
+}
+
+bool QX11VideoSurface::present(const QVideoFrame &frame)
+{
+ if (!m_image) {
+ setError(StoppedError);
+ return false;
+ } else if (m_image->width != frame.width() || m_image->height != frame.height()) {
+ setError(IncorrectFormatError);
+ return false;
+ } else {
+ QVideoFrame frameCopy(frame);
+
+ if (!frameCopy.map(QAbstractVideoBuffer::ReadOnly)) {
+ setError(IncorrectFormatError);
+ return false;
+ } else {
+ bool presented = false;
+
+ if (frame.handleType() != QAbstractVideoBuffer::XvShmImageHandle &&
+ m_image->data_size > frame.mappedBytes()) {
+ qWarning("Insufficient frame buffer size");
+ setError(IncorrectFormatError);
+ } else if (frame.handleType() != QAbstractVideoBuffer::XvShmImageHandle &&
+ m_image->num_planes > 0 &&
+ m_image->pitches[0] != frame.bytesPerLine()) {
+ qWarning("Incompatible frame pitches");
+ setError(IncorrectFormatError);
+ } else {
+ if (frame.handleType() != QAbstractVideoBuffer::XvShmImageHandle) {
+ m_image->data = reinterpret_cast<char *>(frameCopy.bits());
+
+ //qDebug() << "copy frame";
+ XvPutImage(
+ QX11Info::display(),
+ m_portId,
+ m_winId,
+ m_gc,
+ m_image,
+ m_viewport.x(),
+ m_viewport.y(),
+ m_viewport.width(),
+ m_viewport.height(),
+ m_displayRect.x(),
+ m_displayRect.y(),
+ m_displayRect.width(),
+ m_displayRect.height());
+
+ m_image->data = 0;
+ } else {
+ XvImage *img = frame.handle().value<XvImage*>();
+
+ //qDebug() << "render directly";
+ if (img)
+ XvShmPutImage(
+ QX11Info::display(),
+ m_portId,
+ m_winId,
+ m_gc,
+ img,
+ m_viewport.x(),
+ m_viewport.y(),
+ m_viewport.width(),
+ m_viewport.height(),
+ m_displayRect.x(),
+ m_displayRect.y(),
+ m_displayRect.width(),
+ m_displayRect.height(),
+ false);
+ }
+
+ presented = true;
+ }
+
+ frameCopy.unmap();
+
+ return presented;
+ }
+ }
+}
+
+bool QX11VideoSurface::findPort()
+{
+ unsigned int count = 0;
+ XvAdaptorInfo *adaptors = 0;
+ bool portFound = false;
+
+ if (XvQueryAdaptors(QX11Info::display(), m_winId, &count, &adaptors) == Success) {
+#ifdef Q_WS_MAEMO_5
+ //the overlay xvideo adapter fails to switch winId,
+ //prefer the "SGX Textured Video" adapter instead
+ for (int i = count-1; i >= 0 && !portFound; --i) {
+#else
+ for (unsigned int i = 0; i < count && !portFound; ++i) {
+#endif
+ if (adaptors[i].type & XvImageMask) {
+ m_portId = adaptors[i].base_id;
+
+ for (unsigned int j = 0; j < adaptors[i].num_ports && !portFound; ++j, ++m_portId)
+ portFound = XvGrabPort(QX11Info::display(), m_portId, 0) == Success;
+ }
+ }
+ XvFreeAdaptorInfo(adaptors);
+ }
+
+ return portFound;
+}
+
+void QX11VideoSurface::querySupportedFormats()
+{
+ int count = 0;
+ if (XvImageFormatValues *imageFormats = XvListImageFormats(
+ QX11Info::display(), m_portId, &count)) {
+ const int rgbCount = sizeof(qt_xvRgbLookup) / sizeof(XvFormatRgb);
+ const int yuvCount = sizeof(qt_xvYuvLookup) / sizeof(XvFormatYuv);
+
+ for (int i = 0; i < count; ++i) {
+ switch (imageFormats[i].type) {
+ case XvRGB:
+ for (int j = 0; j < rgbCount; ++j) {
+ if (imageFormats[i] == qt_xvRgbLookup[j]) {
+ m_supportedPixelFormats.append(qt_xvRgbLookup[j].pixelFormat);
+ m_formatIds.append(imageFormats[i].id);
+ break;
+ }
+ }
+ break;
+ case XvYUV:
+ for (int j = 0; j < yuvCount; ++j) {
+ if (imageFormats[i] == qt_xvYuvLookup[j]) {
+ m_supportedPixelFormats.append(qt_xvYuvLookup[j].pixelFormat);
+ m_formatIds.append(imageFormats[i].id);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ XFree(imageFormats);
+ }
+
+ m_brightnessRange = qMakePair(0, 0);
+ m_contrastRange = qMakePair(0, 0);
+ m_hueRange = qMakePair(0, 0);
+ m_saturationRange = qMakePair(0, 0);
+
+ if (XvAttribute *attributes = XvQueryPortAttributes(QX11Info::display(), m_portId, &count)) {
+ for (int i = 0; i < count; ++i) {
+ if (qstrcmp(attributes[i].name, "XV_BRIGHTNESS") == 0)
+ m_brightnessRange = qMakePair(attributes[i].min_value, attributes[i].max_value);
+ else if (qstrcmp(attributes[i].name, "XV_CONTRAST") == 0)
+ m_contrastRange = qMakePair(attributes[i].min_value, attributes[i].max_value);
+ else if (qstrcmp(attributes[i].name, "XV_HUE") == 0)
+ m_hueRange = qMakePair(attributes[i].min_value, attributes[i].max_value);
+ else if (qstrcmp(attributes[i].name, "XV_SATURATION") == 0)
+ m_saturationRange = qMakePair(attributes[i].min_value, attributes[i].max_value);
+ }
+
+ XFree(attributes);
+ }
+}
+
+#endif //QT_NO_XVIDEO
+
diff --git a/src/plugins/gstreamer/qx11videosurface.h b/src/plugins/gstreamer/qx11videosurface.h
new file mode 100644
index 000000000..7bebe2f67
--- /dev/null
+++ b/src/plugins/gstreamer/qx11videosurface.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QX11VIDEOSURFACE_H
+#define QX11VIDEOSURFACE_H
+
+#include <QtGui/qwidget.h>
+#include <qabstractvideosurface.h>
+
+#ifndef QT_NO_XVIDEO
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+
+QT_USE_NAMESPACE
+
+class QX11VideoSurface : public QAbstractVideoSurface
+{
+ Q_OBJECT
+public:
+ QX11VideoSurface(QObject *parent = 0);
+ ~QX11VideoSurface();
+
+ WId winId() const;
+ void setWinId(WId id);
+
+ QRect displayRect() const;
+ void setDisplayRect(const QRect &rect);
+
+ QRect viewport() const;
+ void setViewport(const QRect &rect);
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
+
+ bool start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ bool present(const QVideoFrame &frame);
+
+private:
+ WId m_winId;
+ XvPortID m_portId;
+ GC m_gc;
+ XvImage *m_image;
+ QList<QVideoFrame::PixelFormat> m_supportedPixelFormats;
+ QVector<int> m_formatIds;
+ QRect m_viewport;
+ QRect m_displayRect;
+ QPair<int, int> m_brightnessRange;
+ QPair<int, int> m_contrastRange;
+ QPair<int, int> m_hueRange;
+ QPair<int, int> m_saturationRange;
+
+ bool findPort();
+ void querySupportedFormats();
+
+ int getAttribute(const char *attribute, int minimum, int maximum) const;
+ void setAttribute(const char *attribute, int value, int minimum, int maximum);
+
+ static int redistribute(int value, int fromLower, int fromUpper, int toLower, int toUpper);
+};
+
+#endif //QT_NO_XVIDEO
+
+#endif
diff --git a/src/plugins/m3u/m3u.pro b/src/plugins/m3u/m3u.pro
new file mode 100644
index 000000000..f639445ee
--- /dev/null
+++ b/src/plugins/m3u/m3u.pro
@@ -0,0 +1,23 @@
+load(qt_module)
+
+TARGET = qtmultimediakit_m3u
+QT += multimediakit-private
+PLUGIN_TYPE=playlistformats
+
+load(qt_plugin)
+DESTDIR = $$QT.multimediakit.plugins/$${PLUGIN_TYPE}
+
+
+HEADERS += qm3uhandler.h
+SOURCES += main.cpp \
+ qm3uhandler.cpp
+symbian {
+ TARGET.UID3 = 0x2002BFC7
+ TARGET.CAPABILITY = ALL -TCB
+ TARGET.EPOCALLOWDLLDATA = 1
+
+ #make a sis package from plugin + stub (plugin)
+ pluginDep.sources = $${TARGET}.dll
+ pluginDep.path = $${QT_PLUGINS_BASE_DIR}/$${PLUGIN_TYPE}
+ DEPLOYMENT += pluginDep
+}
diff --git a/src/plugins/m3u/main.cpp b/src/plugins/m3u/main.cpp
new file mode 100644
index 000000000..4fd78d7dd
--- /dev/null
+++ b/src/plugins/m3u/main.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qm3uhandler.h"
+#include <qstringlist.h>
+
+
+Q_EXPORT_STATIC_PLUGIN(QM3uPlaylistPlugin)
+Q_EXPORT_PLUGIN2(qtmultimediakit_m3u, QM3uPlaylistPlugin)
diff --git a/src/plugins/m3u/qm3uhandler.cpp b/src/plugins/m3u/qm3uhandler.cpp
new file mode 100644
index 000000000..69e86a1a9
--- /dev/null
+++ b/src/plugins/m3u/qm3uhandler.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qm3uhandler.h"
+#include <qmediaresource.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qtextstream.h>
+#include <QFile>
+#include <QUrl>
+
+
+class QM3uPlaylistReader : public QMediaPlaylistReader
+{
+public:
+ QM3uPlaylistReader(QIODevice *device)
+ :m_ownDevice(false), m_device(device), m_textStream(new QTextStream(m_device))
+ {
+ readItem();
+ }
+
+ QM3uPlaylistReader(const QUrl& location)
+ :m_location(location), m_ownDevice(true)
+ {
+ QFile *f = new QFile(location.toLocalFile());
+ if (f->open(QIODevice::ReadOnly | QIODevice::Text)) {
+ m_device = f;
+ m_textStream = new QTextStream(m_device);
+ readItem();
+ } else {
+ delete f;
+ m_device = 0;
+ m_textStream = 0;
+ }
+ }
+
+ virtual ~QM3uPlaylistReader()
+ {
+ if (m_ownDevice) {
+ delete m_device;
+ }
+ delete m_textStream;
+ }
+
+ virtual bool atEnd() const
+ {
+ //we can't just use m_textStream->atEnd(),
+ //for files with empty lines/comments at end
+ return nextResource.isNull();
+ }
+
+ virtual QMediaContent readItem()
+ {
+ QMediaContent item;
+ if (!nextResource.isNull())
+ item = QMediaContent(nextResource);
+
+ nextResource = QMediaContent();
+
+ while (m_textStream && !m_textStream->atEnd()) {
+ QString line = m_textStream->readLine().trimmed();
+ if (line.isEmpty() || line[0] == '#' || line.size() > 4096)
+ continue;
+
+ QUrl fileUrl = QUrl::fromLocalFile(line);
+ QUrl url(line);
+
+ //m3u may contain url encoded entries or absolute/relative file names
+ //prefer existing file if any
+ QList<QUrl> candidates;
+ if (!m_location.isEmpty()) {
+ candidates << m_location.resolved(fileUrl);
+ candidates << m_location.resolved(url);
+ }
+ candidates << fileUrl;
+ candidates << url;
+
+ foreach (const QUrl &candidate, candidates) {
+ if (QFile::exists(candidate.toLocalFile())) {
+ nextResource = candidate;
+ break;
+ }
+ }
+
+ if (nextResource.isNull()) {
+ //assume the relative urls are file names, not encoded urls if m3u is local file
+ if (!m_location.isEmpty() && url.isRelative()) {
+ if (m_location.scheme() == QLatin1String("file"))
+ nextResource = m_location.resolved(fileUrl);
+ else
+ nextResource = m_location.resolved(url);
+ } else {
+ nextResource = QMediaContent(QUrl::fromUserInput(line));
+ }
+ }
+
+ break;
+ }
+
+ return item;
+ }
+
+ virtual void close()
+ {
+ }
+
+private:
+ QUrl m_location;
+ bool m_ownDevice;
+ QIODevice *m_device;
+ QTextStream *m_textStream;
+ QMediaContent nextResource;
+};
+
+class QM3uPlaylistWriter : public QMediaPlaylistWriter
+{
+public:
+ QM3uPlaylistWriter(QIODevice *device)
+ :m_device(device), m_textStream(new QTextStream(m_device))
+ {
+ }
+
+ virtual ~QM3uPlaylistWriter()
+ {
+ delete m_textStream;
+ }
+
+ virtual bool writeItem(const QMediaContent& item)
+ {
+ *m_textStream << item.canonicalUrl().toString() << endl;
+ return true;
+ }
+
+ virtual void close()
+ {
+ }
+
+private:
+ QIODevice *m_device;
+ QTextStream *m_textStream;
+};
+
+
+QM3uPlaylistPlugin::QM3uPlaylistPlugin(QObject *parent)
+ :QMediaPlaylistIOPlugin(parent)
+{
+}
+
+QM3uPlaylistPlugin::~QM3uPlaylistPlugin()
+{
+}
+
+bool QM3uPlaylistPlugin::canRead(QIODevice *device, const QByteArray &format) const
+{
+ return device->isReadable() && (format == "m3u" || format.isEmpty());
+}
+
+bool QM3uPlaylistPlugin::canRead(const QUrl& location, const QByteArray &format) const
+{
+ if (!QFileInfo(location.toLocalFile()).isReadable())
+ return false;
+
+ if (format == "m3u")
+ return true;
+
+ if (!format.isEmpty())
+ return false;
+ else
+ return location.toLocalFile().toLower().endsWith(QLatin1String("m3u"));
+}
+
+bool QM3uPlaylistPlugin::canWrite(QIODevice *device, const QByteArray &format) const
+{
+ return device->isOpen() && device->isWritable() && format == "m3u";
+}
+
+QStringList QM3uPlaylistPlugin::keys() const
+{
+ return QStringList() << QLatin1String("m3u");
+}
+
+QMediaPlaylistReader *QM3uPlaylistPlugin::createReader(QIODevice *device, const QByteArray &format)
+{
+ Q_UNUSED(format);
+ return new QM3uPlaylistReader(device);
+}
+
+QMediaPlaylistReader *QM3uPlaylistPlugin::createReader(const QUrl& location, const QByteArray &format)
+{
+ Q_UNUSED(format);
+ return new QM3uPlaylistReader(location);
+}
+
+QMediaPlaylistWriter *QM3uPlaylistPlugin::createWriter(QIODevice *device, const QByteArray &format)
+{
+ Q_UNUSED(format);
+ return new QM3uPlaylistWriter(device);
+}
+
diff --git a/src/plugins/m3u/qm3uhandler.h b/src/plugins/m3u/qm3uhandler.h
new file mode 100644
index 000000000..18d088ddd
--- /dev/null
+++ b/src/plugins/m3u/qm3uhandler.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 QM3UHANDLER_H
+#define QM3UHANDLER_H
+
+#include "qmediaplaylistioplugin.h"
+#include <QObject>
+
+QT_USE_NAMESPACE
+
+class QM3uPlaylistPlugin : public QMediaPlaylistIOPlugin
+{
+Q_OBJECT
+public:
+ explicit QM3uPlaylistPlugin(QObject *parent = 0);
+ virtual ~QM3uPlaylistPlugin();
+
+ virtual bool canRead(QIODevice *device, const QByteArray &format = QByteArray() ) const;
+ virtual bool canRead(const QUrl& location, const QByteArray &format = QByteArray()) const;
+
+ virtual bool canWrite(QIODevice *device, const QByteArray &format) const;
+
+ virtual QStringList keys() const;
+
+ virtual QMediaPlaylistReader *createReader(QIODevice *device, const QByteArray &format = QByteArray());
+ virtual QMediaPlaylistReader *createReader(const QUrl& location, const QByteArray &format = QByteArray());
+
+ virtual QMediaPlaylistWriter *createWriter(QIODevice *device, const QByteArray &format);
+};
+
+#endif // QM3UHANDLER_H
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
new file mode 100644
index 000000000..5a96fded0
--- /dev/null
+++ b/src/plugins/plugins.pro
@@ -0,0 +1,46 @@
+######################################################################
+#
+# Mobility API project - multimedia
+#
+######################################################################
+
+TEMPLATE = subdirs
+
+SUBDIRS += m3u
+
+win32 {
+ SUBDIRS += audiocapture
+}
+
+win32:!wince* {
+ contains(directshow_enabled, yes): SUBDIRS += directshow
+}
+
+simulator: SUBDIRS += simulator
+
+unix:!mac:!symbian {
+ TMP_GST_LIBS = \
+ gstreamer-0.10 >= 0.10.19 \
+ gstreamer-base-0.10 >= 0.10.19 \
+ gstreamer-interfaces-0.10 >= 0.10.19 \
+ gstreamer-audio-0.10 >= 0.10.19 \
+ gstreamer-video-0.10 >= 0.10.19
+
+ system(pkg-config --exists \'$${TMP_GST_LIBS}\' --print-errors): {
+ SUBDIRS += gstreamer
+ } else {
+ SUBDIRS += audiocapture
+ }
+
+ !maemo*:SUBDIRS += v4l
+
+ contains(pulseaudio_enabled, yes) {
+ SUBDIRS += pulseaudio
+ }
+}
+
+mac:!simulator {
+ SUBDIRS += audiocapture qt7
+}
+
+symbian:SUBDIRS += symbian
diff --git a/src/plugins/pulseaudio/pulseaudio.pro b/src/plugins/pulseaudio/pulseaudio.pro
new file mode 100644
index 000000000..2f9b7a854
--- /dev/null
+++ b/src/plugins/pulseaudio/pulseaudio.pro
@@ -0,0 +1,26 @@
+load(qt_module)
+
+TARGET = qtmedia_pulse
+QT += multimediakit-private
+PLUGIN_TYPE = audio
+
+load(qt_plugin)
+DESTDIR = $$QT.multimediakit.plugins/$${PLUGIN_TYPE}
+
+CONFIG += link_pkgconfig
+PKGCONFIG += libpulse
+
+# Input
+HEADERS += qpulseaudioplugin.h \
+ qaudiodeviceinfo_pulse.h \
+ qaudiooutput_pulse.h \
+ qaudioinput_pulse.h \
+ qpulseaudioengine.h \
+ qpulsehelpers.h
+
+SOURCES += qpulseaudioplugin.cpp \
+ qaudiodeviceinfo_pulse.cpp \
+ qaudiooutput_pulse.cpp \
+ qaudioinput_pulse.cpp \
+ qpulseaudioengine.cpp \
+ qpulsehelpers.cpp
diff --git a/src/plugins/pulseaudio/qaudiodeviceinfo_pulse.cpp b/src/plugins/pulseaudio/qaudiodeviceinfo_pulse.cpp
new file mode 100644
index 000000000..54296861d
--- /dev/null
+++ b/src/plugins/pulseaudio/qaudiodeviceinfo_pulse.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qaudiodeviceinfo_pulse.h"
+#include "qpulseaudioengine.h"
+#include "qpulsehelpers.h"
+
+QT_BEGIN_NAMESPACE
+
+QPulseAudioDeviceInfo::QPulseAudioDeviceInfo(const QByteArray &device, QAudio::Mode mode)
+ : m_device(device)
+ , m_mode(mode)
+{
+}
+
+bool QPulseAudioDeviceInfo::isFormatSupported(const QAudioFormat &format) const
+{
+ pa_sample_spec spec = QPulseAudioInternal::audioFormatToSampleSpec(format);
+ if (!pa_sample_spec_valid(&spec))
+ return false;
+
+ return true;
+}
+
+QAudioFormat QPulseAudioDeviceInfo::preferredFormat() const
+{
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ QAudioFormat format = pulseEngine->m_preferredFormats.value(m_device);
+ return format;
+}
+
+QString QPulseAudioDeviceInfo::deviceName() const
+{
+ return m_device;
+}
+
+QStringList QPulseAudioDeviceInfo::supportedCodecs()
+{
+ return QStringList() << "audio/pcm";
+}
+
+QList<int> QPulseAudioDeviceInfo::supportedSampleRates()
+{
+ return QList<int>() << 8000 << 11025 << 22050 << 44100 << 48000;
+}
+
+QList<int> QPulseAudioDeviceInfo::supportedChannelCounts()
+{
+ return QList<int>() << 1 << 2 << 4 << 6 << 8;
+}
+
+QList<int> QPulseAudioDeviceInfo::supportedSampleSizes()
+{
+ return QList<int>() << 8 << 16 << 24 << 32;
+}
+
+QList<QAudioFormat::Endian> QPulseAudioDeviceInfo::supportedByteOrders()
+{
+ return QList<QAudioFormat::Endian>() << QAudioFormat::BigEndian << QAudioFormat::LittleEndian;
+}
+
+QList<QAudioFormat::SampleType> QPulseAudioDeviceInfo::supportedSampleTypes()
+{
+ return QList<QAudioFormat::SampleType>() << QAudioFormat::SignedInt << QAudioFormat::UnSignedInt << QAudioFormat::Float;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/pulseaudio/qaudiodeviceinfo_pulse.h b/src/plugins/pulseaudio/qaudiodeviceinfo_pulse.h
new file mode 100644
index 000000000..f76913ca3
--- /dev/null
+++ b/src/plugins/pulseaudio/qaudiodeviceinfo_pulse.h
@@ -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$
+** 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 QAUDIODEVICEINFOPULSE_H
+#define QAUDIODEVICEINFOPULSE_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/qbytearray.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qlist.h>
+
+#include "qaudio.h"
+#include "qaudiodeviceinfo.h"
+#include "qaudiosystem.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPulseAudioDeviceInfo : public QAbstractAudioDeviceInfo
+{
+ Q_OBJECT
+
+public:
+ QPulseAudioDeviceInfo(const QByteArray &device, QAudio::Mode mode);
+ ~QPulseAudioDeviceInfo() {}
+
+ 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();
+
+private:
+ QByteArray m_device;
+ QAudio::Mode m_mode;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/plugins/pulseaudio/qaudioinput_pulse.cpp b/src/plugins/pulseaudio/qaudioinput_pulse.cpp
new file mode 100644
index 000000000..083bbabb6
--- /dev/null
+++ b/src/plugins/pulseaudio/qaudioinput_pulse.cpp
@@ -0,0 +1,600 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qcoreapplication.h>
+#include <QtCore/qdebug.h>
+
+#include "qaudioinput_pulse.h"
+#include "qaudiodeviceinfo_pulse.h"
+#include "qpulseaudioengine.h"
+#include "qpulsehelpers.h"
+
+QT_BEGIN_NAMESPACE
+
+const int PeriodTimeMs = 50;
+
+static void inputStreamReadCallback(pa_stream *stream, size_t length, void *userdata)
+{
+ Q_UNUSED(userdata);
+ Q_UNUSED(length);
+ Q_UNUSED(stream);
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0);
+}
+
+static void inputStreamStateCallback(pa_stream *stream, void *userdata)
+{
+ Q_UNUSED(userdata);
+ pa_stream_state_t state = pa_stream_get_state(stream);
+#ifdef DEBUG_PULSE
+ qDebug() << "Stream state: " << QPulseAudioInternal::stateToQString(state);
+#endif
+ switch (state) {
+ case PA_STREAM_CREATING:
+ break;
+ case PA_STREAM_READY: {
+#ifdef DEBUG_PULSE
+ QPulseAudioInput *audioInput = static_cast<QPulseAudioInput*>(userdata);
+ const pa_buffer_attr *buffer_attr = pa_stream_get_buffer_attr(stream);
+ qDebug() << "*** maxlength: " << buffer_attr->maxlength;
+ qDebug() << "*** prebuf: " << buffer_attr->prebuf;
+ qDebug() << "*** fragsize: " << buffer_attr->fragsize;
+ qDebug() << "*** minreq: " << buffer_attr->minreq;
+ qDebug() << "*** tlength: " << buffer_attr->tlength;
+
+ pa_sample_spec spec = QPulseAudioInternal::audioFormatToSampleSpec(audioInput->format());
+ qDebug() << "*** bytes_to_usec: " << pa_bytes_to_usec(buffer_attr->fragsize, &spec);
+#endif
+ }
+ break;
+ case PA_STREAM_TERMINATED:
+ break;
+ case PA_STREAM_FAILED:
+ default:
+ qWarning() << QString("Stream error: %1").arg(pa_strerror(pa_context_errno(pa_stream_get_context(stream))));
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0);
+ break;
+ }
+}
+
+static void inputStreamUnderflowCallback(pa_stream *stream, void *userdata)
+{
+ Q_UNUSED(userdata)
+ Q_UNUSED(stream)
+ qWarning() << "Got a buffer underflow!";
+}
+
+static void inputStreamOverflowCallback(pa_stream *stream, void *userdata)
+{
+ Q_UNUSED(stream)
+ Q_UNUSED(userdata)
+ qWarning() << "Got a buffer overflow!";
+}
+
+static void inputStreamSuccessCallback(pa_stream *stream, int success, void *userdata)
+{
+ Q_UNUSED(stream);
+ Q_UNUSED(userdata);
+ Q_UNUSED(success);
+
+ //if (!success)
+ //TODO: Is cork success? i->operation_success = success;
+
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0);
+}
+
+QPulseAudioInput::QPulseAudioInput(const QByteArray &device)
+ : m_totalTimeValue(0)
+ , m_audioSource(0)
+ , m_errorState(QAudio::NoError)
+ , m_deviceState(QAudio::StoppedState)
+ , m_pullMode(true)
+ , m_opened(false)
+ , m_bytesAvailable(0)
+ , m_bufferSize(0)
+ , m_periodSize(0)
+ , m_intervalTime(1000)
+ , m_stream(0)
+ , m_device(device)
+{
+ m_timer = new QTimer(this);
+ connect(m_timer, SIGNAL(timeout()), SLOT(userFeed()));
+}
+
+QPulseAudioInput::~QPulseAudioInput()
+{
+ close();
+ disconnect(m_timer, SIGNAL(timeout()));
+ QCoreApplication::processEvents();
+ delete m_timer;
+}
+
+QAudio::Error QPulseAudioInput::error() const
+{
+ return m_errorState;
+}
+
+QAudio::State QPulseAudioInput::state() const
+{
+ return m_deviceState;
+}
+
+void QPulseAudioInput::setFormat(const QAudioFormat &format)
+{
+ if (m_deviceState == QAudio::StoppedState)
+ m_format = format;
+}
+
+QAudioFormat QPulseAudioInput::format() const
+{
+ return m_format;
+}
+
+void QPulseAudioInput::start(QIODevice *device)
+{
+ if (m_deviceState != QAudio::StoppedState)
+ close();
+
+ if (!m_pullMode && m_audioSource)
+ delete m_audioSource;
+
+ m_pullMode = true;
+ m_audioSource = device;
+
+ m_deviceState = QAudio::ActiveState;
+
+ if (!open())
+ return;
+
+ emit stateChanged(m_deviceState);
+}
+
+QIODevice *QPulseAudioInput::start()
+{
+ if (m_deviceState != QAudio::StoppedState)
+ close();
+
+ if (!m_pullMode && m_audioSource)
+ delete m_audioSource;
+
+ m_pullMode = false;
+ m_audioSource = new InputPrivate(this);
+ m_audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
+
+ m_deviceState = QAudio::IdleState;
+
+ if (!open())
+ return 0;
+
+ emit stateChanged(m_deviceState);
+
+ return m_audioSource;
+}
+
+void QPulseAudioInput::stop()
+{
+ if (m_deviceState == QAudio::StoppedState)
+ return;
+
+ m_errorState = QAudio::NoError;
+ m_deviceState = QAudio::StoppedState;
+
+ close();
+ emit stateChanged(m_deviceState);
+}
+
+bool QPulseAudioInput::open()
+{
+ if (m_opened)
+ return false;
+
+#ifdef DEBUG_PULSE
+// QTime now(QTime::currentTime());
+// qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
+#endif
+ m_clockStamp.restart();
+ m_timeStamp.restart();
+ m_elapsedTimeOffset = 0;
+
+ if (m_streamName.isNull())
+ m_streamName = QString(QLatin1String("QtmPulseStream-%1-%2")).arg(::getpid()).arg(quintptr(this)).toUtf8();
+
+ pa_sample_spec spec = QPulseAudioInternal::audioFormatToSampleSpec(m_format);
+
+ if (!pa_sample_spec_valid(&spec)) {
+ m_errorState = QAudio::OpenError;
+ m_deviceState = QAudio::StoppedState;
+ emit stateChanged(m_deviceState);
+ return false;
+ }
+
+#ifdef DEBUG_PULSE
+ qDebug() << "Format: " << QPulseAudioInternal::sampleFormatToQString(spec.format);
+ qDebug() << "Rate: " << spec.rate;
+ qDebug() << "Channels: " << spec.channels;
+ qDebug() << "Frame size: " << pa_frame_size(&spec);
+#endif
+
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_threaded_mainloop_lock(pulseEngine->mainloop());
+ pa_channel_map channel_map;
+
+ pa_channel_map_init_extend(&channel_map, spec.channels, PA_CHANNEL_MAP_DEFAULT);
+
+ if (!pa_channel_map_compatible(&channel_map, &spec)) {
+ qWarning() << "Channel map doesn't match sample specification!";
+ }
+
+ m_stream = pa_stream_new(pulseEngine->context(), m_streamName.constData(), &spec, &channel_map);
+
+ pa_stream_set_state_callback(m_stream, inputStreamStateCallback, this);
+ pa_stream_set_read_callback(m_stream, inputStreamReadCallback, this);
+
+ pa_stream_set_underflow_callback(m_stream, inputStreamUnderflowCallback, this);
+ pa_stream_set_overflow_callback(m_stream, inputStreamOverflowCallback, this);
+
+ m_periodSize = pa_usec_to_bytes(PeriodTimeMs*1000, &spec);
+
+ int flags = 0;
+ pa_buffer_attr buffer_attr;
+ buffer_attr.maxlength = (uint32_t) -1;
+ buffer_attr.prebuf = (uint32_t) -1;
+ buffer_attr.tlength = (uint32_t) -1;
+ buffer_attr.minreq = (uint32_t) -1;
+ flags |= PA_STREAM_ADJUST_LATENCY;
+
+ if (m_bufferSize > 0)
+ buffer_attr.fragsize = (uint32_t) m_bufferSize;
+ else
+ buffer_attr.fragsize = (uint32_t) m_periodSize;
+
+ if (pa_stream_connect_record(m_stream, m_device.data(), &buffer_attr, (pa_stream_flags_t)flags) < 0) {
+ qWarning() << "pa_stream_connect_record() failed!";
+ m_errorState = QAudio::FatalError;
+ return false;
+ }
+
+ while (pa_stream_get_state(m_stream) != PA_STREAM_READY) {
+ pa_threaded_mainloop_wait(pulseEngine->mainloop());
+ }
+ pa_threaded_mainloop_unlock(pulseEngine->mainloop());
+
+ m_opened = true;
+ m_periodSize = pa_usec_to_bytes(PeriodTimeMs*1000, &spec);
+ m_timer->start(PeriodTimeMs);
+ m_errorState = QAudio::NoError;
+
+ m_totalTimeValue = 0;
+
+ return true;
+}
+
+void QPulseAudioInput::close()
+{
+ m_timer->stop();
+
+ if (m_stream) {
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_threaded_mainloop_lock(pulseEngine->mainloop());
+
+ pa_stream_set_read_callback(m_stream, 0, 0);
+
+ pa_stream_disconnect(m_stream);
+ pa_stream_unref(m_stream);
+ m_stream = 0;
+
+ pa_threaded_mainloop_unlock(pulseEngine->mainloop());
+ }
+
+ if (!m_pullMode && m_audioSource) {
+ delete m_audioSource;
+ m_audioSource = 0;
+ }
+ m_opened = false;
+}
+
+int QPulseAudioInput::checkBytesReady()
+{
+ if (m_deviceState != QAudio::ActiveState && m_deviceState != QAudio::IdleState) {
+ m_bytesAvailable = 0;
+ } else {
+ m_bytesAvailable = pa_stream_readable_size(m_stream);
+ }
+
+ return m_bytesAvailable;
+}
+
+int QPulseAudioInput::bytesReady() const
+{
+ return qMax(m_bytesAvailable, 0);
+}
+
+qint64 QPulseAudioInput::read(char *data, qint64 len)
+{
+ m_bytesAvailable = checkBytesReady();
+
+ if (m_deviceState != QAudio::ActiveState) {
+ m_errorState = QAudio::NoError;
+ m_deviceState = QAudio::ActiveState;
+ emit stateChanged(m_deviceState);
+ }
+
+ size_t readBytes = 0;
+
+ if (!m_pullMode && !m_tempBuffer.isEmpty()) {
+ readBytes = qMin(static_cast<int>(len), m_tempBuffer.size());
+ memcpy(data, m_tempBuffer.constData(), readBytes);
+ m_totalTimeValue += readBytes;
+
+ if (readBytes < m_tempBuffer.size()) {
+ m_tempBuffer.remove(0, readBytes);
+ return readBytes;
+ }
+
+ m_tempBuffer.clear();
+ }
+
+ while (pa_stream_readable_size(m_stream) > 0) {
+ size_t readLength = 0;
+
+#ifdef DEBUG_PULSE
+ qDebug() << "QPulseAudioInput::read -- " << pa_stream_readable_size(m_stream) << " bytes available from pulse audio";
+#endif
+
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_threaded_mainloop_lock(pulseEngine->mainloop());
+ const void *audioBuffer;
+
+ // Second and third parameters (audioBuffer and length) to pa_stream_peek are output parameters,
+ // the audioBuffer pointer is set to point to the actual pulse audio data,
+ // and the length is set to the length of this data.
+ if (pa_stream_peek(m_stream, &audioBuffer, &readLength) < 0) {
+ qWarning() << QString("pa_stream_peek() failed: %1").arg(pa_strerror(pa_context_errno(pa_stream_get_context(m_stream))));
+ pa_threaded_mainloop_unlock(pulseEngine->mainloop());
+ return 0;
+ }
+
+ qint64 actualLength = 0;
+ if (m_pullMode) {
+ actualLength = m_audioSource->write(static_cast<const char *>(audioBuffer), readLength);
+
+ if (actualLength < readLength) {
+ pa_threaded_mainloop_unlock(pulseEngine->mainloop());
+
+ m_errorState = QAudio::UnderrunError;
+ m_deviceState = QAudio::IdleState;
+ emit stateChanged(m_deviceState);
+
+ return actualLength;
+ }
+ } else {
+ actualLength = qMin(static_cast<int>(len - readBytes), static_cast<int>(readLength));
+ memcpy(data + readBytes, audioBuffer, actualLength);
+ }
+
+#ifdef DEBUG_PULSE
+ qDebug() << "QPulseAudioInput::read -- wrote " << actualLength << " to client";
+#endif
+
+ if (actualLength < readLength) {
+#ifdef DEBUG_PULSE
+ qDebug() << "QPulseAudioInput::read -- appending " << readLength - actualLength << " bytes of data to temp buffer";
+#endif
+ m_tempBuffer.append(static_cast<const char *>(audioBuffer) + actualLength, readLength - actualLength);
+ QMetaObject::invokeMethod(this, "userFeed", Qt::QueuedConnection);
+ }
+
+ m_totalTimeValue += actualLength;
+ readBytes += actualLength;
+
+ pa_stream_drop(m_stream);
+ pa_threaded_mainloop_unlock(pulseEngine->mainloop());
+
+ if (!m_pullMode && readBytes >= len)
+ break;
+ }
+
+#ifdef DEBUG_PULSE
+ qDebug() << "QPulseAudioInput::read -- returning after reading " << readBytes << " bytes";
+#endif
+
+ return readBytes;
+}
+
+void QPulseAudioInput::resume()
+{
+ if (m_deviceState == QAudio::SuspendedState || m_deviceState == QAudio::IdleState) {
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_operation *operation;
+
+ pa_threaded_mainloop_lock(pulseEngine->mainloop());
+
+ operation = pa_stream_cork(m_stream, 0, inputStreamSuccessCallback, 0);
+
+ while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
+ pa_threaded_mainloop_wait(pulseEngine->mainloop());
+
+ pa_operation_unref(operation);
+
+ pa_threaded_mainloop_unlock(pulseEngine->mainloop());
+
+ m_timer->start(PeriodTimeMs);
+
+ m_deviceState = QAudio::ActiveState;
+
+ emit stateChanged(m_deviceState);
+ }
+}
+
+void QPulseAudioInput::setBufferSize(int value)
+{
+ m_bufferSize = value;
+}
+
+int QPulseAudioInput::bufferSize() const
+{
+ return m_bufferSize;
+}
+
+int QPulseAudioInput::periodSize() const
+{
+ return m_periodSize;
+}
+
+void QPulseAudioInput::setNotifyInterval(int ms)
+{
+ m_intervalTime = qMax(0, ms);
+}
+
+int QPulseAudioInput::notifyInterval() const
+{
+ return m_intervalTime;
+}
+
+qint64 QPulseAudioInput::processedUSecs() const
+{
+ pa_sample_spec spec = QPulseAudioInternal::audioFormatToSampleSpec(m_format);
+ qint64 result = pa_bytes_to_usec(m_totalTimeValue, &spec);
+
+ return result;
+}
+
+void QPulseAudioInput::suspend()
+{
+ if (m_deviceState == QAudio::ActiveState) {
+ m_timer->stop();
+ m_deviceState = QAudio::SuspendedState;
+ emit stateChanged(m_deviceState);
+
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_operation *operation;
+
+ pa_threaded_mainloop_lock(pulseEngine->mainloop());
+
+ operation = pa_stream_cork(m_stream, 1, inputStreamSuccessCallback, 0);
+
+ while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
+ pa_threaded_mainloop_wait(pulseEngine->mainloop());
+
+ pa_operation_unref(operation);
+
+ pa_threaded_mainloop_unlock(pulseEngine->mainloop());
+ }
+}
+
+void QPulseAudioInput::userFeed()
+{
+ if (m_deviceState == QAudio::StoppedState || m_deviceState == QAudio::SuspendedState)
+ return;
+#ifdef DEBUG_PULSE
+// QTime now(QTime::currentTime());
+// qDebug()<< now.second() << "s " << now.msec() << "ms :userFeed() IN";
+#endif
+ deviceReady();
+}
+
+bool QPulseAudioInput::deviceReady()
+{
+ if (m_pullMode) {
+ // reads some audio data and writes it to QIODevice
+ read(0,0);
+ } else {
+ // emits readyRead() so user will call read() on QIODevice to get some audio data
+ if (m_audioSource != 0) {
+ InputPrivate *a = qobject_cast<InputPrivate*>(m_audioSource);
+ a->trigger();
+ }
+ }
+ m_bytesAvailable = checkBytesReady();
+
+ if (m_deviceState != QAudio::ActiveState)
+ return true;
+
+ if (m_intervalTime && (m_timeStamp.elapsed() + m_elapsedTimeOffset) > m_intervalTime) {
+ emit notify();
+ m_elapsedTimeOffset = m_timeStamp.elapsed() + m_elapsedTimeOffset - m_intervalTime;
+ m_timeStamp.restart();
+ }
+
+ return true;
+}
+
+qint64 QPulseAudioInput::elapsedUSecs() const
+{
+ if (m_deviceState == QAudio::StoppedState)
+ return 0;
+
+ return m_clockStamp.elapsed() * 1000;
+}
+
+void QPulseAudioInput::reset()
+{
+ stop();
+ m_bytesAvailable = 0;
+}
+
+InputPrivate::InputPrivate(QPulseAudioInput *audio)
+{
+ m_audioDevice = qobject_cast<QPulseAudioInput*>(audio);
+}
+
+qint64 InputPrivate::readData(char *data, qint64 len)
+{
+ return m_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();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qaudioinput_pulse.cpp"
diff --git a/src/plugins/pulseaudio/qaudioinput_pulse.h b/src/plugins/pulseaudio/qaudioinput_pulse.h
new file mode 100644
index 000000000..c186f91ab
--- /dev/null
+++ b/src/plugins/pulseaudio/qaudioinput_pulse.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** 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$
+** 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$
+**
+****************************************************************************/
+
+//
+// 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 QAUDIOINPUTPULSE_H
+#define QAUDIOINPUTPULSE_H
+
+#include <QtCore/qfile.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"
+
+#include <pulse/pulseaudio.h>
+
+QT_BEGIN_NAMESPACE
+
+class InputPrivate;
+
+class QPulseAudioInput : public QAbstractAudioInput
+{
+ Q_OBJECT
+
+public:
+ QPulseAudioInput(const QByteArray &device);
+ ~QPulseAudioInput();
+
+ 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 &format);
+ QAudioFormat format() const;
+
+ qint64 m_totalTimeValue;
+ QIODevice *m_audioSource;
+ QAudioFormat m_format;
+ QAudio::Error m_errorState;
+ QAudio::State m_deviceState;
+
+private slots:
+ void userFeed();
+ bool deviceReady();
+
+private:
+ int checkBytesReady();
+ bool open();
+ void close();
+
+ bool m_pullMode;
+ bool m_opened;
+ int m_bytesAvailable;
+ int m_bufferSize;
+ int m_periodSize;
+ int m_intervalTime;
+ unsigned int m_bufferTime;
+ unsigned int m_periodTime;
+ QTimer *m_timer;
+ qint64 m_elapsedTimeOffset;
+ char *audioBuffer;
+ pa_stream *m_stream;
+ QTime m_timeStamp;
+ QTime m_clockStamp;
+ QByteArray m_streamName;
+ QByteArray m_device;
+ QByteArray m_tempBuffer;
+};
+
+class InputPrivate : public QIODevice
+{
+ Q_OBJECT
+public:
+ InputPrivate(QPulseAudioInput *audio);
+ ~InputPrivate() {};
+
+ qint64 readData(char *data, qint64 len);
+ qint64 writeData(const char *data, qint64 len);
+
+ void trigger();
+
+private:
+ QPulseAudioInput *m_audioDevice;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/pulseaudio/qaudiooutput_pulse.cpp b/src/plugins/pulseaudio/qaudiooutput_pulse.cpp
new file mode 100644
index 000000000..8e5b3999c
--- /dev/null
+++ b/src/plugins/pulseaudio/qaudiooutput_pulse.cpp
@@ -0,0 +1,573 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qcoreapplication.h>
+#include <QtCore/qdebug.h>
+
+#include "qaudiooutput_pulse.h"
+#include "qaudiodeviceinfo_pulse.h"
+#include "qpulseaudioengine.h"
+#include "qpulsehelpers.h"
+
+QT_BEGIN_NAMESPACE
+
+const int PeriodTimeMs = 20;
+
+static void outputStreamWriteCallback(pa_stream *stream, size_t length, void *userdata)
+{
+ Q_UNUSED(stream);
+ Q_UNUSED(length);
+ Q_UNUSED(userdata);
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0);
+}
+
+static void outputStreamStateCallback(pa_stream *stream, void *userdata)
+{
+ Q_UNUSED(userdata)
+ pa_stream_state_t state = pa_stream_get_state(stream);
+#ifdef DEBUG_PULSE
+ qDebug() << "Stream state: " << QPulseAudioInternal::stateToQString(state);
+#endif
+ switch (state) {
+ case PA_STREAM_CREATING:
+ case PA_STREAM_READY:
+ case PA_STREAM_TERMINATED:
+ break;
+
+ case PA_STREAM_FAILED:
+ default:
+ qWarning() << QString("Stream error: %1").arg(pa_strerror(pa_context_errno(pa_stream_get_context(stream))));
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0);
+ break;
+ }
+}
+
+static void outputStreamUnderflowCallback(pa_stream *stream, void *userdata)
+{
+ Q_UNUSED(stream)
+ ((QPulseAudioOutput*)userdata)->streamUnderflowCallback();
+ qWarning() << "Got a buffer underflow!";
+}
+
+static void outputStreamOverflowCallback(pa_stream *stream, void *userdata)
+{
+ Q_UNUSED(stream)
+ Q_UNUSED(userdata)
+ qWarning() << "Got a buffer overflow!";
+}
+
+static void outputStreamLatencyCallback(pa_stream *stream, void *userdata)
+{
+ Q_UNUSED(stream)
+ Q_UNUSED(userdata)
+
+#ifdef DEBUG_PULSE
+ const pa_timing_info *info = pa_stream_get_timing_info(stream);
+
+ qDebug() << "Write index corrupt: " << info->write_index_corrupt;
+ qDebug() << "Write index: " << info->write_index;
+ qDebug() << "Read index corrupt: " << info->read_index_corrupt;
+ qDebug() << "Read index: " << info->read_index;
+ qDebug() << "Sink usec: " << info->sink_usec;
+ qDebug() << "Configured sink usec: " << info->configured_sink_usec;
+#endif
+}
+
+static void outputStreamSuccessCallback(pa_stream *stream, int success, void *userdata)
+{
+ Q_UNUSED(stream);
+ Q_UNUSED(success);
+ Q_UNUSED(userdata);
+
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0);
+}
+
+static void outputStreamDrainComplete(pa_stream *stream, int success, void *userdata)
+{
+ Q_UNUSED(stream);
+ Q_UNUSED(success);
+ Q_UNUSED(userdata);
+
+#ifdef DEBUG_PULSE
+ qDebug() << "Draining completed successfully: " << (bool)success;
+#endif
+}
+
+QPulseAudioOutput::QPulseAudioOutput(const QByteArray &device)
+ : m_device(device)
+ , m_errorState(QAudio::NoError)
+ , m_deviceState(QAudio::StoppedState)
+ , m_pullMode(true)
+ , m_opened(false)
+ , m_audioSource(0)
+ , m_bytesAvailable(0)
+ , m_stream(0)
+ , m_notifyInterval(1000)
+ , m_periodSize(0)
+ , m_bufferSize(0)
+ , m_totalTimeValue(0)
+ , m_tickTimer(new QTimer(this))
+ , m_audioBuffer(0)
+ , m_resuming(false)
+{
+ connect(m_tickTimer, SIGNAL(timeout()), SLOT(userFeed()));
+}
+
+QPulseAudioOutput::~QPulseAudioOutput()
+{
+ close();
+ disconnect(m_tickTimer, SIGNAL(timeout()));
+ QCoreApplication::processEvents();
+}
+
+QAudio::Error QPulseAudioOutput::error() const
+{
+ return m_errorState;
+}
+
+QAudio::State QPulseAudioOutput::state() const
+{
+ return m_deviceState;
+}
+
+void QPulseAudioOutput::streamUnderflowCallback()
+{
+ if (m_deviceState != QAudio::IdleState && !m_resuming) {
+ m_errorState = QAudio::UnderrunError;
+ emit errorChanged(m_errorState);
+ m_deviceState = QAudio::IdleState;
+ emit stateChanged(m_deviceState);
+ }
+}
+
+void QPulseAudioOutput::start(QIODevice *device)
+{
+ if (m_deviceState != QAudio::StoppedState)
+ m_deviceState = QAudio::StoppedState;
+
+ m_errorState = QAudio::NoError;
+
+ // Handle change of mode
+ if (m_audioSource && !m_pullMode) {
+ delete m_audioSource;
+ m_audioSource = 0;
+ }
+
+ close();
+
+ m_pullMode = true;
+ m_audioSource = device;
+
+ m_deviceState = QAudio::ActiveState;
+
+ open();
+
+ emit stateChanged(m_deviceState);
+}
+
+QIODevice *QPulseAudioOutput::start()
+{
+ if (m_deviceState != QAudio::StoppedState)
+ m_deviceState = QAudio::StoppedState;
+
+ m_errorState = QAudio::NoError;
+
+ // Handle change of mode
+ if (m_audioSource && !m_pullMode) {
+ delete m_audioSource;
+ m_audioSource = 0;
+ }
+
+ close();
+
+ m_audioSource = new OutputPrivate(this);
+ m_audioSource->open(QIODevice::WriteOnly|QIODevice::Unbuffered);
+ m_pullMode = false;
+
+ m_deviceState = QAudio::IdleState;
+
+ open();
+
+ emit stateChanged(m_deviceState);
+
+ return m_audioSource;
+}
+
+bool QPulseAudioOutput::open()
+{
+ if (m_opened)
+ return false;
+
+ pa_sample_spec spec = QPulseAudioInternal::audioFormatToSampleSpec(m_format);
+
+ if (!pa_sample_spec_valid(&spec)) {
+ m_errorState = QAudio::OpenError;
+ m_deviceState = QAudio::StoppedState;
+ return false;
+ }
+
+ m_totalTimeValue = 0;
+ m_elapsedTimeOffset = 0;
+ m_timeStamp.restart();
+
+ if (m_streamName.isNull())
+ m_streamName = QString(QLatin1String("QtmPulseStream-%1-%2")).arg(::getpid()).arg(quintptr(this)).toUtf8();
+
+#ifdef DEBUG_PULSE
+ qDebug() << "Format: " << QPulseAudioInternal::sampleFormatToQString(spec.format);
+ qDebug() << "Rate: " << spec.rate;
+ qDebug() << "Channels: " << spec.channels;
+ qDebug() << "Frame size: " << pa_frame_size(&spec);
+#endif
+
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_threaded_mainloop_lock(pulseEngine->mainloop());
+ m_stream = pa_stream_new(pulseEngine->context(), m_streamName.constData(), &spec, 0);
+
+ pa_stream_set_state_callback(m_stream, outputStreamStateCallback, this);
+ pa_stream_set_write_callback(m_stream, outputStreamWriteCallback, this);
+
+ pa_stream_set_underflow_callback(m_stream, outputStreamUnderflowCallback, this);
+ pa_stream_set_overflow_callback(m_stream, outputStreamOverflowCallback, this);
+ pa_stream_set_latency_update_callback(m_stream, outputStreamLatencyCallback, this);
+
+ if (pa_stream_connect_playback(m_stream, m_device.data(), NULL, (pa_stream_flags_t)0, NULL, NULL) < 0) {
+ qWarning() << "pa_stream_connect_playback() failed!";
+ return false;
+ }
+
+ while (pa_stream_get_state(m_stream) != PA_STREAM_READY) {
+ pa_threaded_mainloop_wait(pulseEngine->mainloop());
+ }
+ pa_threaded_mainloop_unlock(pulseEngine->mainloop());
+
+#ifdef DEBUG_PULSE
+ const pa_buffer_attr *buffer = pa_stream_get_buffer_attr(m_stream);
+
+ qDebug() << "Buffering info:";
+ qDebug() << "\tMax length: " << buffer->maxlength;
+ qDebug() << "\tTarget length: " << buffer->tlength;
+ qDebug() << "\tPre-buffering: " << buffer->prebuf;
+ qDebug() << "\tMinimum request: " << buffer->minreq;
+ qDebug() << "\tFragment size: " << buffer->fragsize;
+#endif
+
+ m_periodSize = pa_usec_to_bytes(PeriodTimeMs*1000, &spec);
+ m_opened = true;
+ m_tickTimer->start(PeriodTimeMs);
+
+ m_elapsedTimeOffset = 0;
+ m_timeStamp.restart();
+ m_clockStamp.restart();
+
+ return true;
+}
+
+void QPulseAudioOutput::userFeed()
+{
+ if (m_deviceState == QAudio::StoppedState || m_deviceState == QAudio::SuspendedState)
+ return;
+
+ if (m_deviceState == QAudio::IdleState)
+ m_bytesAvailable = bytesFree();
+
+ deviceReady();
+}
+
+void QPulseAudioOutput::close()
+{
+ m_tickTimer->stop();
+
+ if (m_stream) {
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_threaded_mainloop_lock(pulseEngine->mainloop());
+ pa_operation *o;
+
+ pa_stream_set_write_callback(m_stream, NULL, NULL);
+
+ if (!(o = pa_stream_drain(m_stream, outputStreamDrainComplete, NULL))) {
+ qWarning() << QString("pa_stream_drain(): %1").arg(pa_strerror(pa_context_errno(pa_stream_get_context(m_stream))));
+ return;
+ }
+ pa_operation_unref(o);
+
+ pa_stream_disconnect(m_stream);
+ pa_stream_unref(m_stream);
+ m_stream = NULL;
+
+ pa_threaded_mainloop_unlock(pulseEngine->mainloop());
+ }
+
+ if (!m_pullMode && m_audioSource) {
+ delete m_audioSource;
+ m_audioSource = 0;
+ }
+ m_opened = false;
+}
+
+bool QPulseAudioOutput::deviceReady()
+{
+ m_resuming = false;
+
+ if (m_pullMode) {
+ int l = 0;
+ int chunks = m_bytesAvailable/m_periodSize;
+ if (chunks==0) {
+ m_bytesAvailable = bytesFree();
+ return false;
+ }
+
+ char buffer[m_periodSize];
+
+ l = m_audioSource->read(buffer, m_periodSize);
+ if (l > 0) {
+ if (m_deviceState != QAudio::ActiveState)
+ return true;
+
+ qint64 bytesWritten = write(buffer, l);
+ Q_UNUSED(bytesWritten);
+ }
+ }
+
+ if (m_deviceState != QAudio::ActiveState)
+ return true;
+
+ if (m_notifyInterval && (m_timeStamp.elapsed() + m_elapsedTimeOffset) > m_notifyInterval) {
+ emit notify();
+ m_elapsedTimeOffset = m_timeStamp.elapsed() + m_elapsedTimeOffset - m_notifyInterval;
+ m_timeStamp.restart();
+ }
+
+ return true;
+}
+
+qint64 QPulseAudioOutput::write(const char *data, qint64 len)
+{
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+
+ pa_threaded_mainloop_lock(pulseEngine->mainloop());
+ len = qMin(len, static_cast<qint64>(pa_stream_writable_size(m_stream)));
+ pa_stream_write(m_stream, data, len, 0, 0, PA_SEEK_RELATIVE);
+ pa_threaded_mainloop_unlock(pulseEngine->mainloop());
+ m_totalTimeValue += len;
+
+ m_errorState = QAudio::NoError;
+ if (m_deviceState != QAudio::ActiveState) {
+ m_deviceState = QAudio::ActiveState;
+ emit stateChanged(m_deviceState);
+ }
+
+ return len;
+}
+
+void QPulseAudioOutput::stop()
+{
+ if (m_deviceState == QAudio::StoppedState)
+ return;
+
+ m_errorState = QAudio::NoError;
+ m_deviceState = QAudio::StoppedState;
+ close();
+ emit stateChanged(m_deviceState);
+}
+
+int QPulseAudioOutput::bytesFree() const
+{
+ if (m_deviceState != QAudio::ActiveState && m_deviceState != QAudio::IdleState)
+ return 0;
+
+ return pa_stream_writable_size(m_stream);
+}
+
+int QPulseAudioOutput::periodSize() const
+{
+ return m_periodSize;
+}
+
+void QPulseAudioOutput::setBufferSize(int value)
+{
+ m_bufferSize = value;
+}
+
+int QPulseAudioOutput::bufferSize() const
+{
+ return m_bufferSize;
+}
+
+void QPulseAudioOutput::setNotifyInterval(int ms)
+{
+ m_notifyInterval = qMax(0, ms);
+}
+
+int QPulseAudioOutput::notifyInterval() const
+{
+ return m_notifyInterval;
+}
+
+qint64 QPulseAudioOutput::processedUSecs() const
+{
+ qint64 result = qint64(1000000) * m_totalTimeValue /
+ (m_format.channels() * (m_format.sampleSize() / 8)) /
+ m_format.frequency();
+
+ return result;
+}
+
+void QPulseAudioOutput::resume()
+{
+ if (m_deviceState == QAudio::SuspendedState) {
+ m_resuming = true;
+
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+
+ pa_threaded_mainloop_lock(pulseEngine->mainloop());
+
+ pa_operation *operation = pa_stream_cork(m_stream, 0, outputStreamSuccessCallback, NULL);
+
+ while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
+ pa_threaded_mainloop_wait(pulseEngine->mainloop());
+
+ pa_operation_unref(operation);
+
+ operation = pa_stream_trigger(m_stream, outputStreamSuccessCallback, NULL);
+
+ while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
+ pa_threaded_mainloop_wait(pulseEngine->mainloop());
+
+ pa_operation_unref(operation);
+
+ pa_threaded_mainloop_unlock(pulseEngine->mainloop());
+
+ m_deviceState = QAudio::ActiveState;
+
+ m_errorState = QAudio::NoError;
+ m_tickTimer->start(PeriodTimeMs);
+
+ emit stateChanged(m_deviceState);
+ }
+}
+
+void QPulseAudioOutput::setFormat(const QAudioFormat &format)
+{
+ m_format = format;
+}
+
+QAudioFormat QPulseAudioOutput::format() const
+{
+ return m_format;
+}
+
+void QPulseAudioOutput::suspend()
+{
+ if (m_deviceState == QAudio::ActiveState || m_deviceState == QAudio::IdleState) {
+ m_tickTimer->stop();
+ m_deviceState = QAudio::SuspendedState;
+ m_errorState = QAudio::NoError;
+ emit stateChanged(m_deviceState);
+
+ QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance();
+ pa_operation *operation;
+
+ pa_threaded_mainloop_lock(pulseEngine->mainloop());
+
+ operation = pa_stream_cork(m_stream, 1, outputStreamSuccessCallback, NULL);
+
+ while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
+ pa_threaded_mainloop_wait(pulseEngine->mainloop());
+
+ pa_operation_unref(operation);
+
+ pa_threaded_mainloop_unlock(pulseEngine->mainloop());
+ }
+}
+
+qint64 QPulseAudioOutput::elapsedUSecs() const
+{
+ if (m_deviceState == QAudio::StoppedState)
+ return 0;
+
+ return m_clockStamp.elapsed() * 1000;
+}
+
+void QPulseAudioOutput::reset()
+{
+ stop();
+}
+
+OutputPrivate::OutputPrivate(QPulseAudioOutput *audio)
+{
+ m_audioDevice = qobject_cast<QPulseAudioOutput*>(audio);
+}
+
+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 ((m_audioDevice->m_deviceState == QAudio::ActiveState)
+ ||(m_audioDevice->m_deviceState == QAudio::IdleState)) {
+ while(written < len) {
+ int chunk = m_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_pulse.cpp"
diff --git a/src/plugins/pulseaudio/qaudiooutput_pulse.h b/src/plugins/pulseaudio/qaudiooutput_pulse.h
new file mode 100644
index 000000000..064754dbc
--- /dev/null
+++ b/src/plugins/pulseaudio/qaudiooutput_pulse.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** 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$
+** 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 QAUDIOOUTPUTPULSE_H
+#define QAUDIOOUTPUTPULSE_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/qfile.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"
+
+#include <pulse/pulseaudio.h>
+
+QT_BEGIN_NAMESPACE
+
+class QPulseAudioOutput : public QAbstractAudioOutput
+{
+ friend class OutputPrivate;
+ Q_OBJECT
+
+public:
+ QPulseAudioOutput(const QByteArray &device);
+ ~QPulseAudioOutput();
+
+ 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 &format);
+ QAudioFormat format() const;
+
+public:
+ void streamUnderflowCallback();
+
+private:
+ bool open();
+ void close();
+ qint64 write(const char *data, qint64 len);
+
+private Q_SLOTS:
+ bool deviceReady();
+ void userFeed();
+
+private:
+ QByteArray m_device;
+ QByteArray m_streamName;
+ QAudioFormat m_format;
+ QAudio::Error m_errorState;
+ QAudio::State m_deviceState;
+ bool m_pullMode;
+ bool m_opened;
+ QIODevice *m_audioSource;
+ int m_bytesAvailable;
+ QTimer m_periodTimer;
+ pa_stream *m_stream;
+ int m_notifyInterval;
+ int m_periodSize;
+ int m_bufferSize;
+ QTime m_clockStamp;
+ qint64 m_totalTimeValue;
+ QTimer *m_tickTimer;
+ char *m_audioBuffer;
+ QTime m_timeStamp;
+ qint64 m_elapsedTimeOffset;
+ bool m_resuming;
+};
+
+class OutputPrivate : public QIODevice
+{
+ friend class QPulseAudioOutput;
+ Q_OBJECT
+
+public:
+ OutputPrivate(QPulseAudioOutput *audio);
+ virtual ~OutputPrivate() {}
+
+protected:
+ qint64 readData(char *data, qint64 len);
+ qint64 writeData(const char *data, qint64 len);
+
+private:
+ QPulseAudioOutput *m_audioDevice;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/pulseaudio/qpulseaudioengine.cpp b/src/plugins/pulseaudio/qpulseaudioengine.cpp
new file mode 100644
index 000000000..da0963fa9
--- /dev/null
+++ b/src/plugins/pulseaudio/qpulseaudioengine.cpp
@@ -0,0 +1,354 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qdebug.h>
+
+#include <qaudiodeviceinfo.h>
+#include "qpulseaudioengine.h"
+#include "qaudiodeviceinfo_pulse.h"
+#include "qaudiooutput_pulse.h"
+#include "qpulsehelpers.h"
+
+QT_BEGIN_NAMESPACE
+
+static void serverInfoCallback(pa_context *context, const pa_server_info *info, void *userdata)
+{
+ if (!info) {
+ qWarning() << QString("Failed to get server information: %s").arg(pa_strerror(pa_context_errno(context)));
+ return;
+ }
+
+#ifdef DEBUG_PULSE
+ char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+
+ pa_sample_spec_snprint(ss, sizeof(ss), &info->sample_spec);
+ pa_channel_map_snprint(cm, sizeof(cm), &info->channel_map);
+
+ qDebug() << QString("User name: %1\n"
+ "Host Name: %2\n"
+ "Server Name: %3\n"
+ "Server Version: %4\n"
+ "Default Sample Specification: %5\n"
+ "Default Channel Map: %6\n"
+ "Default Sink: %7\n"
+ "Default Source: %8\n").arg(
+ info->user_name,
+ info->host_name,
+ info->server_name,
+ info->server_version,
+ ss,
+ cm,
+ info->default_sink_name,
+ info->default_source_name);
+#endif
+
+ QPulseAudioEngine *pulseEngine = static_cast<QPulseAudioEngine*>(userdata);
+ pulseEngine->m_defaultSink = info->default_sink_name;
+ pulseEngine->m_defaultSource = info->default_source_name;
+
+ pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0);
+}
+
+static void sinkInfoCallback(pa_context *context, const pa_sink_info *info, int isLast, void *userdata)
+{
+ QPulseAudioEngine *pulseEngine = static_cast<QPulseAudioEngine*>(userdata);
+ QMap<pa_sink_state, QString> stateMap;
+ stateMap[PA_SINK_INVALID_STATE] = "n/a";
+ stateMap[PA_SINK_RUNNING] = "RUNNING";
+ stateMap[PA_SINK_IDLE] = "IDLE";
+ stateMap[PA_SINK_SUSPENDED] = "SUSPENDED";
+
+ if (isLast < 0) {
+ qWarning() << QString("Failed to get sink information: %s").arg(pa_strerror(pa_context_errno(context)));
+ return;
+ }
+
+ if (isLast) {
+ pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0);
+ return;
+ }
+
+ Q_ASSERT(info);
+
+#ifdef DEBUG_PULSE
+ qDebug() << QString("Sink #%1\n"
+ "\tState: %2\n"
+ "\tName: %3\n"
+ "\tDescription: %4\n"
+ ).arg(QString::number(info->index),
+ stateMap.value(info->state),
+ info->name,
+ info->description);
+#endif
+
+ QAudioFormat format = QPulseAudioInternal::sampleSpecToAudioFormat(info->sample_spec);
+ pulseEngine->m_preferredFormats.insert(info->name, format);
+ pulseEngine->m_sinks.append(info->name);
+}
+
+static void sourceInfoCallback(pa_context *context, const pa_source_info *info, int isLast, void *userdata)
+{
+ Q_UNUSED(context)
+ QPulseAudioEngine *pulseEngine = static_cast<QPulseAudioEngine*>(userdata);
+
+ QMap<pa_source_state, QString> stateMap;
+ stateMap[PA_SOURCE_INVALID_STATE] = "n/a";
+ stateMap[PA_SOURCE_RUNNING] = "RUNNING";
+ stateMap[PA_SOURCE_IDLE] = "IDLE";
+ stateMap[PA_SOURCE_SUSPENDED] = "SUSPENDED";
+
+ if (isLast) {
+ pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0);
+ return;
+ }
+
+ Q_ASSERT(info);
+
+#ifdef DEBUG_PULSE
+ qDebug() << QString("Source #%1\n"
+ "\tState: %2\n"
+ "\tName: %3\n"
+ "\tDescription: %4\n"
+ ).arg(QString::number(info->index),
+ stateMap.value(info->state),
+ info->name,
+ info->description);
+#endif
+
+ QAudioFormat format = QPulseAudioInternal::sampleSpecToAudioFormat(info->sample_spec);
+ pulseEngine->m_preferredFormats.insert(info->name, format);
+ pulseEngine->m_sources.append(info->name);
+}
+
+static void contextStateCallbackInit(pa_context *context, void *userdata)
+{
+ Q_UNUSED(context);
+#ifdef DEBUG_PULSE
+ qDebug() << QPulseAudioInternal::stateToQString(pa_context_get_state(context));
+#endif
+ QPulseAudioEngine *pulseEngine = reinterpret_cast<QPulseAudioEngine*>(userdata);
+ pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0);
+}
+
+static void contextStateCallback(pa_context *context, void *userdata)
+{
+ Q_UNUSED(userdata);
+ Q_UNUSED(context);
+
+#ifdef DEBUG_PULSE
+ pa_context_state_t state = pa_context_get_state(context);
+ qDebug() << QPulseAudioInternal::stateToQString(state);
+#endif
+}
+
+Q_GLOBAL_STATIC(QPulseAudioEngine, pulseEngine);
+
+QPulseAudioEngine::QPulseAudioEngine(QObject *parent)
+ : QObject(parent)
+{
+ bool keepGoing = true;
+ bool ok = true;
+
+ m_mainLoop = pa_threaded_mainloop_new();
+ if (m_mainLoop == 0) {
+ qWarning("Unable to create pulseaudio mainloop");
+ return;
+ }
+
+ if (pa_threaded_mainloop_start(m_mainLoop) != 0) {
+ qWarning("Unable to start pulseaudio mainloop");
+ pa_threaded_mainloop_free(m_mainLoop);
+ return;
+ }
+
+ m_mainLoopApi = pa_threaded_mainloop_get_api(m_mainLoop);
+
+ pa_threaded_mainloop_lock(m_mainLoop);
+
+ m_context = pa_context_new(m_mainLoopApi, QString(QLatin1String("QtmPulseContext:%1")).arg(::getpid()).toAscii().constData());
+ pa_context_set_state_callback(m_context, contextStateCallbackInit, this);
+
+ if (!m_context) {
+ qWarning("Unable to create new pulseaudio context");
+ pa_threaded_mainloop_free(m_mainLoop);
+ return;
+ }
+
+ if (pa_context_connect(m_context, NULL, (pa_context_flags_t)0, NULL) < 0) {
+ qWarning("Unable to create a connection to the pulseaudio context");
+ pa_context_unref(m_context);
+ pa_threaded_mainloop_free(m_mainLoop);
+ return;
+ }
+
+ pa_threaded_mainloop_wait(m_mainLoop);
+
+ while (keepGoing) {
+ switch (pa_context_get_state(m_context)) {
+ case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME:
+ break;
+
+ case PA_CONTEXT_READY:
+#ifdef DEBUG_PULSE
+ qDebug("Connection established.");
+#endif
+ keepGoing = false;
+ break;
+
+ case PA_CONTEXT_TERMINATED:
+ qCritical("Context terminated.");
+ keepGoing = false;
+ ok = false;
+ break;
+
+ case PA_CONTEXT_FAILED:
+ default:
+ qCritical() << QString("Connection failure: %1").arg(pa_strerror(pa_context_errno(m_context)));
+ keepGoing = false;
+ ok = false;
+ }
+
+ if (keepGoing) {
+ pa_threaded_mainloop_wait(m_mainLoop);
+ }
+ }
+
+ if (ok) {
+ pa_context_set_state_callback(m_context, contextStateCallback, this);
+ } else {
+ if (m_context) {
+ pa_context_unref(m_context);
+ m_context = 0;
+ }
+ }
+
+ pa_threaded_mainloop_unlock(m_mainLoop);
+
+ serverInfo();
+ sinks();
+ sources();
+}
+
+QPulseAudioEngine::~QPulseAudioEngine()
+{
+ if (m_context) {
+ pa_threaded_mainloop_lock(m_mainLoop);
+ pa_context_disconnect(m_context);
+ pa_threaded_mainloop_unlock(m_mainLoop);
+ m_context = 0;
+ }
+
+ if (m_mainLoop) {
+ pa_threaded_mainloop_stop(m_mainLoop);
+ pa_threaded_mainloop_free(m_mainLoop);
+ m_mainLoop = 0;
+ }
+}
+
+void QPulseAudioEngine::serverInfo()
+{
+ pa_operation *operation;
+
+ pa_threaded_mainloop_lock(m_mainLoop);
+
+ operation = pa_context_get_server_info(m_context, serverInfoCallback, this);
+
+ while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
+ pa_threaded_mainloop_wait(m_mainLoop);
+
+ pa_operation_unref(operation);
+
+ pa_threaded_mainloop_unlock(m_mainLoop);
+}
+
+void QPulseAudioEngine::sinks()
+{
+ pa_operation *operation;
+
+ pa_threaded_mainloop_lock(m_mainLoop);
+
+ operation = pa_context_get_sink_info_list(m_context, sinkInfoCallback, this);
+
+ while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
+ pa_threaded_mainloop_wait(m_mainLoop);
+
+ pa_operation_unref(operation);
+
+ pa_threaded_mainloop_unlock(m_mainLoop);
+
+ // Swap the default sink to index 0
+ m_sinks.removeOne(m_defaultSink);
+ m_sinks.prepend(m_defaultSink);
+}
+
+void QPulseAudioEngine::sources()
+{
+ pa_operation *operation;
+
+ pa_threaded_mainloop_lock(m_mainLoop);
+
+ operation = pa_context_get_source_info_list(m_context, sourceInfoCallback, this);
+
+ while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
+ pa_threaded_mainloop_wait(m_mainLoop);
+
+ pa_operation_unref(operation);
+
+ pa_threaded_mainloop_unlock(m_mainLoop);
+
+ // Swap the default source to index 0
+ m_sources.removeOne(m_defaultSource);
+ m_sources.prepend(m_defaultSource);
+}
+
+QPulseAudioEngine *QPulseAudioEngine::instance()
+{
+ return pulseEngine();
+}
+
+QList<QByteArray> QPulseAudioEngine::availableDevices(QAudio::Mode mode) const
+{
+ return mode == QAudio::AudioOutput ? m_sinks : m_sources;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/pulseaudio/qpulseaudioengine.h b/src/plugins/pulseaudio/qpulseaudioengine.h
new file mode 100644
index 000000000..3519be79d
--- /dev/null
+++ b/src/plugins/pulseaudio/qpulseaudioengine.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QPULSEAUDIOENGINE_H
+#define QPULSEAUDIOENGINE_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/qmap.h>
+#include <QtCore/qbytearray.h>
+#include <qaudiosystemplugin.h>
+#include <pulse/pulseaudio.h>
+#include "qpulsehelpers.h"
+#include <qaudioformat.h>
+
+QT_BEGIN_NAMESPACE
+
+class QPulseAudioEngine : public QObject
+{
+ Q_OBJECT
+
+public:
+ QPulseAudioEngine(QObject *parent = 0);
+ ~QPulseAudioEngine();
+
+ static QPulseAudioEngine *instance();
+ pa_threaded_mainloop *mainloop() { return m_mainLoop; }
+ pa_context *context() { return m_context; }
+
+ QList<QByteArray> availableDevices(QAudio::Mode mode) const;
+
+private:
+ void serverInfo();
+ void sinks();
+ void sources();
+
+public:
+ QList<QByteArray> m_sinks;
+ QList<QByteArray> m_sources;
+ QMap<QByteArray, QAudioFormat> m_preferredFormats;
+
+ QByteArray m_defaultSink;
+ QByteArray m_defaultSource;
+
+private:
+ pa_mainloop_api *m_mainLoopApi;
+ pa_threaded_mainloop *m_mainLoop;
+ pa_context *m_context;
+ };
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/pulseaudio/qpulseaudioplugin.cpp b/src/plugins/pulseaudio/qpulseaudioplugin.cpp
new file mode 100644
index 000000000..99ff09211
--- /dev/null
+++ b/src/plugins/pulseaudio/qpulseaudioplugin.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** 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$
+** 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 <qaudiodeviceinfo.h>
+
+#include "qpulseaudioplugin.h"
+#include "qaudiodeviceinfo_pulse.h"
+#include "qaudiooutput_pulse.h"
+#include "qaudioinput_pulse.h"
+#include "qpulseaudioengine.h"
+
+QT_BEGIN_NAMESPACE
+
+QPulseAudioPlugin::QPulseAudioPlugin(QObject *parent)
+ : QAudioSystemPlugin(parent)
+ , m_pulseEngine(QPulseAudioEngine::instance())
+{
+}
+
+QStringList QPulseAudioPlugin::keys() const
+{
+ return QStringList() << "default";
+}
+
+QList<QByteArray> QPulseAudioPlugin::availableDevices(QAudio::Mode mode) const
+{
+ return m_pulseEngine->availableDevices(mode);
+}
+
+QAbstractAudioInput *QPulseAudioPlugin::createInput(const QByteArray &device)
+{
+ QPulseAudioInput *input = new QPulseAudioInput(device);
+ return input;
+}
+
+QAbstractAudioOutput *QPulseAudioPlugin::createOutput(const QByteArray &device)
+{
+
+ QPulseAudioOutput *output = new QPulseAudioOutput(device);
+ return output;
+}
+
+QAbstractAudioDeviceInfo *QPulseAudioPlugin::createDeviceInfo(const QByteArray &device, QAudio::Mode mode)
+{
+ QPulseAudioDeviceInfo *deviceInfo = new QPulseAudioDeviceInfo(device, mode);
+ return deviceInfo;
+}
+
+Q_EXPORT_PLUGIN2(qtmedia_pulse, QPulseAudioPlugin);
+
+QT_END_NAMESPACE
diff --git a/src/plugins/pulseaudio/qpulseaudioplugin.h b/src/plugins/pulseaudio/qpulseaudioplugin.h
new file mode 100644
index 000000000..e90270e0c
--- /dev/null
+++ b/src/plugins/pulseaudio/qpulseaudioplugin.h
@@ -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$
+** 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 QPULSEAUDIOPLUGIN_H
+#define QPULSEAUDIOPLUGIN_H
+
+#include <qaudiosystemplugin.h>
+
+QT_BEGIN_NAMESPACE
+
+class QPulseAudioEngine;
+
+class QPulseAudioPlugin : public QAudioSystemPlugin
+{
+ Q_OBJECT
+
+public:
+ QPulseAudioPlugin(QObject *parent = 0);
+ ~QPulseAudioPlugin() {}
+
+ QStringList keys() const;
+ QList<QByteArray> availableDevices(QAudio::Mode mode) const;
+ QAbstractAudioInput *createInput(const QByteArray &device);
+ QAbstractAudioOutput *createOutput(const QByteArray &device);
+ QAbstractAudioDeviceInfo *createDeviceInfo(const QByteArray &device, QAudio::Mode mode);
+
+private:
+ QPulseAudioEngine *m_pulseEngine;
+};
+
+QT_BEGIN_NAMESPACE
+
+#endif
diff --git a/src/plugins/pulseaudio/qpulsehelpers.cpp b/src/plugins/pulseaudio/qpulsehelpers.cpp
new file mode 100644
index 000000000..57e50758f
--- /dev/null
+++ b/src/plugins/pulseaudio/qpulsehelpers.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qpulsehelpers.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QPulseAudioInternal
+{
+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() == 24) {
+ switch (format.byteOrder()) {
+ case QAudioFormat::BigEndian: spec.format = PA_SAMPLE_S24BE; break;
+ case QAudioFormat::LittleEndian: spec.format = PA_SAMPLE_S24LE; break;
+ }
+ } else if (format.sampleSize() == 32) {
+ switch (format.byteOrder()) {
+ case QAudioFormat::BigEndian:
+ format.sampleType() == QAudioFormat::Float ? spec.format = PA_SAMPLE_FLOAT32BE : spec.format = PA_SAMPLE_S32BE;
+ break;
+ case QAudioFormat::LittleEndian:
+ format.sampleType() == QAudioFormat::Float ? spec.format = PA_SAMPLE_FLOAT32LE : spec.format = PA_SAMPLE_S32LE;
+ break;
+ }
+ } else {
+ spec.format = PA_SAMPLE_INVALID;
+ }
+
+ return spec;
+}
+
+#ifdef DEBUG_PULSE
+QString stateToQString(pa_stream_state_t state)
+{
+ switch (state)
+ {
+ case PA_STREAM_UNCONNECTED: return "Unconnected";
+ case PA_STREAM_CREATING: return "Creating";
+ case PA_STREAM_READY: return "Ready";
+ case PA_STREAM_FAILED: return "Failed";
+ case PA_STREAM_TERMINATED: return "Terminated";
+ }
+
+ return QString("Unknown state: %0").arg(state);
+}
+
+QString sampleFormatToQString(pa_sample_format format)
+{
+ switch (format)
+ {
+ case PA_SAMPLE_U8: return "Unsigned 8 Bit PCM.";
+ case PA_SAMPLE_ALAW: return "8 Bit a-Law ";
+ case PA_SAMPLE_ULAW: return "8 Bit mu-Law";
+ case PA_SAMPLE_S16LE: return "Signed 16 Bit PCM, little endian (PC).";
+ case PA_SAMPLE_S16BE: return "Signed 16 Bit PCM, big endian.";
+ case PA_SAMPLE_FLOAT32LE: return "32 Bit IEEE floating point, little endian (PC), range -1.0 to 1.0";
+ case PA_SAMPLE_FLOAT32BE: return "32 Bit IEEE floating point, big endian, range -1.0 to 1.0";
+ case PA_SAMPLE_S32LE: return "Signed 32 Bit PCM, little endian (PC).";
+ case PA_SAMPLE_S32BE: return "Signed 32 Bit PCM, big endian.";
+ case PA_SAMPLE_S24LE: return "Signed 24 Bit PCM packed, little endian (PC).";
+ case PA_SAMPLE_S24BE: return "Signed 24 Bit PCM packed, big endian.";
+ case PA_SAMPLE_S24_32LE: return "Signed 24 Bit PCM in LSB of 32 Bit words, little endian (PC).";
+ case PA_SAMPLE_S24_32BE: return "Signed 24 Bit PCM in LSB of 32 Bit words, big endian.";
+ case PA_SAMPLE_MAX: return "Upper limit of valid sample types.";
+ case PA_SAMPLE_INVALID: return "Invalid sample format";
+ }
+
+ return QString("Invalid value: %0").arg(format);
+}
+
+QString stateToQString(pa_context_state_t state)
+{
+ switch (state)
+ {
+ case PA_CONTEXT_UNCONNECTED: return "Unconnected";
+ case PA_CONTEXT_CONNECTING: return "Connecting";
+ case PA_CONTEXT_AUTHORIZING: return "Authorizing";
+ case PA_CONTEXT_SETTING_NAME: return "Setting Name";
+ case PA_CONTEXT_READY: return "Ready";
+ case PA_CONTEXT_FAILED: return "Failed";
+ case PA_CONTEXT_TERMINATED: return "Terminated";
+ }
+
+ return QString("Unknown state: %0").arg(state);
+}
+#endif
+
+QAudioFormat sampleSpecToAudioFormat(pa_sample_spec spec)
+{
+ QAudioFormat format;
+ format.setFrequency(spec.rate);
+ format.setChannelCount(spec.channels);
+ format.setCodec("audio/pcm");
+
+ switch (spec.format) {
+ case PA_SAMPLE_U8:
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::UnSignedInt);
+ format.setSampleSize(8);
+ break;
+ case PA_SAMPLE_ALAW:
+ // TODO:
+ break;
+ case PA_SAMPLE_ULAW:
+ // TODO:
+ break;
+ case PA_SAMPLE_S16LE:
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::SignedInt);
+ format.setSampleSize(16);
+ break;
+ case PA_SAMPLE_S16BE:
+ format.setByteOrder(QAudioFormat::BigEndian);
+ format.setSampleType(QAudioFormat::SignedInt);
+ format.setSampleSize(16);
+ break;
+ case PA_SAMPLE_FLOAT32LE:
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::Float);
+ format.setSampleSize(32);
+ break;
+ case PA_SAMPLE_FLOAT32BE:
+ format.setByteOrder(QAudioFormat::BigEndian);
+ format.setSampleType(QAudioFormat::Float);
+ format.setSampleSize(32);
+ break;
+ case PA_SAMPLE_S32LE:
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::SignedInt);
+ format.setSampleSize(32);
+ break;
+ case PA_SAMPLE_S32BE:
+ format.setByteOrder(QAudioFormat::BigEndian);
+ format.setSampleType(QAudioFormat::SignedInt);
+ format.setSampleSize(32);
+ break;
+ case PA_SAMPLE_S24LE:
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::SignedInt);
+ format.setSampleSize(24);
+ break;
+ case PA_SAMPLE_S24BE:
+ format.setByteOrder(QAudioFormat::BigEndian);
+ format.setSampleType(QAudioFormat::SignedInt);
+ format.setSampleSize(24);
+ break;
+ case PA_SAMPLE_S24_32LE:
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::SignedInt);
+ format.setSampleSize(24);
+ break;
+ case PA_SAMPLE_S24_32BE:
+ format.setByteOrder(QAudioFormat::BigEndian);
+ format.setSampleType(QAudioFormat::SignedInt);
+ format.setSampleSize(24);
+ break;
+ case PA_SAMPLE_MAX:
+ case PA_SAMPLE_INVALID:
+ default:
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::Unknown);
+ format.setSampleSize(0);
+ }
+
+ return format;
+}
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/pulseaudio/qpulsehelpers.h b/src/plugins/pulseaudio/qpulsehelpers.h
new file mode 100644
index 000000000..255f0cf90
--- /dev/null
+++ b/src/plugins/pulseaudio/qpulsehelpers.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** 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$
+** 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 QPULSEHELPER_H
+#define QPULSEHELPER_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 "qaudiodeviceinfo.h"
+#include <qaudioformat.h>
+#include <pulse/pulseaudio.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QPulseAudioInternal
+{
+pa_sample_spec audioFormatToSampleSpec(const QAudioFormat &format);
+QString stateToQString(pa_stream_state_t state);
+QString stateToQString(pa_context_state_t state);
+QString sampleFormatToQString(pa_sample_format format);
+QAudioFormat sampleSpecToAudioFormat(pa_sample_spec spec);
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qt7/mediaplayer/mediaplayer.pri b/src/plugins/qt7/mediaplayer/mediaplayer.pri
new file mode 100644
index 000000000..2edb1d2c7
--- /dev/null
+++ b/src/plugins/qt7/mediaplayer/mediaplayer.pri
@@ -0,0 +1,16 @@
+INCLUDEPATH += $$PWD
+
+DEFINES += QMEDIA_QT7_PLAYER
+
+HEADERS += \
+ $$PWD/qt7playercontrol.h \
+ $$PWD/qt7playermetadata.h \
+ $$PWD/qt7playerservice.h \
+ $$PWD/qt7playersession.h
+
+OBJECTIVE_SOURCES += \
+ $$PWD/qt7playercontrol.mm \
+ $$PWD/qt7playermetadata.mm \
+ $$PWD/qt7playerservice.mm \
+ $$PWD/qt7playersession.mm
+
diff --git a/src/plugins/qt7/mediaplayer/qt7playercontrol.h b/src/plugins/qt7/mediaplayer/qt7playercontrol.h
new file mode 100644
index 000000000..064c0ccd3
--- /dev/null
+++ b/src/plugins/qt7/mediaplayer/qt7playercontrol.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QT7PLAYERCONTROL_H
+#define QT7PLAYERCONTROL_H
+
+#include <QtCore/qobject.h>
+
+#include <qmediaplayercontrol.h>
+#include <qmediaplayer.h>
+
+#include <QtGui/qmacdefines_mac.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QT7PlayerSession;
+class QT7PlayerService;
+class QMediaPlaylist;
+class QMediaPlaylistNavigator;
+
+class QT7PlayerControl : public QMediaPlayerControl
+{
+Q_OBJECT
+public:
+ QT7PlayerControl(QObject *parent = 0);
+ ~QT7PlayerControl();
+
+ void setSession(QT7PlayerSession *session);
+
+ QMediaPlayer::State state() const;
+ QMediaPlayer::MediaStatus mediaStatus() const;
+
+ QMediaContent media() const;
+ const QIODevice *mediaStream() const;
+ void setMedia(const QMediaContent &content, QIODevice *stream);
+
+ qint64 position() const;
+ qint64 duration() const;
+
+ int bufferStatus() const;
+
+ int volume() const;
+ bool isMuted() const;
+
+ bool isAudioAvailable() const;
+ bool isVideoAvailable() const;
+
+ bool isSeekable() const;
+ QMediaTimeRange availablePlaybackRanges() const;
+
+ qreal playbackRate() const;
+ void setPlaybackRate(qreal rate);
+
+public Q_SLOTS:
+ void setPosition(qint64 pos);
+
+ void play();
+ void pause();
+ void stop();
+
+ void setVolume(int volume);
+ void setMuted(bool muted);
+
+private:
+ QT7PlayerSession *m_session;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qt7/mediaplayer/qt7playercontrol.mm b/src/plugins/qt7/mediaplayer/qt7playercontrol.mm
new file mode 100644
index 000000000..ddfcc3570
--- /dev/null
+++ b/src/plugins/qt7/mediaplayer/qt7playercontrol.mm
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qt7playercontrol.h"
+#include "qt7playersession.h"
+
+#include <qmediaplaylistnavigator.h>
+
+#include <QtCore/qurl.h>
+#include <QtCore/qdebug.h>
+
+QT_USE_NAMESPACE
+
+QT7PlayerControl::QT7PlayerControl(QObject *parent)
+ : QMediaPlayerControl(parent)
+{
+}
+
+QT7PlayerControl::~QT7PlayerControl()
+{
+}
+
+void QT7PlayerControl::setSession(QT7PlayerSession *session)
+{
+ m_session = session;
+
+ connect(m_session, SIGNAL(positionChanged(qint64)), this, SIGNAL(positionChanged(qint64)));
+ connect(m_session, SIGNAL(durationChanged(qint64)), this, SIGNAL(durationChanged(qint64)));
+ connect(m_session, SIGNAL(stateChanged(QMediaPlayer::State)),
+ this, SIGNAL(stateChanged(QMediaPlayer::State)));
+ connect(m_session, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
+ this, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ connect(m_session, SIGNAL(volumeChanged(int)), this, SIGNAL(volumeChanged(int)));
+ connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool)));
+ connect(m_session, SIGNAL(audioAvailableChanged(bool)), this, SIGNAL(audioAvailableChanged(bool)));
+ connect(m_session, SIGNAL(videoAvailableChanged(bool)), this, SIGNAL(videoAvailableChanged(bool)));
+ connect(m_session, SIGNAL(error(int,QString)), this, SIGNAL(error(int,QString)));
+}
+
+qint64 QT7PlayerControl::position() const
+{
+ return m_session->position();
+}
+
+qint64 QT7PlayerControl::duration() const
+{
+ return m_session->duration();
+}
+
+QMediaPlayer::State QT7PlayerControl::state() const
+{
+ return m_session->state();
+}
+
+QMediaPlayer::MediaStatus QT7PlayerControl::mediaStatus() const
+{
+ return m_session->mediaStatus();
+}
+
+int QT7PlayerControl::bufferStatus() const
+{
+ return m_session->bufferStatus();
+}
+
+int QT7PlayerControl::volume() const
+{
+ return m_session->volume();
+}
+
+bool QT7PlayerControl::isMuted() const
+{
+ return m_session->isMuted();
+}
+
+bool QT7PlayerControl::isSeekable() const
+{
+ return m_session->isSeekable();
+}
+
+QMediaTimeRange QT7PlayerControl::availablePlaybackRanges() const
+{
+ return m_session->availablePlaybackRanges();
+}
+
+qreal QT7PlayerControl::playbackRate() const
+{
+ return m_session->playbackRate();
+}
+
+void QT7PlayerControl::setPlaybackRate(qreal rate)
+{
+ m_session->setPlaybackRate(rate);
+}
+
+void QT7PlayerControl::setPosition(qint64 pos)
+{
+ m_session->setPosition(pos);
+}
+
+void QT7PlayerControl::play()
+{
+ m_session->play();
+}
+
+void QT7PlayerControl::pause()
+{
+ m_session->pause();
+}
+
+void QT7PlayerControl::stop()
+{
+ m_session->stop();
+}
+
+void QT7PlayerControl::setVolume(int volume)
+{
+ m_session->setVolume(volume);
+}
+
+void QT7PlayerControl::setMuted(bool muted)
+{
+ m_session->setMuted(muted);
+}
+
+QMediaContent QT7PlayerControl::media() const
+{
+ return m_session->media();
+}
+
+const QIODevice *QT7PlayerControl::mediaStream() const
+{
+ return m_session->mediaStream();
+}
+
+void QT7PlayerControl::setMedia(const QMediaContent &content, QIODevice *stream)
+{
+ m_session->setMedia(content, stream);
+
+ emit mediaChanged(content);
+}
+
+bool QT7PlayerControl::isAudioAvailable() const
+{
+ return m_session->isAudioAvailable();
+}
+
+bool QT7PlayerControl::isVideoAvailable() const
+{
+ return m_session->isVideoAvailable();
+}
+
+
+#include "moc_qt7playercontrol.cpp"
diff --git a/src/plugins/qt7/mediaplayer/qt7playermetadata.h b/src/plugins/qt7/mediaplayer/qt7playermetadata.h
new file mode 100644
index 000000000..441ca07f6
--- /dev/null
+++ b/src/plugins/qt7/mediaplayer/qt7playermetadata.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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$
+** 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 QT7PLAYERMETADATACONTROL_H
+#define QT7PLAYERMETADATACONTROL_H
+
+#include <qmetadatareadercontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class QT7PlayerSession;
+
+class QT7PlayerMetaDataControl : public QMetaDataReaderControl
+{
+ Q_OBJECT
+public:
+ QT7PlayerMetaDataControl(QT7PlayerSession *session, QObject *parent);
+ virtual ~QT7PlayerMetaDataControl();
+
+ bool isMetaDataAvailable() const;
+ bool isWritable() const;
+
+ QVariant metaData(QtMultimediaKit::MetaData key) const;
+ QList<QtMultimediaKit::MetaData> availableMetaData() const;
+
+ QVariant extendedMetaData(const QString &key) const ;
+ QStringList availableExtendedMetaData() const;
+
+private slots:
+ void updateTags();
+
+private:
+ QT7PlayerSession *m_session;
+ QMap<QtMultimediaKit::MetaData, QVariant> m_tags;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qt7/mediaplayer/qt7playermetadata.mm b/src/plugins/qt7/mediaplayer/qt7playermetadata.mm
new file mode 100644
index 000000000..ec0d41cc2
--- /dev/null
+++ b/src/plugins/qt7/mediaplayer/qt7playermetadata.mm
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qt7backend.h"
+#include "qt7playermetadata.h"
+#include "qt7playersession.h"
+#include <QtCore/qvarlengtharray.h>
+
+#import <QTKit/QTMovie.h>
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ #include <QuickTime/QuickTime.h>
+ #undef check // avoid name clash;
+#endif
+
+QT_USE_NAMESPACE
+
+QT7PlayerMetaDataControl::QT7PlayerMetaDataControl(QT7PlayerSession *session, QObject *parent)
+ :QMetaDataReaderControl(parent), m_session(session)
+{
+}
+
+QT7PlayerMetaDataControl::~QT7PlayerMetaDataControl()
+{
+}
+
+bool QT7PlayerMetaDataControl::isMetaDataAvailable() const
+{
+ return !m_tags.isEmpty();
+}
+
+bool QT7PlayerMetaDataControl::isWritable() const
+{
+ return false;
+}
+
+QVariant QT7PlayerMetaDataControl::metaData(QtMultimediaKit::MetaData key) const
+{
+ return m_tags.value(key);
+}
+
+QList<QtMultimediaKit::MetaData> QT7PlayerMetaDataControl::availableMetaData() const
+{
+ return m_tags.keys();
+}
+
+QVariant QT7PlayerMetaDataControl::extendedMetaData(const QString &key) const
+{
+ Q_UNUSED(key);
+ return QVariant();
+}
+
+QStringList QT7PlayerMetaDataControl::availableExtendedMetaData() const
+{
+ return QStringList();
+}
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+
+static QString stripCopyRightSymbol(const QString &key)
+{
+ return key.right(key.length()-1);
+}
+
+static QString convertQuickTimeKeyToUserKey(const QString &key)
+{
+ if (key == QLatin1String("com.apple.quicktime.displayname"))
+ return QLatin1String("nam");
+ else if (key == QLatin1String("com.apple.quicktime.album"))
+ return QLatin1String("alb");
+ else if (key == QLatin1String("com.apple.quicktime.artist"))
+ return QLatin1String("ART");
+ else
+ return QLatin1String("???");
+}
+
+static OSStatus readMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, QTPropertyClass propClass,
+ QTPropertyID id, QTPropertyValuePtr *value, ByteCount *size)
+{
+ QTPropertyValueType type;
+ ByteCount propSize;
+ UInt32 propFlags;
+ OSStatus err = QTMetaDataGetItemPropertyInfo(metaDataRef, item, propClass, id, &type, &propSize, &propFlags);
+
+ if (err == noErr) {
+ *value = malloc(propSize);
+ if (*value != 0) {
+ err = QTMetaDataGetItemProperty(metaDataRef, item, propClass, id, propSize, *value, size);
+
+ if (err == noErr && (type == 'code' || type == 'itsk' || type == 'itlk')) {
+ // convert from native endian to big endian
+ OSTypePtr pType = (OSTypePtr)*value;
+ *pType = EndianU32_NtoB(*pType);
+ }
+ }
+ else
+ return -1;
+ }
+
+ return err;
+}
+
+static UInt32 getMetaType(QTMetaDataRef metaDataRef, QTMetaDataItem item)
+{
+ QTPropertyValuePtr value = 0;
+ ByteCount ignore = 0;
+ OSStatus err = readMetaValue(
+ metaDataRef, item, kPropertyClass_MetaDataItem, kQTMetaDataItemPropertyID_DataType, &value, &ignore);
+
+ if (err == noErr) {
+ UInt32 type = *((UInt32 *) value);
+ if (value)
+ free(value);
+ return type;
+ }
+
+ return 0;
+}
+
+static QString cFStringToQString(CFStringRef str)
+{
+ if(!str)
+ return QString();
+ CFIndex length = CFStringGetLength(str);
+ const UniChar *chars = CFStringGetCharactersPtr(str);
+ if (chars)
+ return QString(reinterpret_cast<const QChar *>(chars), length);
+
+ QVarLengthArray<UniChar> buffer(length);
+ CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data());
+ return QString(reinterpret_cast<const QChar *>(buffer.constData()), length);
+}
+
+
+static QString getMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, SInt32 id)
+{
+ QTPropertyValuePtr value = 0;
+ ByteCount size = 0;
+ OSStatus err = readMetaValue(metaDataRef, item, kPropertyClass_MetaDataItem, id, &value, &size);
+ QString string;
+
+ if (err == noErr) {
+ UInt32 dataType = getMetaType(metaDataRef, item);
+ switch (dataType){
+ case kQTMetaDataTypeUTF8:
+ case kQTMetaDataTypeMacEncodedText:
+ string = cFStringToQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF8, false));
+ break;
+ case kQTMetaDataTypeUTF16BE:
+ string = cFStringToQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF16BE, false));
+ break;
+ default:
+ break;
+ }
+
+ if (value)
+ free(value);
+ }
+
+ return string;
+}
+
+
+static void readFormattedData(QTMetaDataRef metaDataRef, OSType format, QMultiMap<QString, QString> &result)
+{
+ QTMetaDataItem item = kQTMetaDataItemUninitialized;
+ OSStatus err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item);
+ while (err == noErr){
+ QString key = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Key);
+ if (format == kQTMetaDataStorageFormatQuickTime)
+ key = convertQuickTimeKeyToUserKey(key);
+ else
+ key = stripCopyRightSymbol(key);
+
+ if (!result.contains(key)){
+ QString val = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Value);
+ result.insert(key, val);
+ }
+ err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item);
+ }
+}
+#endif
+
+
+void QT7PlayerMetaDataControl::updateTags()
+{
+ bool wasEmpty = m_tags.isEmpty();
+ m_tags.clear();
+
+ QTMovie *movie = (QTMovie*)m_session->movie();
+
+ if (movie) {
+ QMultiMap<QString, QString> metaMap;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QTMetaDataRef metaDataRef;
+ OSStatus err = QTCopyMovieMetaData([movie quickTimeMovie], &metaDataRef);
+ if (err == noErr) {
+ readFormattedData(metaDataRef, kQTMetaDataStorageFormatUserData, metaMap);
+ readFormattedData(metaDataRef, kQTMetaDataStorageFormatQuickTime, metaMap);
+ readFormattedData(metaDataRef, kQTMetaDataStorageFormatiTunes, metaMap);
+ }
+#else
+ AutoReleasePool pool;
+ NSString *name = [movie attributeForKey:@"QTMovieDisplayNameAttribute"];
+ metaMap.insert(QLatin1String("nam"), QString::fromUtf8([name UTF8String]));
+#endif // QUICKTIME_C_API_AVAILABLE
+
+ m_tags.insert(QtMultimediaKit::AlbumArtist, metaMap.value(QLatin1String("ART")));
+ m_tags.insert(QtMultimediaKit::AlbumTitle, metaMap.value(QLatin1String("alb")));
+ m_tags.insert(QtMultimediaKit::Title, metaMap.value(QLatin1String("nam")));
+ m_tags.insert(QtMultimediaKit::Date, metaMap.value(QLatin1String("day")));
+ m_tags.insert(QtMultimediaKit::Genre, metaMap.value(QLatin1String("gnre")));
+ m_tags.insert(QtMultimediaKit::TrackNumber, metaMap.value(QLatin1String("trk")));
+ m_tags.insert(QtMultimediaKit::Description, metaMap.value(QLatin1String("des")));
+ }
+
+ if (!wasEmpty || !m_tags.isEmpty())
+ emit metaDataChanged();
+}
+
+#include "moc_qt7playermetadata.cpp"
diff --git a/src/plugins/qt7/mediaplayer/qt7playerservice.h b/src/plugins/qt7/mediaplayer/qt7playerservice.h
new file mode 100644
index 000000000..65415f0a9
--- /dev/null
+++ b/src/plugins/qt7/mediaplayer/qt7playerservice.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** 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$
+** 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 QT7PLAYERSERVICE_H
+#define QT7PLAYERSERVICE_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qset.h>
+#include <qmediaservice.h>
+
+
+QT_BEGIN_NAMESPACE
+class QMediaMetaData;
+class QMediaPlayerControl;
+class QMediaPlaylist;
+class QMediaPlaylistNavigator;
+class QT7PlayerControl;
+class QT7PlayerMetaDataControl;
+class QT7VideoWindowControl;
+class QT7VideoWidgetControl;
+class QT7VideoRendererControl;
+class QT7VideoOutput;
+class QT7PlayerSession;
+
+class QT7PlayerService : public QMediaService
+{
+Q_OBJECT
+public:
+ QT7PlayerService(QObject *parent = 0);
+ ~QT7PlayerService();
+
+ QMediaControl* requestControl(const char *name);
+ void releaseControl(QMediaControl *control);
+
+private:
+ QT7PlayerSession *m_session;
+ QT7PlayerControl *m_control;
+ QMediaControl * m_videoOutput;
+ QT7PlayerMetaDataControl *m_playerMetaDataControl;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qt7/mediaplayer/qt7playerservice.mm b/src/plugins/qt7/mediaplayer/qt7playerservice.mm
new file mode 100644
index 000000000..39d06a4f3
--- /dev/null
+++ b/src/plugins/qt7/mediaplayer/qt7playerservice.mm
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <QtCore/qvariant.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/qwidget.h>
+
+#include "qt7backend.h"
+#include "qt7playerservice.h"
+#include "qt7playercontrol.h"
+#include "qt7playersession.h"
+#include "qt7videooutput.h"
+#include "qt7movieviewoutput.h"
+#include "qt7movieviewrenderer.h"
+#include "qt7movierenderer.h"
+#include "qt7movievideowidget.h"
+#include "qt7playermetadata.h"
+
+#include <qmediaplaylistnavigator.h>
+#include <qmediaplaylist.h>
+
+QT_USE_NAMESPACE
+
+QT7PlayerService::QT7PlayerService(QObject *parent):
+ QMediaService(parent),
+ m_videoOutput(0)
+{
+ m_session = new QT7PlayerSession(this);
+
+ m_control = new QT7PlayerControl(this);
+ m_control->setSession(m_session);
+
+ m_playerMetaDataControl = new QT7PlayerMetaDataControl(m_session, this);
+ connect(m_control, SIGNAL(mediaChanged(QMediaContent)), m_playerMetaDataControl, SLOT(updateTags()));
+}
+
+QT7PlayerService::~QT7PlayerService()
+{
+}
+
+QMediaControl *QT7PlayerService::requestControl(const char *name)
+{
+ if (qstrcmp(name, QMediaPlayerControl_iid) == 0)
+ return m_control;
+
+ if (qstrcmp(name, QMetaDataReaderControl_iid) == 0)
+ return m_playerMetaDataControl;
+
+#ifndef QT_NO_OPENGL
+ if (!m_videoOutput) {
+ if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
+#if defined(QT_MAC_USE_COCOA)
+ m_videoOutput = new QT7MovieViewOutput(this);
+#endif
+ }
+
+ if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+#ifdef QUICKTIME_C_API_AVAILABLE
+ m_videoOutput = new QT7MovieRenderer(this);
+#else
+ m_videoOutput = new QT7MovieViewRenderer(this);
+#endif
+ }
+
+ if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
+#ifdef QUICKTIME_C_API_AVAILABLE
+ m_videoOutput = new QT7MovieVideoWidget(this);
+#endif
+ }
+
+ if (m_videoOutput) {
+ QT7VideoOutput *videoOutput = qobject_cast<QT7VideoOutput*>(m_videoOutput);
+ m_session->setVideoOutput(videoOutput);
+ return m_videoOutput;
+ }
+ }
+#endif // !defined(QT_NO_OPENGL)
+
+ return 0;
+}
+
+void QT7PlayerService::releaseControl(QMediaControl *control)
+{
+ if (m_videoOutput == control) {
+ m_videoOutput = 0;
+ m_session->setVideoOutput(0);
+ delete control;
+ }
+}
+
+#include "moc_qt7playerservice.cpp"
diff --git a/src/plugins/qt7/mediaplayer/qt7playersession.h b/src/plugins/qt7/mediaplayer/qt7playersession.h
new file mode 100644
index 000000000..0b18748a4
--- /dev/null
+++ b/src/plugins/qt7/mediaplayer/qt7playersession.h
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QT7PLAYERSESSION_H
+#define QT7PLAYERSESSION_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qset.h>
+#include <QtCore/qresource.h>
+
+#include <qmediaplayercontrol.h>
+#include <qmediaplayer.h>
+
+#include <QtGui/qmacdefines_mac.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QT7PlayerControl;
+class QMediaPlaylist;
+class QMediaPlaylistNavigator;
+class QT7VideoOutput;
+class QT7PlayerSession;
+class QT7PlayerService;
+
+
+class QT7PlayerSession : public QObject
+{
+ Q_OBJECT
+public:
+ QT7PlayerSession(QObject *parent = 0);
+ ~QT7PlayerSession();
+
+ void *movie() const;
+
+ void setControl(QT7PlayerControl *control);
+
+ void setVideoOutput(QT7VideoOutput *output);
+
+ QMediaPlayer::State state() const;
+ QMediaPlayer::MediaStatus mediaStatus() const;
+
+ QMediaContent media() const;
+ const QIODevice *mediaStream() const;
+ void setMedia(const QMediaContent &content, QIODevice *stream);
+
+ qint64 position() const;
+ qint64 duration() const;
+
+ int bufferStatus() const;
+
+ int volume() const;
+ bool isMuted() const;
+
+ bool isAudioAvailable() const;
+ bool isVideoAvailable() const;
+
+ bool isSeekable() const;
+ QMediaTimeRange availablePlaybackRanges() const;
+
+ qreal playbackRate() const;
+
+public slots:
+ void setPlaybackRate(qreal rate);
+
+ void setPosition(qint64 pos);
+
+ void play();
+ void pause();
+ void stop();
+
+ void setVolume(int volume);
+ void setMuted(bool muted);
+
+ void processEOS();
+ void processLoadStateChange();
+ void processVolumeChange();
+ void processNaturalSizeChange();
+ void processPositionChange();
+
+signals:
+ void positionChanged(qint64 position);
+ void durationChanged(qint64 duration);
+ void stateChanged(QMediaPlayer::State newState);
+ void mediaStatusChanged(QMediaPlayer::MediaStatus status);
+ void volumeChanged(int volume);
+ void mutedChanged(bool muted);
+ void audioAvailableChanged(bool audioAvailable);
+ void videoAvailableChanged(bool videoAvailable);
+ void error(int error, const QString &errorString);
+
+private:
+ class ResourceHandler {
+ public:
+ ResourceHandler():resource(0) {}
+ ~ResourceHandler() { clear(); }
+ void setResourceFile(const QString &file) {
+ if (resource) {
+ if (resource->fileName() == file)
+ return;
+ delete resource;
+ rawData.clear();
+ }
+ resource = new QResource(file);
+ }
+ bool isValid() const { return resource && resource->isValid() && resource->data() != 0; }
+ const uchar *data() {
+ if (!isValid())
+ return 0;
+ if (resource->isCompressed()) {
+ if (rawData.size() == 0)
+ rawData = qUncompress(resource->data(), resource->size());
+ return (const uchar *)rawData.constData();
+ }
+ return resource->data();
+ }
+ qint64 size() {
+ if (data() == 0)
+ return 0;
+ return resource->isCompressed() ? rawData.size() : resource->size();
+ }
+ void clear() {
+ delete resource;
+ rawData.clear();
+ }
+ QResource *resource;
+ QByteArray rawData;
+ };
+
+ void openMovie(bool tryAsync);
+
+ void *m_QTMovie;
+ void *m_movieObserver;
+
+ QMediaPlayer::State m_state;
+ QMediaPlayer::MediaStatus m_mediaStatus;
+ QIODevice *m_mediaStream;
+ QMediaContent m_resources;
+ ResourceHandler m_resourceHandler;
+
+ QT7VideoOutput * m_videoOutput;
+
+ bool m_muted;
+ bool m_tryingAsync;
+ int m_volume;
+ qreal m_rate;
+
+ qint64 m_duration;
+ bool m_videoAvailable;
+ bool m_audioAvailable;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qt7/mediaplayer/qt7playersession.mm b/src/plugins/qt7/mediaplayer/qt7playersession.mm
new file mode 100644
index 000000000..c4eef5c9d
--- /dev/null
+++ b/src/plugins/qt7/mediaplayer/qt7playersession.mm
@@ -0,0 +1,751 @@
+/****************************************************************************
+**
+** 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$
+** 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$
+**
+****************************************************************************/
+
+#import <QTKit/QTDataReference.h>
+#import <QTKit/QTMovie.h>
+
+#include "qt7backend.h"
+
+#include "qt7playersession.h"
+#include "qt7playercontrol.h"
+#include "qt7videooutput.h"
+
+#include <QtNetwork/qnetworkcookie.h>
+#include <qmediaplaylistnavigator.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Foundation/Foundation.h>
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qurl.h>
+
+#include <QtCore/qdebug.h>
+
+QT_USE_NAMESPACE
+
+//#define QT_DEBUG_QT7
+
+@interface QTMovieObserver : NSObject
+{
+@private
+ QT7PlayerSession *m_session;
+ QTMovie *m_movie;
+}
+
+- (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session;
+- (void) setMovie:(QTMovie *)movie;
+- (void) processEOS:(NSNotification *)notification;
+- (void) processLoadStateChange:(NSNotification *)notification;
+- (void) processVolumeChange:(NSNotification *)notification;
+- (void) processNaturalSizeChange :(NSNotification *)notification;
+- (void) processPositionChange :(NSNotification *)notification;
+@end
+
+@implementation QTMovieObserver
+
+- (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session
+{
+ if (!(self = [super init]))
+ return nil;
+
+ self->m_session = session;
+ return self;
+}
+
+- (void) setMovie:(QTMovie *)movie
+{
+ if (m_movie == movie)
+ return;
+
+ if (m_movie) {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [m_movie release];
+ }
+
+ m_movie = movie;
+
+ if (movie) {
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(processEOS:)
+ name:QTMovieDidEndNotification
+ object:m_movie];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(processLoadStateChange:)
+ name:QTMovieLoadStateDidChangeNotification
+ object:m_movie];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(processVolumeChange:)
+ name:QTMovieVolumeDidChangeNotification
+ object:m_movie];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(processPositionChange:)
+ name:QTMovieTimeDidChangeNotification
+ object:m_movie];
+
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) {
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(processNaturalSizeChange:)
+ name:@"QTMovieNaturalSizeDidChangeNotification"
+ object:m_movie];
+
+ }
+ else {
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(processNaturalSizeChange:)
+ name:QTMovieEditedNotification
+ object:m_movie];
+ }
+
+ [movie retain];
+ }
+}
+
+- (void) processEOS:(NSNotification *)notification
+{
+ Q_UNUSED(notification);
+ QMetaObject::invokeMethod(m_session, "processEOS", Qt::AutoConnection);
+}
+
+- (void) processLoadStateChange:(NSNotification *)notification
+{
+ Q_UNUSED(notification);
+ QMetaObject::invokeMethod(m_session, "processLoadStateChange", Qt::AutoConnection);
+}
+
+- (void) processVolumeChange:(NSNotification *)notification
+{
+ Q_UNUSED(notification);
+ QMetaObject::invokeMethod(m_session, "processVolumeChange", Qt::AutoConnection);
+}
+
+- (void) processNaturalSizeChange :(NSNotification *)notification
+{
+ Q_UNUSED(notification);
+ QMetaObject::invokeMethod(m_session, "processNaturalSizeChange", Qt::AutoConnection);
+}
+
+- (void) processPositionChange :(NSNotification *)notification
+{
+ Q_UNUSED(notification);
+ QMetaObject::invokeMethod(m_session, "processPositionChange", Qt::AutoConnection);
+}
+
+@end
+
+static inline NSString *qString2CFStringRef(const QString &string)
+{
+ return [NSString stringWithCharacters:reinterpret_cast<const UniChar *>(string.unicode()) length:string.length()];
+}
+
+QT7PlayerSession::QT7PlayerSession(QObject *parent)
+ : QObject(parent)
+ , m_QTMovie(0)
+ , m_state(QMediaPlayer::StoppedState)
+ , m_mediaStatus(QMediaPlayer::NoMedia)
+ , m_mediaStream(0)
+ , m_videoOutput(0)
+ , m_muted(false)
+ , m_tryingAsync(false)
+ , m_volume(100)
+ , m_rate(1.0)
+ , m_duration(0)
+ , m_videoAvailable(false)
+ , m_audioAvailable(false)
+{
+ m_movieObserver = [[QTMovieObserver alloc] initWithPlayerSession:this];
+}
+
+QT7PlayerSession::~QT7PlayerSession()
+{
+ if (m_videoOutput)
+ m_videoOutput->setMovie(0);
+
+ [(QTMovieObserver*)m_movieObserver setMovie:nil];
+ [(QTMovieObserver*)m_movieObserver release];
+ [(QTMovie*)m_QTMovie release];
+}
+
+void *QT7PlayerSession::movie() const
+{
+ return m_QTMovie;
+}
+
+void QT7PlayerSession::setVideoOutput(QT7VideoOutput *output)
+{
+ if (m_videoOutput == output)
+ return;
+
+ if (m_videoOutput)
+ m_videoOutput->setMovie(0);
+
+ m_videoOutput = output;
+
+ if (m_videoOutput && m_state != QMediaPlayer::StoppedState)
+ m_videoOutput->setMovie(m_QTMovie);
+}
+
+qint64 QT7PlayerSession::position() const
+{
+ if (!m_QTMovie)
+ return 0;
+
+ QTTime qtTime = [(QTMovie*)m_QTMovie currentTime];
+
+ return static_cast<quint64>(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f);
+}
+
+qint64 QT7PlayerSession::duration() const
+{
+ if (!m_QTMovie)
+ return 0;
+
+ QTTime qtTime = [(QTMovie*)m_QTMovie duration];
+
+ return static_cast<quint64>(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f);
+}
+
+QMediaPlayer::State QT7PlayerSession::state() const
+{
+ return m_state;
+}
+
+QMediaPlayer::MediaStatus QT7PlayerSession::mediaStatus() const
+{
+ return m_mediaStatus;
+}
+
+int QT7PlayerSession::bufferStatus() const
+{
+ return 100;
+}
+
+int QT7PlayerSession::volume() const
+{
+ return m_volume;
+}
+
+bool QT7PlayerSession::isMuted() const
+{
+ return m_muted;
+}
+
+bool QT7PlayerSession::isSeekable() const
+{
+ return true;
+}
+
+#ifndef QUICKTIME_C_API_AVAILABLE
+@interface QTMovie(QtExtensions)
+- (NSArray*)loadedRanges;
+- (QTTime)maxTimeLoaded;
+@end
+#endif
+
+QMediaTimeRange QT7PlayerSession::availablePlaybackRanges() const
+{
+ QTMovie *movie = (QTMovie*)m_QTMovie;
+#ifndef QUICKTIME_C_API_AVAILABLE
+ AutoReleasePool pool;
+ if ([movie respondsToSelector:@selector(loadedRanges)]) {
+ QMediaTimeRange rc;
+ NSArray *r = [movie loadedRanges];
+ for (NSValue *tr in r) {
+ QTTimeRange timeRange = [tr QTTimeRangeValue];
+ qint64 startTime = qint64(float(timeRange.time.timeValue) / timeRange.time.timeScale * 1000.0);
+ rc.addInterval(startTime, startTime + qint64(float(timeRange.duration.timeValue) / timeRange.duration.timeScale * 1000.0));
+ }
+ return rc;
+ }
+ else if ([movie respondsToSelector:@selector(maxTimeLoaded)]) {
+ QTTime loadedTime = [movie maxTimeLoaded];
+ return QMediaTimeRange(0, qint64(float(loadedTime.timeValue) / loadedTime.timeScale * 1000.0));
+ }
+#else
+ TimeValue loadedTime;
+ TimeScale scale;
+ Movie m = [movie quickTimeMovie];
+ if (GetMaxLoadedTimeInMovie(m, &loadedTime) == noErr) {
+ scale = GetMovieTimeScale(m);
+ return QMediaTimeRange(0, qint64(float(loadedTime) / scale * 1000.0f));
+ }
+#endif
+ return QMediaTimeRange(0, duration());
+}
+
+qreal QT7PlayerSession::playbackRate() const
+{
+ return m_rate;
+}
+
+void QT7PlayerSession::setPlaybackRate(qreal rate)
+{
+ if (qFuzzyCompare(m_rate, rate))
+ return;
+
+ m_rate = rate;
+
+ if (m_QTMovie != 0 && m_state == QMediaPlayer::PlayingState) {
+ AutoReleasePool pool;
+ float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue];
+ [(QTMovie*)m_QTMovie setRate:preferredRate * m_rate];
+ }
+}
+
+void QT7PlayerSession::setPosition(qint64 pos)
+{
+ if ( !isSeekable() || pos == position())
+ return;
+
+ if (duration() > 0)
+ pos = qMin(pos, duration());
+
+ QTTime newQTTime = [(QTMovie*)m_QTMovie currentTime];
+ newQTTime.timeValue = (pos / 1000.0f) * newQTTime.timeScale;
+ [(QTMovie*)m_QTMovie setCurrentTime:newQTTime];
+
+ //reset the EndOfMedia status position is changed after playback is finished
+ if (m_mediaStatus == QMediaPlayer::EndOfMedia)
+ processLoadStateChange();
+}
+
+void QT7PlayerSession::play()
+{
+ if (m_state == QMediaPlayer::PlayingState)
+ return;
+
+ m_state = QMediaPlayer::PlayingState;
+
+ if (m_videoOutput)
+ m_videoOutput->setMovie(m_QTMovie);
+
+ //reset the EndOfMedia status if the same file is played again
+ if (m_mediaStatus == QMediaPlayer::EndOfMedia)
+ processLoadStateChange();
+
+ AutoReleasePool pool;
+ float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue];
+ [(QTMovie*)m_QTMovie setRate:preferredRate * m_rate];
+
+ processLoadStateChange();
+ emit stateChanged(m_state);
+}
+
+void QT7PlayerSession::pause()
+{
+ if (m_state == QMediaPlayer::PausedState)
+ return;
+
+ m_state = QMediaPlayer::PausedState;
+
+ if (m_videoOutput)
+ m_videoOutput->setMovie(m_QTMovie);
+
+ //reset the EndOfMedia status if the same file is played again
+ if (m_mediaStatus == QMediaPlayer::EndOfMedia)
+ processLoadStateChange();
+
+ [(QTMovie*)m_QTMovie setRate:0];
+
+ processLoadStateChange();
+ emit stateChanged(m_state);
+}
+
+void QT7PlayerSession::stop()
+{
+ if (m_state == QMediaPlayer::StoppedState)
+ return;
+
+ m_state = QMediaPlayer::StoppedState;
+
+ [(QTMovie*)m_QTMovie setRate:0];
+ setPosition(0);
+
+ if (m_videoOutput)
+ m_videoOutput->setMovie(0);
+
+ processLoadStateChange();
+ emit stateChanged(m_state);
+ emit positionChanged(position());
+}
+
+void QT7PlayerSession::setVolume(int volume)
+{
+ if (m_volume == volume)
+ return;
+
+ m_volume = volume;
+
+ if (m_QTMovie != 0)
+ [(QTMovie*)m_QTMovie setVolume:m_volume / 100.0f];
+
+ emit volumeChanged(m_volume);
+}
+
+void QT7PlayerSession::setMuted(bool muted)
+{
+ if (m_muted == muted)
+ return;
+
+ m_muted = muted;
+
+ if (m_QTMovie != 0)
+ [(QTMovie*)m_QTMovie setMuted:m_muted];
+
+ emit mutedChanged(muted);
+}
+
+QMediaContent QT7PlayerSession::media() const
+{
+ return m_resources;
+}
+
+const QIODevice *QT7PlayerSession::mediaStream() const
+{
+ return m_mediaStream;
+}
+
+void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream)
+{
+ AutoReleasePool pool;
+
+#ifdef QT_DEBUG_QT7
+ qDebug() << Q_FUNC_INFO << content.canonicalUrl();
+#endif
+
+ if (m_QTMovie) {
+ [(QTMovieObserver*)m_movieObserver setMovie:nil];
+
+ if (m_videoOutput)
+ m_videoOutput->setMovie(0);
+
+ [(QTMovie*)m_QTMovie release];
+ m_QTMovie = 0;
+ m_resourceHandler.clear();
+ }
+
+ m_resources = content;
+ m_mediaStream = stream;
+ QMediaPlayer::MediaStatus oldMediaStatus = m_mediaStatus;
+
+ if (content.isNull()) {
+ m_mediaStatus = QMediaPlayer::NoMedia;
+ if (m_state != QMediaPlayer::StoppedState)
+ emit stateChanged(m_state = QMediaPlayer::StoppedState);
+
+ if (m_mediaStatus != oldMediaStatus)
+ emit mediaStatusChanged(m_mediaStatus);
+ emit positionChanged(position());
+ return;
+ }
+
+ m_mediaStatus = QMediaPlayer::LoadingMedia;
+ if (m_mediaStatus != oldMediaStatus)
+ emit mediaStatusChanged(m_mediaStatus);
+
+ QNetworkRequest request = content.canonicalResource().request();
+
+ QVariant cookies = request.header(QNetworkRequest::CookieHeader);
+ if (cookies.isValid()) {
+ NSHTTPCookieStorage *store = [NSHTTPCookieStorage sharedHTTPCookieStorage];
+ QList<QNetworkCookie> cookieList = cookies.value<QList<QNetworkCookie> >();
+
+ foreach (const QNetworkCookie &requestCookie, cookieList) {
+ NSMutableDictionary *p = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ qString2CFStringRef(requestCookie.name()), NSHTTPCookieName,
+ qString2CFStringRef(requestCookie.value()), NSHTTPCookieValue,
+ qString2CFStringRef(requestCookie.domain()), NSHTTPCookieDomain,
+ qString2CFStringRef(requestCookie.path()), NSHTTPCookiePath,
+ nil
+ ];
+ if (requestCookie.isSessionCookie())
+ [p setObject:[NSString stringWithUTF8String:"TRUE"] forKey:NSHTTPCookieDiscard];
+ else
+ [p setObject:[NSDate dateWithTimeIntervalSince1970:requestCookie.expirationDate().toTime_t()] forKey:NSHTTPCookieExpires];
+
+ [store setCookie:[NSHTTPCookie cookieWithProperties:p]];
+ }
+ }
+
+ // Attempt multiple times to open the movie.
+ // First try - attempt open in async mode
+ openMovie(true);
+
+ emit positionChanged(position());
+}
+
+void QT7PlayerSession::openMovie(bool tryAsync)
+{
+ QUrl requestUrl = m_resources.canonicalResource().request().url();
+ if (requestUrl.scheme().isEmpty())
+ requestUrl.setScheme(QLatin1String("file"));
+
+#ifdef QT_DEBUG_QT7
+ qDebug() << Q_FUNC_INFO << requestUrl;
+#endif
+
+ NSError *err = 0;
+ NSString *urlString = [NSString stringWithUTF8String:requestUrl.toEncoded().constData()];
+
+ NSMutableDictionary *attr = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute,
+ [NSNumber numberWithBool:YES], QTMovieIsActiveAttribute,
+ [NSNumber numberWithBool:YES], QTMovieResolveDataRefsAttribute,
+ [NSNumber numberWithBool:YES], QTMovieDontInteractWithUserAttribute,
+ nil];
+
+
+ if (requestUrl.scheme() == QLatin1String("qrc")) {
+ // Load from Qt resource
+ m_resourceHandler.setResourceFile(QLatin1Char(':') + requestUrl.path());
+ if (!m_resourceHandler.isValid()) {
+ emit error(QMediaPlayer::FormatError, tr("Attempting to play invalid Qt resource"));
+ return;
+ }
+
+ CFDataRef resourceData =
+ CFDataCreateWithBytesNoCopy(0, m_resourceHandler.data(), m_resourceHandler.size(), kCFAllocatorNull);
+
+ QTDataReference *dataReference =
+ [QTDataReference dataReferenceWithReferenceToData:(NSData*)resourceData
+ name:qString2CFStringRef(requestUrl.path())
+ MIMEType:nil];
+
+ [attr setObject:dataReference forKey:QTMovieDataReferenceAttribute];
+
+ CFRelease(resourceData);
+ } else {
+ [attr setObject:[NSURL URLWithString:urlString] forKey:QTMovieURLAttribute];
+ }
+
+ if (tryAsync && QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) {
+ [attr setObject:[NSNumber numberWithBool:YES] forKey:@"QTMovieOpenAsyncRequiredAttribute"];
+// XXX: This is disabled for now. causes some problems with video playback for some formats
+// [attr setObject:[NSNumber numberWithBool:YES] forKey:@"QTMovieOpenForPlaybackAttribute"];
+ m_tryingAsync = true;
+ }
+ else
+ m_tryingAsync = false;
+
+ m_QTMovie = [QTMovie movieWithAttributes:attr error:&err];
+ if (err != nil) {
+ // First attempt to test for inability to perform async
+// if ([err code] == QTErrorMovieOpeningCannotBeAsynchronous) { XXX: error code unknown!
+ if (m_tryingAsync) {
+ m_tryingAsync = false;
+ err = nil;
+ [attr removeObjectForKey:@"QTMovieOpenAsyncRequiredAttribute"];
+ m_QTMovie = [QTMovie movieWithAttributes:attr error:&err];
+ }
+ }
+
+ if (err != nil) {
+ m_QTMovie = 0;
+ QString description = QString::fromUtf8([[err localizedDescription] UTF8String]);
+ emit error(QMediaPlayer::FormatError, description);
+
+#ifdef QT_DEBUG_QT7
+ qDebug() << Q_FUNC_INFO << description;
+#endif
+ }
+ else {
+ [(QTMovie*)m_QTMovie retain];
+
+ [(QTMovieObserver*)m_movieObserver setMovie:(QTMovie*)m_QTMovie];
+
+ if (m_state != QMediaPlayer::StoppedState && m_videoOutput)
+ m_videoOutput->setMovie(m_QTMovie);
+
+ processLoadStateChange();
+
+ [(QTMovie*)m_QTMovie setMuted:m_muted];
+ [(QTMovie*)m_QTMovie setVolume:m_volume / 100.0f];
+ }
+}
+
+bool QT7PlayerSession::isAudioAvailable() const
+{
+ if (!m_QTMovie)
+ return false;
+
+ AutoReleasePool pool;
+ return [[(QTMovie*)m_QTMovie attributeForKey:@"QTMovieHasAudioAttribute"] boolValue] == YES;
+}
+
+bool QT7PlayerSession::isVideoAvailable() const
+{
+ if (!m_QTMovie)
+ return false;
+
+ AutoReleasePool pool;
+ return [[(QTMovie*)m_QTMovie attributeForKey:@"QTMovieHasVideoAttribute"] boolValue] == YES;
+}
+
+void QT7PlayerSession::processEOS()
+{
+#ifdef QT_DEBUG_QT7
+ qDebug() << Q_FUNC_INFO;
+#endif
+ emit positionChanged(position());
+ m_mediaStatus = QMediaPlayer::EndOfMedia;
+ if (m_videoOutput)
+ m_videoOutput->setMovie(0);
+ emit stateChanged(m_state = QMediaPlayer::StoppedState);
+ emit mediaStatusChanged(m_mediaStatus);
+}
+
+void QT7PlayerSession::processLoadStateChange()
+{
+ if (!m_QTMovie)
+ return;
+
+ AutoReleasePool pool;
+
+ long state = [[(QTMovie*)m_QTMovie attributeForKey:QTMovieLoadStateAttribute] longValue];
+
+#ifdef QT_DEBUG_QT7
+ qDebug() << Q_FUNC_INFO << state;
+#endif
+
+#ifndef QUICKTIME_C_API_AVAILABLE
+ enum {
+ kMovieLoadStateError = -1L,
+ kMovieLoadStateLoading = 1000,
+ kMovieLoadStateLoaded = 2000,
+ kMovieLoadStatePlayable = 10000,
+ kMovieLoadStatePlaythroughOK = 20000,
+ kMovieLoadStateComplete = 100000
+ };
+#endif
+
+ if (state == kMovieLoadStateError) {
+ if (m_tryingAsync) {
+ NSError *error = [(QTMovie*)m_QTMovie attributeForKey:@"QTMovieLoadStateErrorAttribute"];
+ if ([error code] == componentNotThreadSafeErr) {
+ // Last Async check, try again with no such flag
+ openMovie(false);
+ }
+ }
+ else {
+ if (m_videoOutput)
+ m_videoOutput->setMovie(0);
+
+ emit error(QMediaPlayer::FormatError, tr("Failed to load media"));
+ emit mediaStatusChanged(m_mediaStatus = QMediaPlayer::InvalidMedia);
+ emit stateChanged(m_state = QMediaPlayer::StoppedState);
+ }
+
+ return;
+ }
+
+ QMediaPlayer::MediaStatus newStatus = QMediaPlayer::NoMedia;
+ bool isPlaying = (m_state != QMediaPlayer::StoppedState);
+
+ if (state >= kMovieLoadStatePlaythroughOK) {
+ newStatus = isPlaying ? QMediaPlayer::BufferedMedia : QMediaPlayer::LoadedMedia;
+ } else if (state >= kMovieLoadStatePlayable)
+ newStatus = isPlaying ? QMediaPlayer::BufferingMedia : QMediaPlayer::LoadingMedia;
+ else if (state >= kMovieLoadStateLoading) {
+ if (!isPlaying)
+ newStatus = QMediaPlayer::LoadingMedia;
+ else if (m_mediaStatus >= QMediaPlayer::LoadedMedia)
+ newStatus = QMediaPlayer::StalledMedia;
+ else
+ newStatus = QMediaPlayer::LoadingMedia;
+ }
+
+ if (state >= kMovieLoadStatePlayable &&
+ m_state == QMediaPlayer::PlayingState &&
+ [(QTMovie*)m_QTMovie rate] == 0) {
+
+ float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue];
+
+ [(QTMovie*)m_QTMovie setRate:preferredRate * m_rate];
+ }
+
+ if (state >= kMovieLoadStateLoaded) {
+ qint64 currentDuration = duration();
+ if (m_duration != currentDuration)
+ emit durationChanged(m_duration = currentDuration);
+
+ if (m_audioAvailable != isAudioAvailable())
+ emit audioAvailableChanged(m_audioAvailable = !m_audioAvailable);
+
+ if (m_videoAvailable != isVideoAvailable())
+ emit videoAvailableChanged(m_videoAvailable = !m_videoAvailable);
+ }
+
+ if (newStatus != m_mediaStatus)
+ emit mediaStatusChanged(m_mediaStatus = newStatus);
+}
+
+void QT7PlayerSession::processVolumeChange()
+{
+ if (!m_QTMovie)
+ return;
+
+ int newVolume = qRound(100.0f * [((QTMovie*)m_QTMovie) volume]);
+
+ if (newVolume != m_volume) {
+ emit volumeChanged(m_volume = newVolume);
+ }
+}
+
+void QT7PlayerSession::processNaturalSizeChange()
+{
+ AutoReleasePool pool;
+ NSSize size = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue];
+#ifdef QT_DEBUG_QT7
+ qDebug() << Q_FUNC_INFO << QSize(size.width, size.height);
+#endif
+
+ if (m_videoOutput)
+ m_videoOutput->updateNaturalSize(QSize(size.width, size.height));
+}
+
+void QT7PlayerSession::processPositionChange()
+{
+ emit positionChanged(position());
+}
+
+#include "moc_qt7playersession.cpp"
diff --git a/src/plugins/qt7/qcvdisplaylink.h b/src/plugins/qt7/qcvdisplaylink.h
new file mode 100644
index 000000000..536abbf58
--- /dev/null
+++ b/src/plugins/qt7/qcvdisplaylink.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** 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$
+** 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 QCVDISPLAYLINK_H
+#define QCVDISPLAYLINK_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmutex.h>
+
+#include <qmobilityglobal.h>
+
+#include <QuartzCore/CVDisplayLink.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCvDisplayLink : public QObject
+{
+Q_OBJECT
+public:
+ QCvDisplayLink(QObject *parent = 0);
+ virtual ~QCvDisplayLink();
+
+ bool isValid();
+ bool isActive() const;
+
+public slots:
+ void start();
+ void stop();
+
+signals:
+ void tick(const CVTimeStamp &ts);
+
+public:
+ void displayLinkEvent(const CVTimeStamp *);
+
+protected:
+ virtual bool event(QEvent *);
+
+private:
+ CVDisplayLinkRef m_displayLink;
+ QMutex m_displayLinkMutex;
+ bool m_pendingDisplayLinkEvent;
+ bool m_isActive;
+ CVTimeStamp m_frameTimeStamp;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/plugins/qt7/qcvdisplaylink.mm b/src/plugins/qt7/qcvdisplaylink.mm
new file mode 100644
index 000000000..ecc4235bd
--- /dev/null
+++ b/src/plugins/qt7/qcvdisplaylink.mm
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qcvdisplaylink.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdebug.h>
+
+QT_USE_NAMESPACE
+
+static CVReturn CVDisplayLinkCallback(CVDisplayLinkRef displayLink,
+ const CVTimeStamp *inNow,
+ const CVTimeStamp *inOutputTime,
+ CVOptionFlags flagsIn,
+ CVOptionFlags *flagsOut,
+ void *displayLinkContext)
+{
+ Q_UNUSED(displayLink);
+ Q_UNUSED(inNow);
+ Q_UNUSED(flagsIn);
+ Q_UNUSED(flagsOut);
+
+ QCvDisplayLink *link = (QCvDisplayLink *)displayLinkContext;
+
+ link->displayLinkEvent(inOutputTime);
+ return kCVReturnSuccess;
+}
+
+
+QCvDisplayLink::QCvDisplayLink(QObject *parent)
+ :QObject(parent),
+ m_pendingDisplayLinkEvent(false),
+ m_isActive(false)
+{
+ // create display link for the main display
+ CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &m_displayLink);
+ if (m_displayLink) {
+ // set the current display of a display link.
+ CVDisplayLinkSetCurrentCGDisplay(m_displayLink, kCGDirectMainDisplay);
+
+ // set the renderer output callback function
+ CVDisplayLinkSetOutputCallback(m_displayLink, &CVDisplayLinkCallback, this);
+ }
+}
+
+QCvDisplayLink::~QCvDisplayLink()
+{
+ if (m_displayLink) {
+ CVDisplayLinkStop(m_displayLink);
+ CVDisplayLinkRelease(m_displayLink);
+ m_displayLink = NULL;
+ }
+}
+
+bool QCvDisplayLink::isValid()
+{
+ return m_displayLink != 0;
+}
+
+bool QCvDisplayLink::isActive() const
+{
+ return m_isActive;
+}
+
+void QCvDisplayLink::start()
+{
+ if (m_displayLink && !m_isActive) {
+ CVDisplayLinkStart(m_displayLink);
+ m_isActive = true;
+ }
+}
+
+void QCvDisplayLink::stop()
+{
+ if (m_displayLink && m_isActive) {
+ CVDisplayLinkStop(m_displayLink);
+ m_isActive = false;
+ }
+}
+
+void QCvDisplayLink::displayLinkEvent(const CVTimeStamp *ts)
+{
+ // This function is called from a
+ // thread != gui thread. So we post the event.
+ // But we need to make sure that we don't post faster
+ // than the event loop can eat:
+ m_displayLinkMutex.lock();
+ bool pending = m_pendingDisplayLinkEvent;
+ m_pendingDisplayLinkEvent = true;
+ m_frameTimeStamp = *ts;
+ m_displayLinkMutex.unlock();
+
+ if (!pending)
+ qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority);
+}
+
+bool QCvDisplayLink::event(QEvent *event)
+{
+ switch (event->type()){
+ case QEvent::User: {
+ m_displayLinkMutex.lock();
+ m_pendingDisplayLinkEvent = false;
+ CVTimeStamp ts = m_frameTimeStamp;
+ m_displayLinkMutex.unlock();
+
+ emit tick(ts);
+
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+ return QObject::event(event);
+}
+
+#include "moc_qcvdisplaylink.cpp"
+
diff --git a/src/plugins/qt7/qt7.pro b/src/plugins/qt7/qt7.pro
new file mode 100644
index 000000000..db3728c33
--- /dev/null
+++ b/src/plugins/qt7/qt7.pro
@@ -0,0 +1,58 @@
+load(qt_module)
+
+TARGET = qqt7engine
+QT += multimediakit-private network
+PLUGIN_TYPE = mediaservice
+
+load(qt_plugin)
+DESTDIR = $$QT.multimediakit.plugins/$${PLUGIN_TYPE}
+
+!simulator {
+QT += opengl
+}
+
+#DEFINES += QT_DEBUG_QT7
+
+LIBS += -framework AppKit -framework AudioUnit \
+ -framework AudioToolbox -framework CoreAudio \
+ -framework QuartzCore -framework QTKit
+
+# The Quicktime framework is only awailable for 32-bit builds, so we
+# need to check for this before linking against it.
+# QMAKE_MAC_XARCH is not awailable on Tiger, but at the same time,
+# we never build for 64-bit architechtures on Tiger either:
+contains(QMAKE_MAC_XARCH, no) {
+ LIBS += -framework QuickTime
+} else {
+ LIBS += -Xarch_i386 -framework QuickTime -Xarch_ppc -framework QuickTime
+}
+
+HEADERS += \
+ qt7backend.h \
+ qt7videooutput.h \
+ qt7serviceplugin.h
+
+OBJECTIVE_SOURCES += \
+ qt7backend.mm \
+ qt7serviceplugin.mm
+
+!simulator {
+ HEADERS += \
+ qt7movieviewoutput.h \
+ qt7movievideowidget.h \
+ qt7movieviewrenderer.h \
+ qt7movierenderer.h \
+ qt7ciimagevideobuffer.h \
+ qcvdisplaylink.h
+
+ OBJECTIVE_SOURCES += \
+ qt7movieviewoutput.mm \
+ qt7movievideowidget.mm \
+ qt7movieviewrenderer.mm \
+ qt7movierenderer.mm \
+ qt7videooutput.mm \
+ qt7ciimagevideobuffer.mm \
+ qcvdisplaylink.mm
+}
+
+include(mediaplayer/mediaplayer.pri)
diff --git a/src/plugins/qt7/qt7backend.h b/src/plugins/qt7/qt7backend.h
new file mode 100644
index 000000000..d52f0396a
--- /dev/null
+++ b/src/plugins/qt7/qt7backend.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** 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$
+** 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 QT7BACKEND_H
+#define QT7BACKEND_H
+
+#include "qmobilityglobal.h"
+
+#include <QtCore/QString>
+
+#ifndef Q_WS_SIMULATOR
+#ifndef Q_WS_MAC64
+#define QUICKTIME_C_API_AVAILABLE
+#endif
+#endif // !defined(Q_WS_SIMULATOR)
+
+QT_BEGIN_NAMESPACE
+
+class AutoReleasePool
+{
+private:
+ void *pool;
+public:
+ AutoReleasePool();
+ ~AutoReleasePool();
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qt7/qt7backend.mm b/src/plugins/qt7/qt7backend.mm
new file mode 100644
index 000000000..83a044dab
--- /dev/null
+++ b/src/plugins/qt7/qt7backend.mm
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qt7backend.h"
+
+#import <Foundation/NSAutoreleasePool.h>
+#include <CoreFoundation/CFBase.h>
+
+
+QT_BEGIN_NAMESPACE
+
+AutoReleasePool::AutoReleasePool()
+{
+ pool = (void*)[[NSAutoreleasePool alloc] init];
+}
+
+AutoReleasePool::~AutoReleasePool()
+{
+ [(NSAutoreleasePool*)pool release];
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qt7/qt7ciimagevideobuffer.h b/src/plugins/qt7/qt7ciimagevideobuffer.h
new file mode 100644
index 000000000..d6ae19f80
--- /dev/null
+++ b/src/plugins/qt7/qt7ciimagevideobuffer.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QT7CIIMAGEVIDEOBUFFER_H
+#define QT7CIIMAGEVIDEOBUFFER_H
+
+#include "qt7backend.h"
+#import <QTKit/QTKit.h>
+
+#include <QtCore/qvariant.h>
+#include <qabstractvideobuffer.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.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QT7CIImageVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ QT7CIImageVideoBuffer(CIImage *image);
+
+ virtual ~QT7CIImageVideoBuffer();
+
+ MapMode mapMode() const;
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine);
+ void unmap();
+ QVariant handle() const;
+
+private:
+ CIImage *m_image;
+ NSBitmapImageRep *m_buffer;
+ MapMode m_mode;
+};
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qt7/qt7ciimagevideobuffer.mm b/src/plugins/qt7/qt7ciimagevideobuffer.mm
new file mode 100644
index 000000000..e7758c0a6
--- /dev/null
+++ b/src/plugins/qt7/qt7ciimagevideobuffer.mm
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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 "qt7ciimagevideobuffer.h"
+
+#include <QuartzCore/CIFilter.h>
+#include <QuartzCore/CIVector.h>
+
+QT7CIImageVideoBuffer::QT7CIImageVideoBuffer(CIImage *image)
+ : QAbstractVideoBuffer(CoreImageHandle)
+ , m_image(image)
+ , m_buffer(0)
+ , m_mode(NotMapped)
+{
+ [m_image retain];
+}
+
+QT7CIImageVideoBuffer::~QT7CIImageVideoBuffer()
+{
+ [m_image release];
+ [m_buffer release];
+}
+
+QAbstractVideoBuffer::MapMode QT7CIImageVideoBuffer::mapMode() const
+{
+ return m_mode;
+}
+
+uchar *QT7CIImageVideoBuffer::map(QAbstractVideoBuffer::MapMode mode, int *numBytes, int *bytesPerLine)
+{
+ if (mode == NotMapped || m_mode != NotMapped || !m_image)
+ return 0;
+
+ if (!m_buffer) {
+ //swap R and B channels
+ CIFilter *colorSwapFilter = [CIFilter filterWithName: @"CIColorMatrix" keysAndValues:
+ @"inputImage", m_image,
+ @"inputRVector", [CIVector vectorWithX: 0 Y: 0 Z: 1 W: 0],
+ @"inputGVector", [CIVector vectorWithX: 0 Y: 1 Z: 0 W: 0],
+ @"inputBVector", [CIVector vectorWithX: 1 Y: 0 Z: 0 W: 0],
+ @"inputAVector", [CIVector vectorWithX: 0 Y: 0 Z: 0 W: 1],
+ @"inputBiasVector", [CIVector vectorWithX: 0 Y: 0 Z: 0 W: 0],
+ nil];
+ CIImage *img = [colorSwapFilter valueForKey: @"outputImage"];
+
+ m_buffer = [[NSBitmapImageRep alloc] initWithCIImage:img];
+ }
+
+ if (numBytes)
+ *numBytes = [m_buffer bytesPerPlane];
+
+ if (bytesPerLine)
+ *bytesPerLine = [m_buffer bytesPerRow];
+
+ m_mode = mode;
+
+ return [m_buffer bitmapData];
+}
+
+void QT7CIImageVideoBuffer::unmap()
+{
+ m_mode = NotMapped;
+}
+
+QVariant QT7CIImageVideoBuffer::handle() const
+{
+ return QVariant::fromValue<void*>(m_image);
+}
+
diff --git a/src/plugins/qt7/qt7movierenderer.h b/src/plugins/qt7/qt7movierenderer.h
new file mode 100644
index 000000000..42a2732da
--- /dev/null
+++ b/src/plugins/qt7/qt7movierenderer.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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$
+** 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 QT7MOVIERENDERER_H
+#define QT7MOVIERENDERER_H
+
+#include "qt7backend.h"
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmutex.h>
+
+#include <qvideorenderercontrol.h>
+#include <qmediaplayer.h>
+
+#include <QtGui/qmacdefines_mac.h>
+#include "qt7videooutput.h"
+
+#include <QuartzCore/CVOpenGLTexture.h>
+#include <QuickTime/QuickTime.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGLContext;
+
+class QCvDisplayLink;
+class QT7PlayerSession;
+class QT7PlayerService;
+
+class QT7MovieRenderer : public QT7VideoRendererControl
+{
+Q_OBJECT
+public:
+ QT7MovieRenderer(QObject *parent = 0);
+ virtual ~QT7MovieRenderer();
+
+ void setMovie(void *movie);
+ void updateNaturalSize(const QSize &newSize);
+
+ QAbstractVideoSurface *surface() const;
+ void setSurface(QAbstractVideoSurface *surface);
+
+ QSize nativeSize() const;
+
+private slots:
+ void updateVideoFrame(const CVTimeStamp &ts);
+
+private:
+ void setupVideoOutput();
+ bool createPixelBufferVisualContext();
+ bool createGLVisualContext();
+
+ void *m_movie;
+
+ QMutex m_mutex;
+
+ QCvDisplayLink *m_displayLink;
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QTVisualContextRef m_visualContext;
+ bool m_usingGLContext;
+ const QGLContext *m_currentGLContext;
+ QSize m_pixelBufferContextGeometry;
+#endif
+ QAbstractVideoSurface *m_surface;
+ QSize m_nativeSize;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qt7/qt7movierenderer.mm b/src/plugins/qt7/qt7movierenderer.mm
new file mode 100644
index 000000000..6818f02d1
--- /dev/null
+++ b/src/plugins/qt7/qt7movierenderer.mm
@@ -0,0 +1,479 @@
+/****************************************************************************
+**
+** 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$
+** 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$
+**
+****************************************************************************/
+
+#import <QTKit/QTKit.h>
+
+#include "qt7backend.h"
+
+#include "qt7playercontrol.h"
+#include "qt7movierenderer.h"
+#include "qt7playersession.h"
+#include "qt7ciimagevideobuffer.h"
+#include "qcvdisplaylink.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qcoreapplication.h>
+
+#include <QGLWidget>
+
+#include <qabstractvideobuffer.h>
+#include <qabstractvideosurface.h>
+#include <qvideosurfaceformat.h>
+
+QT_USE_NAMESPACE
+
+//#define USE_MAIN_MONITOR_COLOR_SPACE 1
+
+class CVGLTextureVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ CVGLTextureVideoBuffer(CVOpenGLTextureRef buffer)
+ : QAbstractVideoBuffer(GLTextureHandle)
+ , m_buffer(buffer)
+ , m_mode(NotMapped)
+ {
+ CVOpenGLTextureRetain(m_buffer);
+ }
+
+ virtual ~CVGLTextureVideoBuffer()
+ {
+ CVOpenGLTextureRelease(m_buffer);
+ }
+
+ QVariant handle() const
+ {
+ GLuint id = CVOpenGLTextureGetName(m_buffer);
+ return QVariant(int(id));
+ }
+
+ MapMode mapMode() const { return m_mode; }
+
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine)
+ {
+ if (numBytes)
+ *numBytes = 0;
+
+ if (bytesPerLine)
+ *bytesPerLine = 0;
+
+ m_mode = mode;
+ return 0;
+ }
+
+ void unmap() { m_mode = NotMapped; }
+
+private:
+ CVOpenGLTextureRef m_buffer;
+ MapMode m_mode;
+};
+
+
+class CVPixelBufferVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ CVPixelBufferVideoBuffer(CVPixelBufferRef buffer)
+ : QAbstractVideoBuffer(NoHandle)
+ , m_buffer(buffer)
+ , m_mode(NotMapped)
+ {
+ CVPixelBufferRetain(m_buffer);
+ }
+
+ virtual ~CVPixelBufferVideoBuffer()
+ {
+ CVPixelBufferRelease(m_buffer);
+ }
+
+ MapMode mapMode() const { return m_mode; }
+
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine)
+ {
+ if (mode != NotMapped && m_mode == NotMapped) {
+ CVPixelBufferLockBaseAddress(m_buffer, 0);
+
+ if (numBytes)
+ *numBytes = CVPixelBufferGetDataSize(m_buffer);
+
+ if (bytesPerLine)
+ *bytesPerLine = CVPixelBufferGetBytesPerRow(m_buffer);
+
+ m_mode = mode;
+
+ return (uchar*)CVPixelBufferGetBaseAddress(m_buffer);
+ } else {
+ return 0;
+ }
+ }
+
+ void unmap()
+ {
+ if (m_mode != NotMapped) {
+ m_mode = NotMapped;
+ CVPixelBufferUnlockBaseAddress(m_buffer, 0);
+ }
+ }
+
+private:
+ CVPixelBufferRef m_buffer;
+ MapMode m_mode;
+};
+
+
+
+QT7MovieRenderer::QT7MovieRenderer(QObject *parent)
+ :QT7VideoRendererControl(parent),
+ m_movie(0),
+#ifdef QUICKTIME_C_API_AVAILABLE
+ m_visualContext(0),
+ m_usingGLContext(false),
+ m_currentGLContext(0),
+#endif
+ m_surface(0)
+{
+#ifdef QT_DEBUG_QT7
+ qDebug() << "QT7MovieRenderer";
+#endif
+ m_displayLink = new QCvDisplayLink(this);
+ connect(m_displayLink, SIGNAL(tick(CVTimeStamp)), SLOT(updateVideoFrame(CVTimeStamp)));
+}
+
+
+bool QT7MovieRenderer::createGLVisualContext()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+ AutoReleasePool pool;
+ CGLContextObj cglContext = CGLGetCurrentContext();
+ NSOpenGLPixelFormat *nsglPixelFormat = [NSOpenGLView defaultPixelFormat];
+ CGLPixelFormatObj cglPixelFormat = static_cast<CGLPixelFormatObj>([nsglPixelFormat CGLPixelFormatObj]);
+
+ OSStatus err = QTOpenGLTextureContextCreate(kCFAllocatorDefault, cglContext,
+ cglPixelFormat, NULL, &m_visualContext);
+ if (err != noErr)
+ qWarning() << "Could not create visual context (OpenGL)";
+
+ return (err == noErr);
+#endif // QUICKTIME_C_API_AVAILABLE
+
+ return false;
+}
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+static bool DictionarySetValue(CFMutableDictionaryRef dict, CFStringRef key, SInt32 value)
+{
+ CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value);
+
+ if (number) {
+ CFDictionarySetValue( dict, key, number );
+ CFRelease( number );
+ return true;
+ }
+ return false;
+}
+#endif // QUICKTIME_C_API_AVAILABLE
+
+bool QT7MovieRenderer::createPixelBufferVisualContext()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (m_visualContext) {
+ QTVisualContextRelease(m_visualContext);
+ m_visualContext = 0;
+ }
+
+ m_pixelBufferContextGeometry = m_nativeSize;
+
+ CFMutableDictionaryRef pixelBufferOptions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ //DictionarySetValue(pixelBufferOptions, kCVPixelBufferPixelFormatTypeKey, k32ARGBPixelFormat );
+ DictionarySetValue(pixelBufferOptions, kCVPixelBufferPixelFormatTypeKey, k32BGRAPixelFormat );
+ DictionarySetValue(pixelBufferOptions, kCVPixelBufferWidthKey, m_nativeSize.width() );
+ DictionarySetValue(pixelBufferOptions, kCVPixelBufferHeightKey, m_nativeSize.height() );
+ DictionarySetValue(pixelBufferOptions, kCVPixelBufferBytesPerRowAlignmentKey, 16);
+ //CFDictionarySetValue(pixelBufferOptions, kCVPixelBufferOpenGLCompatibilityKey, kCFBooleanTrue);
+
+ CFMutableDictionaryRef visualContextOptions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFDictionarySetValue(visualContextOptions, kQTVisualContextPixelBufferAttributesKey, pixelBufferOptions);
+
+ CGColorSpaceRef colorSpace = NULL;
+
+#if USE_MAIN_MONITOR_COLOR_SPACE
+ CMProfileRef sysprof = NULL;
+
+ // Get the Systems Profile for the main display
+ if (CMGetSystemProfile(&sysprof) == noErr) {
+ // Create a colorspace with the systems profile
+ colorSpace = CGColorSpaceCreateWithPlatformColorSpace(sysprof);
+ CMCloseProfile(sysprof);
+ }
+#endif
+
+ if (!colorSpace)
+ colorSpace = CGColorSpaceCreateDeviceRGB();
+
+ CFDictionarySetValue(visualContextOptions, kQTVisualContextOutputColorSpaceKey, colorSpace);
+
+ OSStatus err = QTPixelBufferContextCreate(kCFAllocatorDefault,
+ visualContextOptions,
+ &m_visualContext);
+ CFRelease(pixelBufferOptions);
+ CFRelease(visualContextOptions);
+
+ if (err != noErr) {
+ qWarning() << "Could not create visual context (PixelBuffer)";
+ return false;
+ }
+
+ return true;
+#endif // QUICKTIME_C_API_AVAILABLE
+
+ return false;
+}
+
+
+QT7MovieRenderer::~QT7MovieRenderer()
+{
+ m_displayLink->stop();
+}
+
+void QT7MovieRenderer::setupVideoOutput()
+{
+ AutoReleasePool pool;
+
+#ifdef QT_DEBUG_QT7
+ qDebug() << "QT7MovieRenderer::setupVideoOutput" << m_movie;
+#endif
+
+ if (m_movie == 0 || m_surface == 0) {
+ m_displayLink->stop();
+ return;
+ }
+
+ NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue];
+ m_nativeSize = QSize(size.width, size.height);
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ bool usedGLContext = m_usingGLContext;
+
+ if (!m_nativeSize.isEmpty()) {
+
+ bool glSupported = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty();
+
+ //Try rendering using opengl textures first:
+ if (glSupported) {
+ QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32, QAbstractVideoBuffer::GLTextureHandle);
+
+ if (m_surface->isActive())
+ m_surface->stop();
+
+ if (!m_surface->start(format)) {
+ qWarning() << "failed to start video surface" << m_surface->error();
+ qWarning() << "Surface format:" << format;
+ glSupported = false;
+ } else {
+ m_usingGLContext = true;
+ }
+
+ }
+
+ if (!glSupported) {
+ m_usingGLContext = false;
+ QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32);
+
+ if (m_surface->isActive() && m_surface->surfaceFormat() != format) {
+#ifdef QT_DEBUG_QT7
+ qDebug() << "Surface format was changed, stop the surface.";
+#endif
+ m_surface->stop();
+ }
+
+ if (!m_surface->isActive()) {
+#ifdef QT_DEBUG_QT7
+ qDebug() << "Starting the surface with format" << format;
+#endif
+ if (!m_surface->start(format)) {
+ qWarning() << "failed to start video surface" << m_surface->error();
+ qWarning() << "Surface format:" << format;
+ }
+ }
+ }
+ }
+
+
+ if (m_visualContext) {
+ //check if the visual context still can be reused
+ if (usedGLContext != m_usingGLContext ||
+ (m_usingGLContext && (m_currentGLContext != QGLContext::currentContext())) ||
+ (!m_usingGLContext && (m_pixelBufferContextGeometry != m_nativeSize))) {
+ QTVisualContextRelease(m_visualContext);
+ m_pixelBufferContextGeometry = QSize();
+ m_visualContext = 0;
+ }
+ }
+
+ if (!m_nativeSize.isEmpty()) {
+ if (!m_visualContext) {
+ if (m_usingGLContext) {
+#ifdef QT_DEBUG_QT7
+ qDebug() << "Building OpenGL visual context" << m_nativeSize;
+#endif
+ m_currentGLContext = QGLContext::currentContext();
+ if (!createGLVisualContext()) {
+ qWarning() << "QT7MovieRenderer: failed to create visual context";
+ return;
+ }
+ } else {
+#ifdef QT_DEBUG_QT7
+ qDebug() << "Building Pixel Buffer visual context" << m_nativeSize;
+#endif
+ if (!createPixelBufferVisualContext()) {
+ qWarning() << "QT7MovieRenderer: failed to create visual context";
+ return;
+ }
+ }
+ }
+
+ // targets a Movie to render into a visual context
+ SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], m_visualContext);
+
+ m_displayLink->start();
+ }
+#endif
+
+}
+
+void QT7MovieRenderer::setMovie(void *movie)
+{
+#ifdef QT_DEBUG_QT7
+ qDebug() << "QT7MovieRenderer::setMovie" << movie;
+#endif
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QMutexLocker locker(&m_mutex);
+
+ if (m_movie != movie) {
+ if (m_movie) {
+ //ensure the old movie doesn't hold the visual context, otherwise it can't be reused
+ SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], nil);
+ [(QTMovie*)m_movie release];
+ }
+
+ m_movie = movie;
+ [(QTMovie*)m_movie retain];
+
+ setupVideoOutput();
+ }
+#endif
+}
+
+void QT7MovieRenderer::updateNaturalSize(const QSize &newSize)
+{
+ if (m_nativeSize != newSize) {
+ m_nativeSize = newSize;
+ setupVideoOutput();
+ }
+}
+
+QAbstractVideoSurface *QT7MovieRenderer::surface() const
+{
+ return m_surface;
+}
+
+void QT7MovieRenderer::setSurface(QAbstractVideoSurface *surface)
+{
+#ifdef QT_DEBUG_QT7
+ qDebug() << "Set video surface" << surface;
+#endif
+
+ if (surface == m_surface)
+ return;
+
+ QMutexLocker locker(&m_mutex);
+
+ if (m_surface && m_surface->isActive())
+ m_surface->stop();
+
+ m_surface = surface;
+ setupVideoOutput();
+}
+
+
+QSize QT7MovieRenderer::nativeSize() const
+{
+ return m_nativeSize;
+}
+
+void QT7MovieRenderer::updateVideoFrame(const CVTimeStamp &ts)
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+
+ QMutexLocker locker(&m_mutex);
+
+ if (m_surface && m_surface->isActive() &&
+ m_visualContext && QTVisualContextIsNewImageAvailable(m_visualContext, &ts)) {
+
+ CVImageBufferRef imageBuffer = NULL;
+
+ OSStatus status = QTVisualContextCopyImageForTime(m_visualContext, NULL, &ts, &imageBuffer);
+
+ if (status == noErr && imageBuffer) {
+ QAbstractVideoBuffer *buffer = 0;
+
+ if (m_usingGLContext) {
+ buffer = new QT7CIImageVideoBuffer([CIImage imageWithCVImageBuffer:imageBuffer]);
+ CVOpenGLTextureRelease((CVOpenGLTextureRef)imageBuffer);
+ } else {
+ buffer = new CVPixelBufferVideoBuffer((CVPixelBufferRef)imageBuffer);
+ //buffer = new QT7CIImageVideoBuffer( [CIImage imageWithCVImageBuffer:imageBuffer] );
+ CVPixelBufferRelease((CVPixelBufferRef)imageBuffer);
+ }
+
+ QVideoFrame frame(buffer, m_nativeSize, QVideoFrame::Format_RGB32);
+ m_surface->present(frame);
+ QTVisualContextTask(m_visualContext);
+ }
+ }
+#else
+ Q_UNUSED(ts);
+#endif
+}
+
+#include "moc_qt7movierenderer.cpp"
diff --git a/src/plugins/qt7/qt7movievideowidget.h b/src/plugins/qt7/qt7movievideowidget.h
new file mode 100644
index 000000000..d69ead655
--- /dev/null
+++ b/src/plugins/qt7/qt7movievideowidget.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QT7MOVIEVIDEOWIDGET_H
+#define QT7MOVIEVIDEOWIDGET_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmutex.h>
+
+#include <qvideowindowcontrol.h>
+#include <qmediaplayer.h>
+
+#include <QtGui/qmacdefines_mac.h>
+#include "qt7videooutput.h"
+
+#include <QuartzCore/CVOpenGLTexture.h>
+#include <QuickTime/QuickTime.h>
+
+class GLVideoWidget;
+
+QT_BEGIN_NAMESPACE
+
+class QCvDisplayLink;
+class QT7PlayerSession;
+class QT7PlayerService;
+
+class QT7MovieVideoWidget : public QT7VideoWidgetControl
+{
+Q_OBJECT
+public:
+ QT7MovieVideoWidget(QObject *parent = 0);
+ virtual ~QT7MovieVideoWidget();
+
+ void setMovie(void *movie);
+ void updateNaturalSize(const QSize &newSize);
+
+ QWidget *videoWidget();
+
+ bool isFullScreen() const;
+ void setFullScreen(bool fullScreen);
+
+ QSize nativeSize() const;
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+private slots:
+ void updateVideoFrame(const CVTimeStamp &ts);
+
+private:
+ void setupVideoOutput();
+ bool createVisualContext();
+
+ void updateColors();
+
+ void *m_movie;
+ GLVideoWidget *m_videoWidget;
+
+ QCvDisplayLink *m_displayLink;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QTVisualContextRef m_visualContext;
+#endif
+
+ bool m_fullscreen;
+ QSize m_nativeSize;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ int m_brightness;
+ int m_contrast;
+ int m_hue;
+ int m_saturation;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qt7/qt7movievideowidget.mm b/src/plugins/qt7/qt7movievideowidget.mm
new file mode 100644
index 000000000..a0858c7fc
--- /dev/null
+++ b/src/plugins/qt7/qt7movievideowidget.mm
@@ -0,0 +1,437 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qt7backend.h"
+
+#import <QTKit/QTDataReference.h>
+#import <QTKit/QTMovie.h>
+#import <QTKit/QTMovieView.h>
+#import <QTKit/QTMovieLayer.h>
+#import <AppKit/NSImage.h>
+#import <OpenGL/glu.h>
+
+
+#include "qt7playercontrol.h"
+#include "qt7movievideowidget.h"
+#include "qt7playersession.h"
+#include "qcvdisplaylink.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qcoreapplication.h>
+
+#include <QGLWidget>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#import <QuartzCore/QuartzCore.h>
+
+#include "math.h"
+
+QT_USE_NAMESPACE
+
+class GLVideoWidget : public QGLWidget
+{
+public:
+
+ GLVideoWidget(QWidget *parent, const QGLFormat &format)
+ : QGLWidget(format, parent),
+ m_texRef(0),
+ m_nativeSize(640,480),
+ m_aspectRatioMode(Qt::KeepAspectRatio)
+ {
+ setAutoFillBackground(false);
+ }
+
+ void initializeGL()
+ {
+ QColor bgColor = palette().color(QPalette::Background);
+ glClearColor(bgColor.redF(), bgColor.greenF(), bgColor.blueF(), bgColor.alphaF());
+ }
+
+ void resizeGL(int w, int h)
+ {
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glViewport(0, 0, GLsizei(w), GLsizei(h));
+ gluOrtho2D(0, GLsizei(w), 0, GLsizei(h));
+ updateGL();
+ }
+
+ void paintGL()
+ {
+ glClear(GL_COLOR_BUFFER_BIT);
+ if (!m_texRef)
+ return;
+
+ glPushMatrix();
+ glDisable(GL_CULL_FACE);
+ GLenum target = CVOpenGLTextureGetTarget(m_texRef);
+ glEnable(target);
+
+ glBindTexture(target, CVOpenGLTextureGetName(m_texRef));
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ GLfloat lowerLeft[2], lowerRight[2], upperRight[2], upperLeft[2];
+ CVOpenGLTextureGetCleanTexCoords(m_texRef, lowerLeft, lowerRight, upperRight, upperLeft);
+
+ glBegin(GL_QUADS);
+ QRect rect = displayRect();
+ glTexCoord2f(lowerLeft[0], lowerLeft[1]);
+ glVertex2i(rect.topLeft().x(), rect.topLeft().y());
+ glTexCoord2f(lowerRight[0], lowerRight[1]);
+ glVertex2i(rect.topRight().x() + 1, rect.topRight().y());
+ glTexCoord2f(upperRight[0], upperRight[1]);
+ glVertex2i(rect.bottomRight().x() + 1, rect.bottomRight().y() + 1);
+ glTexCoord2f(upperLeft[0], upperLeft[1]);
+ glVertex2i(rect.bottomLeft().x(), rect.bottomLeft().y() + 1);
+ glEnd();
+ glPopMatrix();
+ }
+
+ void setCVTexture(CVOpenGLTextureRef texRef)
+ {
+ if (m_texRef)
+ CVOpenGLTextureRelease(m_texRef);
+
+ m_texRef = texRef;
+
+ if (m_texRef)
+ CVOpenGLTextureRetain(m_texRef);
+
+ if (isVisible()) {
+ makeCurrent();
+ paintGL();
+ swapBuffers();
+ }
+ }
+
+ QSize sizeHint() const
+ {
+ return m_nativeSize;
+ }
+
+ void setNativeSize(const QSize &size)
+ {
+ m_nativeSize = size;
+ }
+
+ void setAspectRatioMode(Qt::AspectRatioMode mode)
+ {
+ if (m_aspectRatioMode != mode) {
+ m_aspectRatioMode = mode;
+ update();
+ }
+ }
+
+private:
+ QRect displayRect() const
+ {
+ QRect displayRect = rect();
+
+ if (m_aspectRatioMode == Qt::KeepAspectRatio) {
+ QSize size = m_nativeSize;
+ size.scale(displayRect.size(), Qt::KeepAspectRatio);
+
+ displayRect = QRect(QPoint(0, 0), size);
+ displayRect.moveCenter(rect().center());
+ }
+ return displayRect;
+ }
+
+ CVOpenGLTextureRef m_texRef;
+ QSize m_nativeSize;
+ Qt::AspectRatioMode m_aspectRatioMode;
+};
+
+QT7MovieVideoWidget::QT7MovieVideoWidget(QObject *parent)
+ :QT7VideoWidgetControl(parent),
+ m_movie(0),
+ m_videoWidget(0),
+ m_fullscreen(false),
+ m_aspectRatioMode(Qt::KeepAspectRatio),
+ m_brightness(0),
+ m_contrast(0),
+ m_hue(0),
+ m_saturation(0)
+{
+#ifdef QT_DEBUG_QT7
+ qDebug() << "QT7MovieVideoWidget";
+#endif
+
+ QGLFormat format = QGLFormat::defaultFormat();
+ format.setSwapInterval(1); // Vertical sync (avoid tearing)
+ m_videoWidget = new GLVideoWidget(0, format);
+
+ m_displayLink = new QCvDisplayLink(this);
+
+ connect(m_displayLink, SIGNAL(tick(CVTimeStamp)), SLOT(updateVideoFrame(CVTimeStamp)));
+
+ if (!createVisualContext()) {
+ qWarning() << "QT7MovieVideoWidget: failed to create visual context";
+ }
+}
+
+bool QT7MovieVideoWidget::createVisualContext()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+ m_videoWidget->makeCurrent();
+
+ AutoReleasePool pool;
+ CGLContextObj cglContext = CGLGetCurrentContext();
+ NSOpenGLPixelFormat *nsglPixelFormat = [NSOpenGLView defaultPixelFormat];
+ CGLPixelFormatObj cglPixelFormat = static_cast<CGLPixelFormatObj>([nsglPixelFormat CGLPixelFormatObj]);
+
+ CFTypeRef keys[] = { kQTVisualContextOutputColorSpaceKey };
+ CGColorSpaceRef colorSpace = NULL;
+ CMProfileRef sysprof = NULL;
+
+ // Get the Systems Profile for the main display
+ if (CMGetSystemProfile(&sysprof) == noErr) {
+ // Create a colorspace with the systems profile
+ colorSpace = CGColorSpaceCreateWithPlatformColorSpace(sysprof);
+ CMCloseProfile(sysprof);
+ }
+
+ if (!colorSpace)
+ colorSpace = CGColorSpaceCreateDeviceRGB();
+
+ CFDictionaryRef textureContextAttributes = CFDictionaryCreate(kCFAllocatorDefault,
+ (const void **)keys,
+ (const void **)&colorSpace, 1,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ OSStatus err = QTOpenGLTextureContextCreate(kCFAllocatorDefault,
+ cglContext,
+ cglPixelFormat,
+ textureContextAttributes,
+ &m_visualContext);
+ if (err != noErr)
+ qWarning() << "Could not create visual context (OpenGL)";
+
+
+ return (err == noErr);
+#endif // QUICKTIME_C_API_AVAILABLE
+
+ return false;
+}
+
+QT7MovieVideoWidget::~QT7MovieVideoWidget()
+{
+ m_displayLink->stop();
+ [(QTMovie*)m_movie release];
+ delete m_videoWidget;
+}
+
+QWidget *QT7MovieVideoWidget::videoWidget()
+{
+ return m_videoWidget;
+}
+
+void QT7MovieVideoWidget::setupVideoOutput()
+{
+ AutoReleasePool pool;
+
+#ifdef QT_DEBUG_QT7
+ qDebug() << "QT7MovieVideoWidget::setupVideoOutput" << m_movie;
+#endif
+
+ if (m_movie == 0) {
+ m_displayLink->stop();
+ return;
+ }
+
+ NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue];
+ m_nativeSize = QSize(size.width, size.height);
+ m_videoWidget->setNativeSize(m_nativeSize);
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ // targets a Movie to render into a visual context
+ SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], m_visualContext);
+#endif
+
+ m_displayLink->start();
+}
+
+void QT7MovieVideoWidget::setMovie(void *movie)
+{
+ if (m_movie == movie)
+ return;
+
+ if (m_movie) {
+#ifdef QUICKTIME_C_API_AVAILABLE
+ SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], nil);
+#endif
+ [(QTMovie*)m_movie release];
+ }
+
+ m_movie = movie;
+ [(QTMovie*)m_movie retain];
+
+ setupVideoOutput();
+}
+
+void QT7MovieVideoWidget::updateNaturalSize(const QSize &newSize)
+{
+ if (m_nativeSize != newSize) {
+ m_nativeSize = newSize;
+ setupVideoOutput();
+ }
+}
+
+bool QT7MovieVideoWidget::isFullScreen() const
+{
+ return m_fullscreen;
+}
+
+void QT7MovieVideoWidget::setFullScreen(bool fullScreen)
+{
+ m_fullscreen = fullScreen;
+}
+
+QSize QT7MovieVideoWidget::nativeSize() const
+{
+ return m_nativeSize;
+}
+
+Qt::AspectRatioMode QT7MovieVideoWidget::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void QT7MovieVideoWidget::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_aspectRatioMode = mode;
+ m_videoWidget->setAspectRatioMode(mode);
+}
+
+int QT7MovieVideoWidget::brightness() const
+{
+ return m_brightness;
+}
+
+void QT7MovieVideoWidget::setBrightness(int brightness)
+{
+ m_brightness = brightness;
+ updateColors();
+}
+
+int QT7MovieVideoWidget::contrast() const
+{
+ return m_contrast;
+}
+
+void QT7MovieVideoWidget::setContrast(int contrast)
+{
+ m_contrast = contrast;
+ updateColors();
+}
+
+int QT7MovieVideoWidget::hue() const
+{
+ return m_hue;
+}
+
+void QT7MovieVideoWidget::setHue(int hue)
+{
+ m_hue = hue;
+ updateColors();
+}
+
+int QT7MovieVideoWidget::saturation() const
+{
+ return m_saturation;
+}
+
+void QT7MovieVideoWidget::setSaturation(int saturation)
+{
+ m_saturation = saturation;
+ updateColors();
+}
+
+void QT7MovieVideoWidget::updateColors()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (m_movie) {
+ QTMovie *movie = (QTMovie*)m_movie;
+
+ Float32 value;
+ value = m_brightness/100.0;
+ SetMovieVisualBrightness([movie quickTimeMovie], value, 0);
+ value = pow(2, m_contrast/50.0);
+ SetMovieVisualContrast([movie quickTimeMovie], value, 0);
+ value = m_hue/100.0;
+ SetMovieVisualHue([movie quickTimeMovie], value, 0);
+ value = 1.0+m_saturation/100.0;
+ SetMovieVisualSaturation([movie quickTimeMovie], value, 0);
+ }
+#endif
+}
+
+void QT7MovieVideoWidget::updateVideoFrame(const CVTimeStamp &ts)
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+ AutoReleasePool pool;
+ // check for new frame
+ if (m_visualContext && QTVisualContextIsNewImageAvailable(m_visualContext, &ts)) {
+ CVOpenGLTextureRef currentFrame = NULL;
+
+ // get a "frame" (image buffer) from the Visual Context, indexed by the provided time
+ OSStatus status = QTVisualContextCopyImageForTime(m_visualContext, NULL, &ts, &currentFrame);
+
+ // the above call may produce a null frame so check for this first
+ // if we have a frame, then draw it
+ if (status == noErr && currentFrame) {
+#ifdef QT_DEBUG_QT7
+ qDebug() << "render video frame";
+#endif
+ m_videoWidget->setCVTexture(currentFrame);
+ CVOpenGLTextureRelease(currentFrame);
+ }
+ QTVisualContextTask(m_visualContext);
+ }
+#else
+ Q_UNUSED(ts);
+#endif
+}
+
+#include "moc_qt7movievideowidget.cpp"
diff --git a/src/plugins/qt7/qt7movieviewoutput.h b/src/plugins/qt7/qt7movieviewoutput.h
new file mode 100644
index 000000000..4b9cff3ea
--- /dev/null
+++ b/src/plugins/qt7/qt7movieviewoutput.h
@@ -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$
+** 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 QT7MOVIEVIEWOUTPUT_H
+#define QT7MOVIEVIEWOUTPUT_H
+
+#include <QtCore/qobject.h>
+
+#include <qvideowindowcontrol.h>
+#include <qmediaplayer.h>
+
+#include <QtGui/qmacdefines_mac.h>
+#include "qt7videooutput.h"
+
+
+QT_BEGIN_NAMESPACE
+
+class QT7PlayerSession;
+class QT7PlayerService;
+
+class QT7MovieViewOutput : public QT7VideoWindowControl
+{
+public:
+ QT7MovieViewOutput(QObject *parent = 0);
+ ~QT7MovieViewOutput();
+
+ void setMovie(void *movie);
+ void updateNaturalSize(const QSize &newSize);
+
+ WId winId() const;
+ void setWinId(WId id);
+
+ QRect displayRect() const;
+ void setDisplayRect(const QRect &rect);
+
+ bool isFullScreen() const;
+ void setFullScreen(bool fullScreen);
+
+ void repaint();
+
+ QSize nativeSize() const;
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+private:
+ void setupVideoOutput();
+
+ void *m_movie;
+ void *m_movieView;
+ bool m_layouted;
+
+ WId m_winId;
+ QRect m_displayRect;
+ bool m_fullscreen;
+ QSize m_nativeSize;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ int m_brightness;
+ int m_contrast;
+ int m_hue;
+ int m_saturation;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qt7/qt7movieviewoutput.mm b/src/plugins/qt7/qt7movieviewoutput.mm
new file mode 100644
index 000000000..6d38d6148
--- /dev/null
+++ b/src/plugins/qt7/qt7movieviewoutput.mm
@@ -0,0 +1,339 @@
+/****************************************************************************
+**
+** 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$
+** 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$
+**
+****************************************************************************/
+
+#import <QTKit/QTkit.h>
+
+#include "qt7backend.h"
+
+#include "qt7playercontrol.h"
+#include "qt7movieviewoutput.h"
+#include "qt7playersession.h"
+#include <QtCore/qdebug.h>
+
+#include <QuartzCore/CIFilter.h>
+#include <QuartzCore/CIVector.h>
+
+QT_USE_NAMESPACE
+
+#define VIDEO_TRANSPARENT(m) -(void)m:(NSEvent *)e{[[self superview] m:e];}
+
+@interface TransparentQTMovieView : QTMovieView
+{
+@private
+ QRect *m_drawRect;
+ qreal m_brightness, m_contrast, m_saturation, m_hue;
+}
+
+- (TransparentQTMovieView *) init;
+- (void) setDrawRect:(QRect &)rect;
+- (CIImage *) view:(QTMovieView *)view willDisplayImage:(CIImage *)img;
+- (void) setContrast:(qreal) contrast;
+@end
+
+@implementation TransparentQTMovieView
+
+- (TransparentQTMovieView *) init
+{
+ self = [super initWithFrame:NSZeroRect];
+ if (self) {
+ [self setControllerVisible:NO];
+ [self setContrast:1.0];
+ [self setDelegate:self];
+ }
+ return self;
+}
+
+- (void) dealloc
+{
+ [super dealloc];
+}
+
+- (void) setContrast:(qreal) contrast
+{
+ m_hue = 0.0;
+ m_brightness = 0.0;
+ m_contrast = contrast;
+ m_saturation = 1.0;
+}
+
+
+- (void) setDrawRect:(QRect &)rect
+{
+ *m_drawRect = rect;
+
+ NSRect nsrect;
+ nsrect.origin.x = m_drawRect->x();
+ nsrect.origin.y = m_drawRect->y();
+ nsrect.size.width = m_drawRect->width();
+ nsrect.size.height = m_drawRect->height();
+ [self setFrame:nsrect];
+}
+
+- (CIImage *) view:(QTMovieView *)view willDisplayImage:(CIImage *)img
+{
+ // This method is called from QTMovieView just
+ // before the image will be drawn.
+ Q_UNUSED(view);
+
+ if ( !qFuzzyCompare(m_brightness, 0.0) ||
+ !qFuzzyCompare(m_contrast, 1.0) ||
+ !qFuzzyCompare(m_saturation, 1.0)){
+ CIFilter *colorFilter = [CIFilter filterWithName:@"CIColorControls"];
+ [colorFilter setValue:[NSNumber numberWithFloat:m_brightness] forKey:@"inputBrightness"];
+ [colorFilter setValue:[NSNumber numberWithFloat:(m_contrast < 1) ? m_contrast : 1 + ((m_contrast-1)*3)] forKey:@"inputContrast"];
+ [colorFilter setValue:[NSNumber numberWithFloat:m_saturation] forKey:@"inputSaturation"];
+ [colorFilter setValue:img forKey:@"inputImage"];
+ img = [colorFilter valueForKey:@"outputImage"];
+ }
+
+ /*if (m_hue){
+ CIFilter *colorFilter = [CIFilter filterWithName:@"CIHueAdjust"];
+ [colorFilter setValue:[NSNumber numberWithFloat:(m_hue * 3.14)] forKey:@"inputAngle"];
+ [colorFilter setValue:img forKey:@"inputImage"];
+ img = [colorFilter valueForKey:@"outputImage"];
+ }*/
+
+ return img;
+}
+
+
+VIDEO_TRANSPARENT(mouseDown);
+VIDEO_TRANSPARENT(mouseDragged);
+VIDEO_TRANSPARENT(mouseUp);
+VIDEO_TRANSPARENT(mouseMoved);
+VIDEO_TRANSPARENT(mouseEntered);
+VIDEO_TRANSPARENT(mouseExited);
+VIDEO_TRANSPARENT(rightMouseDown);
+VIDEO_TRANSPARENT(rightMouseDragged);
+VIDEO_TRANSPARENT(rightMouseUp);
+VIDEO_TRANSPARENT(otherMouseDown);
+VIDEO_TRANSPARENT(otherMouseDragged);
+VIDEO_TRANSPARENT(otherMouseUp);
+VIDEO_TRANSPARENT(keyDown);
+VIDEO_TRANSPARENT(keyUp);
+VIDEO_TRANSPARENT(scrollWheel)
+
+@end
+
+
+QT7MovieViewOutput::QT7MovieViewOutput(QObject *parent)
+ :QT7VideoWindowControl(parent),
+ m_movie(0),
+ m_movieView(0),
+ m_layouted(false),
+ m_winId(0),
+ m_fullscreen(false),
+ m_aspectRatioMode(Qt::KeepAspectRatio),
+ m_brightness(0),
+ m_contrast(0),
+ m_hue(0),
+ m_saturation(0)
+{
+}
+
+QT7MovieViewOutput::~QT7MovieViewOutput()
+{
+ [(QTMovieView*)m_movieView release];
+ [(QTMovie*)m_movie release];
+}
+
+void QT7MovieViewOutput::setupVideoOutput()
+{
+ AutoReleasePool pool;
+
+#ifdef QT_DEBUG_QT7
+ qDebug() << "QT7MovieViewOutput::setupVideoOutput" << m_movie << m_winId;
+#endif
+ if (m_movie == 0 || m_winId <= 0)
+ return;
+
+ NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue];
+ m_nativeSize = QSize(size.width, size.height);
+
+ if (!m_movieView)
+ m_movieView = [[TransparentQTMovieView alloc] init];
+
+ [(QTMovieView*)m_movieView setControllerVisible:NO];
+ [(QTMovieView*)m_movieView setMovie:(QTMovie*)m_movie];
+
+ [(NSView *)m_winId addSubview:(QTMovieView*)m_movieView];
+ m_layouted = true;
+
+ setDisplayRect(m_displayRect);
+}
+
+void QT7MovieViewOutput::setMovie(void *movie)
+{
+ if (m_movie != movie) {
+ if (m_movie) {
+ if (m_movieView)
+ [(QTMovieView*)m_movieView setMovie:nil];
+
+ [(QTMovie*)m_movie release];
+ }
+
+ m_movie = movie;
+
+ if (m_movie)
+ [(QTMovie*)m_movie retain];
+
+ setupVideoOutput();
+ }
+}
+
+void QT7MovieViewOutput::updateNaturalSize(const QSize &newSize)
+{
+ if (m_nativeSize != newSize) {
+ m_nativeSize = newSize;
+ emit nativeSizeChanged();
+ }
+}
+
+WId QT7MovieViewOutput::winId() const
+{
+ return m_winId;
+}
+
+void QT7MovieViewOutput::setWinId(WId id)
+{
+ if (m_winId != id) {
+ if (m_movieView && m_layouted) {
+ [(QTMovieView*)m_movieView removeFromSuperview];
+ m_layouted = false;
+ }
+
+ m_winId = id;
+ setupVideoOutput();
+ }
+}
+
+QRect QT7MovieViewOutput::displayRect() const
+{
+ return m_displayRect;
+}
+
+void QT7MovieViewOutput::setDisplayRect(const QRect &rect)
+{
+ m_displayRect = rect;
+
+ if (m_movieView) {
+ AutoReleasePool pool;
+ [(QTMovieView*)m_movieView setPreservesAspectRatio:(m_aspectRatioMode == Qt::KeepAspectRatio ? YES : NO)];
+ [(QTMovieView*)m_movieView setFrame:NSMakeRect(m_displayRect.x(),
+ m_displayRect.y(),
+ m_displayRect.width(),
+ m_displayRect.height())];
+ }
+
+}
+
+bool QT7MovieViewOutput::isFullScreen() const
+{
+ return m_fullscreen;
+}
+
+void QT7MovieViewOutput::setFullScreen(bool fullScreen)
+{
+ m_fullscreen = fullScreen;
+ setDisplayRect(m_displayRect);
+}
+
+void QT7MovieViewOutput::repaint()
+{
+}
+
+QSize QT7MovieViewOutput::nativeSize() const
+{
+ return m_nativeSize;
+}
+
+Qt::AspectRatioMode QT7MovieViewOutput::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void QT7MovieViewOutput::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_aspectRatioMode = mode;
+ setDisplayRect(m_displayRect);
+}
+
+int QT7MovieViewOutput::brightness() const
+{
+ return m_brightness;
+}
+
+void QT7MovieViewOutput::setBrightness(int brightness)
+{
+ m_brightness = brightness;
+}
+
+int QT7MovieViewOutput::contrast() const
+{
+ return m_contrast;
+}
+
+void QT7MovieViewOutput::setContrast(int contrast)
+{
+ m_contrast = contrast;
+ [(TransparentQTMovieView*)m_movieView setContrast:(contrast/100.0+1.0)];
+}
+
+int QT7MovieViewOutput::hue() const
+{
+ return m_hue;
+}
+
+void QT7MovieViewOutput::setHue(int hue)
+{
+ m_hue = hue;
+}
+
+int QT7MovieViewOutput::saturation() const
+{
+ return m_saturation;
+}
+
+void QT7MovieViewOutput::setSaturation(int saturation)
+{
+ m_saturation = saturation;
+}
+
diff --git a/src/plugins/qt7/qt7movieviewrenderer.h b/src/plugins/qt7/qt7movieviewrenderer.h
new file mode 100644
index 000000000..f95f6097d
--- /dev/null
+++ b/src/plugins/qt7/qt7movieviewrenderer.h
@@ -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$
+** 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 QT7MOVIEVIEWRENDERER_H
+#define QT7MOVIEVIEWRENDERER_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmutex.h>
+
+#include <qvideowindowcontrol.h>
+#include <qmediaplayer.h>
+
+#include <QtGui/qmacdefines_mac.h>
+#include "qt7videooutput.h"
+#include <qvideoframe.h>
+
+QT_BEGIN_NAMESPACE
+
+class QVideoFrame;
+
+class QT7PlayerSession;
+class QT7PlayerService;
+
+class QT7MovieViewRenderer : public QT7VideoRendererControl
+{
+public:
+ QT7MovieViewRenderer(QObject *parent = 0);
+ ~QT7MovieViewRenderer();
+
+ void setMovie(void *movie);
+ void updateNaturalSize(const QSize &newSize);
+
+ QAbstractVideoSurface *surface() const;
+ void setSurface(QAbstractVideoSurface *surface);
+
+ void renderFrame(const QVideoFrame &);
+
+protected:
+ bool event(QEvent *event);
+
+private:
+ void setupVideoOutput();
+
+ void *m_movie;
+ void *m_movieView;
+ QSize m_nativeSize;
+ QAbstractVideoSurface *m_surface;
+ QVideoFrame m_currentFrame;
+ bool m_pendingRenderEvent;
+ QMutex m_mutex;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qt7/qt7movieviewrenderer.mm b/src/plugins/qt7/qt7movieviewrenderer.mm
new file mode 100644
index 000000000..b9d4f64b9
--- /dev/null
+++ b/src/plugins/qt7/qt7movieviewrenderer.mm
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** 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$
+** 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$
+**
+****************************************************************************/
+
+#import <QTKit/QTKit.h>
+
+#include "qt7backend.h"
+
+#include "qt7playercontrol.h"
+#include "qt7movieviewrenderer.h"
+#include "qt7playersession.h"
+#include "qt7ciimagevideobuffer.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qcoreapplication.h>
+
+#include <QtCore/qreadwritelock.h>
+
+#include <qabstractvideobuffer.h>
+#include <qabstractvideosurface.h>
+#include <qvideosurfaceformat.h>
+
+#include <QuartzCore/CIFilter.h>
+#include <QuartzCore/CIVector.h>
+
+QT_USE_NAMESPACE
+
+class NSBitmapVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ NSBitmapVideoBuffer(NSBitmapImageRep *buffer)
+ : QAbstractVideoBuffer(NoHandle)
+ , m_buffer(buffer)
+ , m_mode(NotMapped)
+ {
+ [m_buffer retain];
+ }
+
+ virtual ~NSBitmapVideoBuffer()
+ {
+ [m_buffer release];
+ }
+
+ MapMode mapMode() const { return m_mode; }
+
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine)
+ {
+ if (mode != NotMapped && m_mode == NotMapped) {
+ if (numBytes)
+ *numBytes = [m_buffer bytesPerPlane];
+
+ if (bytesPerLine)
+ *bytesPerLine = [m_buffer bytesPerRow];
+
+ m_mode = mode;
+
+ return [m_buffer bitmapData];
+ } else {
+ return 0;
+ }
+ }
+
+ void unmap() { m_mode = NotMapped; }
+
+private:
+ NSBitmapImageRep *m_buffer;
+ MapMode m_mode;
+};
+
+
+#define VIDEO_TRANSPARENT(m) -(void)m:(NSEvent *)e{[[self superview] m:e];}
+
+@interface HiddenQTMovieView : QTMovieView
+{
+@private
+ QWidget *m_window;
+ QT7MovieViewRenderer *m_renderer;
+ QReadWriteLock m_rendererLock;
+}
+
+- (HiddenQTMovieView *) initWithRenderer:(QT7MovieViewRenderer *)renderer;
+- (void) setRenderer:(QT7MovieViewRenderer *)renderer;
+- (void) setDrawRect:(const QRect &)rect;
+- (CIImage *) view:(QTMovieView *)view willDisplayImage:(CIImage *)img;
+@end
+
+@implementation HiddenQTMovieView
+
+- (HiddenQTMovieView *) initWithRenderer:(QT7MovieViewRenderer *)renderer
+{
+ self = [super initWithFrame:NSZeroRect];
+ if (self) {
+ [self setControllerVisible:NO];
+ [self setDelegate:self];
+
+ QWriteLocker lock(&self->m_rendererLock);
+ self->m_renderer = renderer;
+
+ self->m_window = new QWidget;
+ self->m_window->setWindowOpacity(0.0);
+ self->m_window->show();
+ self->m_window->hide();
+
+ [(NSView *)(self->m_window->winId()) addSubview:self];
+ [self setDrawRect:QRect(0,0,1,1)];
+ }
+ return self;
+}
+
+- (void) dealloc
+{
+ [super dealloc];
+}
+
+- (void) setRenderer:(QT7MovieViewRenderer *)renderer
+{
+ QWriteLocker lock(&m_rendererLock);
+ m_renderer = renderer;
+}
+
+- (void) setDrawRect:(const QRect &)rect
+{
+ NSRect nsrect;
+ nsrect.origin.x = rect.x();
+ nsrect.origin.y = rect.y();
+ nsrect.size.width = rect.width();
+ nsrect.size.height = rect.height();
+ [self setFrame:nsrect];
+}
+
+- (CIImage *) view:(QTMovieView *)view willDisplayImage:(CIImage *)img
+{
+ // This method is called from QTMovieView just
+ // before the image will be drawn.
+ Q_UNUSED(view);
+ QReadLocker lock(&m_rendererLock);
+
+ if (m_renderer) {
+ CGRect bounds = [img extent];
+ int w = bounds.size.width;
+ int h = bounds.size.height;
+
+ QVideoFrame frame;
+
+ QAbstractVideoSurface *surface = m_renderer->surface();
+ if (!surface || !surface->isActive())
+ return img;
+
+ if (surface->surfaceFormat().handleType() == QAbstractVideoBuffer::CoreImageHandle) {
+ //surface supports rendering of opengl based CIImage
+ frame = QVideoFrame(new QT7CIImageVideoBuffer(img), QSize(w,h), QVideoFrame::Format_RGB32 );
+ } else {
+ //Swap R and B colors
+ CIFilter *colorSwapFilter = [CIFilter filterWithName: @"CIColorMatrix" keysAndValues:
+ @"inputImage", img,
+ @"inputRVector", [CIVector vectorWithX: 0 Y: 0 Z: 1 W: 0],
+ @"inputGVector", [CIVector vectorWithX: 0 Y: 1 Z: 0 W: 0],
+ @"inputBVector", [CIVector vectorWithX: 1 Y: 0 Z: 0 W: 0],
+ @"inputAVector", [CIVector vectorWithX: 0 Y: 0 Z: 0 W: 1],
+ @"inputBiasVector", [CIVector vectorWithX: 0 Y: 0 Z: 0 W: 0],
+ nil];
+ CIImage *img = [colorSwapFilter valueForKey: @"outputImage"];
+ NSBitmapImageRep *bitmap =[[NSBitmapImageRep alloc] initWithCIImage:img];
+ //requesting the bitmap data is slow,
+ //but it's better to do it here to avoid blocking the main thread for a long.
+ [bitmap bitmapData];
+ frame = QVideoFrame(new NSBitmapVideoBuffer(bitmap), QSize(w,h), QVideoFrame::Format_RGB32 );
+ [bitmap release];
+ }
+
+ m_renderer->renderFrame(frame);
+ }
+
+ return img;
+}
+
+// Override this method so that the movie doesn't stop if
+// the window becomes invisible
+- (void)viewWillMoveToWindow:(NSWindow *)newWindow
+{
+ Q_UNUSED(newWindow);
+}
+
+
+VIDEO_TRANSPARENT(mouseDown);
+VIDEO_TRANSPARENT(mouseDragged);
+VIDEO_TRANSPARENT(mouseUp);
+VIDEO_TRANSPARENT(mouseMoved);
+VIDEO_TRANSPARENT(mouseEntered);
+VIDEO_TRANSPARENT(mouseExited);
+VIDEO_TRANSPARENT(rightMouseDown);
+VIDEO_TRANSPARENT(rightMouseDragged);
+VIDEO_TRANSPARENT(rightMouseUp);
+VIDEO_TRANSPARENT(otherMouseDown);
+VIDEO_TRANSPARENT(otherMouseDragged);
+VIDEO_TRANSPARENT(otherMouseUp);
+VIDEO_TRANSPARENT(keyDown);
+VIDEO_TRANSPARENT(keyUp);
+VIDEO_TRANSPARENT(scrollWheel)
+
+@end
+
+
+QT7MovieViewRenderer::QT7MovieViewRenderer(QObject *parent)
+ :QT7VideoRendererControl(parent),
+ m_movie(0),
+ m_movieView(0),
+ m_surface(0),
+ m_pendingRenderEvent(false)
+{
+}
+
+QT7MovieViewRenderer::~QT7MovieViewRenderer()
+{
+ [(HiddenQTMovieView*)m_movieView setRenderer:0];
+
+ QMutexLocker locker(&m_mutex);
+ m_currentFrame = QVideoFrame();
+ [(HiddenQTMovieView*)m_movieView release];
+}
+
+void QT7MovieViewRenderer::setupVideoOutput()
+{
+ AutoReleasePool pool;
+
+#ifdef QT_DEBUG_QT7
+ qDebug() << "QT7MovieViewRenderer::setupVideoOutput" << m_movie << m_surface;
+#endif
+
+ HiddenQTMovieView *movieView = (HiddenQTMovieView*)m_movieView;
+
+ if (movieView && !m_movie) {
+ [movieView setMovie:nil];
+ }
+
+ if (m_movie) {
+ NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue];
+
+ m_nativeSize = QSize(size.width, size.height);
+
+ if (!movieView) {
+ movieView = [[HiddenQTMovieView alloc] initWithRenderer:this];
+ m_movieView = movieView;
+ [movieView setControllerVisible:NO];
+ }
+
+ [movieView setMovie:(QTMovie*)m_movie];
+ [movieView setDrawRect:QRect(QPoint(0,0), m_nativeSize)];
+ }
+
+ if (m_surface && !m_nativeSize.isEmpty()) {
+ bool coreImageFrameSupported = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::CoreImageHandle).isEmpty() &&
+ !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty();
+
+ QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32,
+ coreImageFrameSupported ? QAbstractVideoBuffer::CoreImageHandle : QAbstractVideoBuffer::NoHandle);
+
+ if (m_surface->isActive() && m_surface->surfaceFormat() != format) {
+#ifdef QT_DEBUG_QT7
+ qDebug() << "Surface format was changed, stop the surface.";
+#endif
+ m_surface->stop();
+ }
+
+ if (!m_surface->isActive()) {
+#ifdef QT_DEBUG_QT7
+ qDebug() << "Starting the surface with format" << format;
+#endif
+ if (!m_surface->start(format))
+ qWarning() << "failed to start video surface" << m_surface->error();
+ }
+ }
+}
+
+void QT7MovieViewRenderer::setMovie(void *movie)
+{
+ if (movie == m_movie)
+ return;
+
+ QMutexLocker locker(&m_mutex);
+ m_movie = movie;
+ setupVideoOutput();
+}
+
+void QT7MovieViewRenderer::updateNaturalSize(const QSize &newSize)
+{
+ if (m_nativeSize != newSize) {
+ m_nativeSize = newSize;
+ setupVideoOutput();
+ }
+}
+
+QAbstractVideoSurface *QT7MovieViewRenderer::surface() const
+{
+ return m_surface;
+}
+
+void QT7MovieViewRenderer::setSurface(QAbstractVideoSurface *surface)
+{
+ if (surface == m_surface)
+ return;
+
+ QMutexLocker locker(&m_mutex);
+
+ if (m_surface && m_surface->isActive())
+ m_surface->stop();
+
+ m_surface = surface;
+ setupVideoOutput();
+}
+
+void QT7MovieViewRenderer::renderFrame(const QVideoFrame &frame)
+{
+
+ QMutexLocker locker(&m_mutex);
+ m_currentFrame = frame;
+
+ if (!m_pendingRenderEvent)
+ qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority);
+
+ m_pendingRenderEvent = true;
+}
+
+bool QT7MovieViewRenderer::event(QEvent *event)
+{
+ if (event->type() == QEvent::User) {
+ QMutexLocker locker(&m_mutex);
+ m_pendingRenderEvent = false;
+ if (m_surface->isActive())
+ m_surface->present(m_currentFrame);
+ }
+
+ return QT7VideoRendererControl::event(event);
+}
diff --git a/src/plugins/qt7/qt7serviceplugin.h b/src/plugins/qt7/qt7serviceplugin.h
new file mode 100644
index 000000000..fb0a546b3
--- /dev/null
+++ b/src/plugins/qt7/qt7serviceplugin.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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$
+** 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 QT7SERVICEPLUGIN_H
+#define QT7SERVICEPLUGIN_H
+
+#include <qmediaserviceproviderplugin.h>
+
+QT_BEGIN_NAMESPACE
+
+class QT7ServicePlugin
+ : public QMediaServiceProviderPlugin
+ , public QMediaServiceSupportedFormatsInterface
+ , public QMediaServiceFeaturesInterface
+{
+ Q_INTERFACES(QMediaServiceFeaturesInterface)
+public:
+ QT7ServicePlugin();
+
+ QStringList keys() const;
+ QMediaService* create(QString const& key);
+ void release(QMediaService *service);
+
+ QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const;
+ QtMultimediaKit::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const;
+ QStringList supportedMimeTypes() const;
+
+private:
+ void buildSupportedTypes();
+
+ QStringList m_supportedMimeTypes;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGSTREAMERSERVICEPLUGIN_H
diff --git a/src/plugins/qt7/qt7serviceplugin.mm b/src/plugins/qt7/qt7serviceplugin.mm
new file mode 100644
index 000000000..a692e190f
--- /dev/null
+++ b/src/plugins/qt7/qt7serviceplugin.mm
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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$
+**
+****************************************************************************/
+
+#import <Foundation/Foundation.h>
+#import <QTKit/QTKit.h>
+
+#include <QtCore/qstring.h>
+#include <QtCore/qdebug.h>
+
+#include "qt7backend.h"
+#include "qt7serviceplugin.h"
+#include "qt7playerservice.h"
+
+#include <qmediaserviceprovider.h>
+
+QT_BEGIN_NAMESPACE
+
+
+QT7ServicePlugin::QT7ServicePlugin()
+{
+ buildSupportedTypes();
+}
+
+QStringList QT7ServicePlugin::keys() const
+{
+ return QStringList()
+#ifdef QMEDIA_QT7_PLAYER
+ << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)
+#endif
+ ;
+}
+
+QMediaService* QT7ServicePlugin::create(QString const& key)
+{
+#ifdef QT_DEBUG_QT7
+ qDebug() << "QT7ServicePlugin::create" << key;
+#endif
+#ifdef QMEDIA_QT7_PLAYER
+ if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER))
+ return new QT7PlayerService;
+#endif
+ qWarning() << "unsupported key:" << key;
+
+ return 0;
+}
+
+void QT7ServicePlugin::release(QMediaService *service)
+{
+ delete service;
+}
+
+QMediaServiceProviderHint::Features QT7ServicePlugin::supportedFeatures(
+ const QByteArray &service) const
+{
+ if (service == Q_MEDIASERVICE_MEDIAPLAYER)
+ return QMediaServiceProviderHint::VideoSurface;
+ else
+ return QMediaServiceProviderHint::Features();
+}
+
+QtMultimediaKit::SupportEstimate QT7ServicePlugin::hasSupport(const QString &mimeType, const QStringList& codecs) const
+{
+ Q_UNUSED(codecs);
+
+ if (m_supportedMimeTypes.contains(mimeType))
+ return QtMultimediaKit::ProbablySupported;
+
+ return QtMultimediaKit::MaybeSupported;
+}
+
+QStringList QT7ServicePlugin::supportedMimeTypes() const
+{
+ return m_supportedMimeTypes;
+}
+
+void QT7ServicePlugin::buildSupportedTypes()
+{
+ AutoReleasePool pool;
+ NSArray *utis = [QTMovie movieTypesWithOptions:QTIncludeCommonTypes];
+ for (NSString *uti in utis) {
+ NSString* mimeType = (NSString*)UTTypeCopyPreferredTagWithClass((CFStringRef)uti, kUTTagClassMIMEType);
+ if (mimeType != 0) {
+ m_supportedMimeTypes.append(QString::fromUtf8([mimeType UTF8String]));
+ [mimeType release];
+ }
+ }
+}
+
+Q_EXPORT_PLUGIN2(qtmedia_qt7engine, QT7ServicePlugin);
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qt7/qt7videooutput.h b/src/plugins/qt7/qt7videooutput.h
new file mode 100644
index 000000000..060f7b910
--- /dev/null
+++ b/src/plugins/qt7/qt7videooutput.h
@@ -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$
+** 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 QT7VIDEOOUTPUTCONTROL_H
+#define QT7VIDEOOUTPUTCONTROL_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qsize.h>
+
+#include <qvideowindowcontrol.h>
+#include <qvideowidgetcontrol.h>
+#include <qvideorenderercontrol.h>
+#include <qmediaplayer.h>
+
+#include <QtGui/qmacdefines_mac.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QMediaPlaylist;
+class QMediaPlaylistNavigator;
+class QT7PlayerSession;
+class QT7PlayerService;
+
+
+class QT7VideoOutput {
+public:
+ virtual ~QT7VideoOutput() {}
+ virtual void setMovie(void *movie) = 0;
+ virtual void updateNaturalSize(const QSize &newSize) = 0;
+};
+
+#define QT7VideoOutput_iid \
+ "com.nokia.Qt.QT7VideoOutput/1.0"
+Q_DECLARE_INTERFACE(QT7VideoOutput, QT7VideoOutput_iid)
+
+class QT7VideoWindowControl : public QVideoWindowControl, public QT7VideoOutput
+{
+Q_OBJECT
+Q_INTERFACES(QT7VideoOutput)
+public:
+ virtual ~QT7VideoWindowControl() {}
+
+protected:
+ QT7VideoWindowControl(QObject *parent)
+ :QVideoWindowControl(parent)
+ {}
+};
+
+class QT7VideoRendererControl : public QVideoRendererControl, public QT7VideoOutput
+{
+Q_OBJECT
+Q_INTERFACES(QT7VideoOutput)
+public:
+ virtual ~QT7VideoRendererControl() {}
+
+protected:
+ QT7VideoRendererControl(QObject *parent)
+ :QVideoRendererControl(parent)
+ {}
+};
+
+class QT7VideoWidgetControl : public QVideoWidgetControl, public QT7VideoOutput
+{
+Q_OBJECT
+Q_INTERFACES(QT7VideoOutput)
+public:
+ virtual ~QT7VideoWidgetControl() {}
+
+protected:
+ QT7VideoWidgetControl(QObject *parent)
+ :QVideoWidgetControl(parent)
+ {}
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qt7/qt7videooutput.mm b/src/plugins/qt7/qt7videooutput.mm
new file mode 100644
index 000000000..2be053669
--- /dev/null
+++ b/src/plugins/qt7/qt7videooutput.mm
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qt7playercontrol.h"
+#include "qt7playersession.h"
+#include <QtCore/qdebug.h>
+
+QT_USE_NAMESPACE
+
+/*
+QT7VideoOutputControl::QT7VideoOutputControl(QObject *parent)
+ :QVideoOutputControl(parent),
+ m_session(0),
+ m_output(QVideoOutputControl::NoOutput)
+{
+}
+
+QT7VideoOutputControl::~QT7VideoOutputControl()
+{
+}
+
+void QT7VideoOutputControl::setSession(QT7PlayerSession *session)
+{
+ m_session = session;
+}
+
+QList<QVideoOutputControl::Output> QT7VideoOutputControl::availableOutputs() const
+{
+ return m_outputs;
+}
+
+void QT7VideoOutputControl::enableOutput(QVideoOutputControl::Output output)
+{
+ if (!m_outputs.contains(output))
+ m_outputs.append(output);
+}
+
+QVideoOutputControl::Output QT7VideoOutputControl::output() const
+{
+ return m_output;
+}
+
+void QT7VideoOutputControl::setOutput(Output output)
+{
+ if (m_output != output) {
+ m_output = output;
+ emit videoOutputChanged(m_output);
+ }
+}
+
+#include "moc_qt7videooutputcontrol.cpp"
+
+*/
diff --git a/src/plugins/simulator/camera/simulatorcamera.pri b/src/plugins/simulator/camera/simulatorcamera.pri
new file mode 100644
index 000000000..867fc4b31
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorcamera.pri
@@ -0,0 +1,25 @@
+INCLUDEPATH += $$PWD \
+ $${SOURCE_DIR}/src/multimedia
+
+INCLUDEPATH += camera
+
+HEADERS += \
+ $$PWD/simulatorcameraservice.h \
+ $$PWD/simulatorcamerasession.h \
+ $$PWD/simulatorcameracontrol.h \
+ $$PWD/simulatorvideorenderercontrol.h \
+ $$PWD/simulatorvideoinputdevicecontrol.h \
+ $$PWD/simulatorcameraimagecapturecontrol.h \
+ $$PWD/simulatorcameraexposurecontrol.h \
+ $$PWD/simulatorcamerasettings.h
+
+SOURCES += \
+ $$PWD/simulatorcameraservice.cpp \
+ $$PWD/simulatorcamerasession.cpp \
+ $$PWD/simulatorcameracontrol.cpp \
+ $$PWD/simulatorvideorenderercontrol.cpp \
+ $$PWD/simulatorvideoinputdevicecontrol.cpp \
+ $$PWD/simulatorcameraimagecapturecontrol.cpp \
+ $$PWD/simulatorcameraexposurecontrol.cpp \
+ $$PWD/simulatorcamerasettings.cpp
+
diff --git a/src/plugins/simulator/camera/simulatorcameracontrol.cpp b/src/plugins/simulator/camera/simulatorcameracontrol.cpp
new file mode 100644
index 000000000..384215295
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorcameracontrol.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** 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 "simulatorcameracontrol.h"
+
+#include <QtCore/qfile.h>
+
+SimulatorCameraControl::SimulatorCameraControl(SimulatorCameraSession *session)
+ :QCameraControl(session),
+ m_session(session),
+ mState(QCamera::UnloadedState),
+ mStatus(QCamera::UnloadedStatus)
+{
+}
+
+SimulatorCameraControl::~SimulatorCameraControl()
+{
+}
+
+QCamera::CaptureMode SimulatorCameraControl::captureMode() const
+{
+ return m_session->captureMode();
+}
+
+void SimulatorCameraControl::setCaptureMode(QCamera::CaptureMode mode)
+{
+ if (m_session->captureMode() != mode) {
+ m_session->setCaptureMode(mode);
+ emit captureModeChanged(mode);
+ }
+}
+
+void SimulatorCameraControl::setState(QCamera::State state)
+{
+ if (mState == state) {
+ return;
+ }
+
+ // Simulator only supports these status
+ Q_ASSERT(mStatus == QCamera::UnloadedStatus || mStatus == QCamera::LoadedStatus
+ || mStatus == QCamera::ActiveStatus);
+
+ switch (state) {
+ case QCamera::UnloadedState: // To UnloadedState - Release resources
+ switch (mStatus) {
+ case QCamera::LoadedStatus:
+ // Unload
+ break;
+ case QCamera::ActiveStatus:
+ // Stop and Unload
+ emit stopCamera();
+ break;
+ default:
+ // Unrecognized internal state (Status)
+ return;
+ }
+ mStatus = QCamera::UnloadedStatus;
+ emit statusChanged(mStatus);
+ break;
+
+ case QCamera::LoadedState: // To LoadedState - Reserve resources OR Stop ViewFinder and Cancel Capture
+ switch (mStatus) {
+ case QCamera::UnloadedStatus:
+ // Load
+ mStatus = QCamera::LoadingStatus;
+ emit statusChanged(mStatus);
+ break;
+ case QCamera::ActiveStatus:
+ // Stop
+ emit stopCamera();
+ break;
+
+ default:
+ // Unregocnized internal state (Status)
+ return;
+ }
+ mStatus = QCamera::LoadedStatus;
+ emit statusChanged(mStatus);
+ break;
+
+ case QCamera::ActiveState: // To ActiveState - (Reserve Resources and) Start ViewFinder
+ switch (mStatus) {
+ case QCamera::UnloadedStatus:
+ // Load and Start (setting state handles starting)
+ mStatus = QCamera::LoadingStatus;
+ emit statusChanged(mStatus);
+ mStatus = QCamera::LoadedStatus;
+ emit statusChanged(mStatus);
+ mStatus = QCamera::StartingStatus;
+ emit statusChanged(mStatus);
+ emit startCamera();
+ break;
+ case QCamera::LoadedStatus:
+ // Start
+ mStatus = QCamera::StartingStatus;
+ emit statusChanged(mStatus);
+ emit startCamera();
+ break;
+ default:
+ // Unregocnized internal state (Status)
+ return;
+ }
+ mStatus = QCamera::ActiveStatus;
+ emit statusChanged(mStatus);
+ break;
+
+ default:
+ return;
+ }
+
+ mState = state;
+ emit stateChanged(mState);
+}
+
+QCamera::State SimulatorCameraControl::state() const
+{
+ return mState;
+}
+
+bool SimulatorCameraControl::canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const
+{
+ Q_UNUSED(status);
+
+ switch (changeType) {
+ case QCameraControl::CaptureMode:
+ case QCameraControl::Viewfinder:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool SimulatorCameraControl::isCaptureModeSupported(QCamera::CaptureMode mode) const
+{
+ return mode == QCamera::CaptureStillImage;
+}
+
+QCamera::Status SimulatorCameraControl::status() const
+{
+ return mStatus;
+}
diff --git a/src/plugins/simulator/camera/simulatorcameracontrol.h b/src/plugins/simulator/camera/simulatorcameracontrol.h
new file mode 100644
index 000000000..779f8150c
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorcameracontrol.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 SIMULATORCAMERACONTROL_H
+#define SIMULATORCAMERACONTROL_H
+
+#include <QHash>
+#include <qcameracontrol.h>
+#include "simulatorcamerasession.h"
+
+QT_USE_NAMESPACE
+QT_USE_NAMESPACE
+
+class SimulatorCameraControl : public QCameraControl
+{
+ Q_OBJECT
+public:
+ SimulatorCameraControl(SimulatorCameraSession *session );
+ virtual ~SimulatorCameraControl();
+
+ bool isValid() const { return true; }
+
+ QCamera::State state() const;
+ void setState(QCamera::State state);
+
+ QCamera::Status status() const;
+
+ QCamera::CaptureMode captureMode() const;
+ void setCaptureMode(QCamera::CaptureMode mode);
+
+ bool isCaptureModeSupported(QCamera::CaptureMode mode) const;
+
+ bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const;
+
+signals:
+ void startCamera();
+ void stopCamera();
+
+private:
+ void updateSupportedResolutions(const QString &device);
+
+ SimulatorCameraSession *m_session;
+ QCamera::State mState;
+ QCamera::Status mStatus;
+ bool m_reloadPending;
+};
+
+#endif // CAMERACONTROL_H
diff --git a/src/plugins/simulator/camera/simulatorcameraexposurecontrol.cpp b/src/plugins/simulator/camera/simulatorcameraexposurecontrol.cpp
new file mode 100644
index 000000000..d99d521d1
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorcameraexposurecontrol.cpp
@@ -0,0 +1,502 @@
+/****************************************************************************
+**
+** 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 <QtCore/qstring.h>
+
+#include "simulatorcameraexposurecontrol.h"
+#include "simulatorcamerasession.h"
+
+SimulatorCameraExposureControl::SimulatorCameraExposureControl(SimulatorCameraSession *session, QObject *parent) :
+ QCameraExposureControl(parent),
+ mExposureMode(QCameraExposure::ExposureAuto),
+ mMeteringMode(QCameraExposure::MeteringAverage),
+ mSession(session),
+ mSettings(0)
+{
+ mSettings = mSession->settings();
+
+ connect(mSettings, SIGNAL(apertureChanged()), this, SLOT(apertureChanged()));
+ connect(mSettings, SIGNAL(apertureRangeChanged()), this, SLOT(apertureRangeChanged()));
+ connect(mSettings, SIGNAL(shutterSpeedChanged()), this, SLOT(shutterSpeedChanged()));
+ connect(mSettings, SIGNAL(isoSensitivityChanged()), this, SLOT(isoSensitivityChanged()));
+}
+
+SimulatorCameraExposureControl::~SimulatorCameraExposureControl()
+{
+}
+
+void SimulatorCameraExposureControl::apertureChanged()
+{
+ emit exposureParameterChanged(QCameraExposureControl::Aperture);
+}
+
+void SimulatorCameraExposureControl::apertureRangeChanged()
+{
+ emit exposureParameterRangeChanged(QCameraExposureControl::Aperture);
+}
+
+void SimulatorCameraExposureControl::shutterSpeedChanged()
+{
+ emit exposureParameterChanged(QCameraExposureControl::ShutterSpeed);
+}
+
+void SimulatorCameraExposureControl::isoSensitivityChanged()
+{
+ emit exposureParameterChanged(QCameraExposureControl::ISO);
+}
+
+QCameraExposure::ExposureMode SimulatorCameraExposureControl::exposureMode() const
+{
+ return mExposureMode;
+}
+
+void SimulatorCameraExposureControl::setExposureMode(QCameraExposure::ExposureMode mode)
+{
+ if (isExposureModeSupported(mode))
+ mExposureMode = mode;
+}
+
+bool SimulatorCameraExposureControl::isExposureModeSupported(QCameraExposure::ExposureMode mode) const
+{
+ switch (mode) {
+ case QCameraExposure::ExposureAuto:
+ case QCameraExposure::ExposureManual:
+ return true;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+QCameraExposure::MeteringMode SimulatorCameraExposureControl::meteringMode() const
+{
+ return mMeteringMode;
+}
+
+void SimulatorCameraExposureControl::setMeteringMode(QCameraExposure::MeteringMode mode)
+{
+ if (isMeteringModeSupported(mode))
+ mMeteringMode = mode;
+}
+
+bool SimulatorCameraExposureControl::isMeteringModeSupported(QCameraExposure::MeteringMode mode) const
+{
+ switch (mode) {
+ case QCameraExposure::MeteringAverage:
+ case QCameraExposure::MeteringSpot:
+ case QCameraExposure::MeteringMatrix:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+bool SimulatorCameraExposureControl::isParameterSupported(ExposureParameter parameter) const
+{
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ case QCameraExposureControl::Aperture:
+ case QCameraExposureControl::ShutterSpeed:
+ case QCameraExposureControl::ExposureCompensation:
+ return true;
+ case QCameraExposureControl::FlashPower:
+ case QCameraExposureControl::FlashCompensation:
+ return false;
+
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+QVariant SimulatorCameraExposureControl::exposureParameter(ExposureParameter parameter) const
+{
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ return QVariant(isoSensitivity());
+ case QCameraExposureControl::Aperture:
+ return QVariant(aperture());
+ case QCameraExposureControl::ShutterSpeed:
+ return QVariant(shutterSpeed());
+ case QCameraExposureControl::ExposureCompensation:
+ return QVariant(exposureCompensation());
+ case QCameraExposureControl::FlashPower:
+ case QCameraExposureControl::FlashCompensation:
+ // Not supported
+ return QVariant();
+
+ default:
+ // Not supported
+ return QVariant();
+ }
+}
+
+QCameraExposureControl::ParameterFlags SimulatorCameraExposureControl::exposureParameterFlags(ExposureParameter parameter) const
+{
+ QCameraExposureControl::ParameterFlags flags;
+
+ /*
+ * ISO, Aperture, ShutterSpeed:
+ * - Automatic/Manual
+ * - Read/Write
+ * - Discrete range
+ *
+ * ExposureCompensation:
+ * - Automatic/Manual
+ * - Read/Write
+ * - Continuous range
+ *
+ * FlashPower, FlashCompensation:
+ * - Not supported
+ */
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ case QCameraExposureControl::Aperture:
+ case QCameraExposureControl::ShutterSpeed:
+ flags |= QCameraExposureControl::AutomaticValue;
+ break;
+ case QCameraExposureControl::ExposureCompensation:
+ flags |= QCameraExposureControl::AutomaticValue;
+ flags |= QCameraExposureControl::ContinuousRange;
+ break;
+ case QCameraExposureControl::FlashPower:
+ case QCameraExposureControl::FlashCompensation:
+ // Do nothing - no flags
+ break;
+
+ default:
+ // Do nothing - no flags
+ break;
+ }
+
+ return flags;
+}
+
+QVariantList SimulatorCameraExposureControl::supportedParameterRange(ExposureParameter parameter) const
+{
+ QVariantList valueList;
+ switch (parameter) {
+ case QCameraExposureControl::ISO: {
+ QList<int> exposureValues = mSettings->supportedIsoSensitivities();
+ for (int i = 0; i < exposureValues.count(); ++i) {
+ valueList.append(QVariant(exposureValues[i]));
+ }
+ break;
+ }
+ case QCameraExposureControl::Aperture: {
+ QList<qreal> apertureValues = mSettings->supportedApertures();
+ for (int i = 0; i < apertureValues.count(); ++i) {
+ valueList.append(QVariant(apertureValues[i]));
+ }
+ break;
+ }
+ case QCameraExposureControl::ShutterSpeed: {
+ QList<qreal> shutterSpeedValues = mSettings->supportedShutterSpeeds();
+ for (int i = 0; i < shutterSpeedValues.count(); ++i) {
+ valueList.append(QVariant(shutterSpeedValues[i]));
+ }
+ break;
+ }
+ case QCameraExposureControl::ExposureCompensation: {
+ QList<qreal> evValues = mSettings->supportedExposureCompensationValues();
+ for (int i = 0; i < evValues.count(); ++i) {
+ valueList.append(QVariant(evValues[i]));
+ }
+ break;
+ }
+ case QCameraExposureControl::FlashPower:
+ case QCameraExposureControl::FlashCompensation:
+ // Not supported
+ break;
+
+ default:
+ // Not supported
+ return QVariantList();
+ }
+
+ return valueList;
+}
+
+bool SimulatorCameraExposureControl::setExposureParameter(ExposureParameter parameter, const QVariant& value)
+{
+ bool useDefaultValue = false;
+
+ if (value.isNull())
+ useDefaultValue = true;
+
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ if (useDefaultValue) {
+ setAutoIsoSensitivity();
+ return false;
+ }
+ else
+ return setManualIsoSensitivity(value.toInt());
+
+ case QCameraExposureControl::Aperture:
+ if (useDefaultValue) {
+ setAutoAperture();
+ return false;
+ }
+ else
+ return setManualAperture(value.toReal());
+
+ case QCameraExposureControl::ShutterSpeed:
+ if (useDefaultValue) {
+ setAutoShutterSpeed();
+ return false;
+ }
+ else
+ return setManualShutterSpeed(value.toReal());
+
+ case QCameraExposureControl::ExposureCompensation:
+ if (useDefaultValue) {
+ setAutoExposureCompensation();
+ return false;
+ }
+ else
+ return setManualExposureCompensation(value.toReal());
+
+ case QCameraExposureControl::FlashPower:
+ return false;
+ case QCameraExposureControl::FlashCompensation:
+ return false;
+
+ default:
+ // Not supported
+ return false;
+ }
+}
+
+QString SimulatorCameraExposureControl::extendedParameterName(ExposureParameter parameter)
+{
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ return QString("ISO Sensitivity");
+ case QCameraExposureControl::Aperture:
+ return QString("Aperture");
+ case QCameraExposureControl::ShutterSpeed:
+ return QString("Shutter Speed");
+ case QCameraExposureControl::ExposureCompensation:
+ return QString("Exposure Compensation");
+ case QCameraExposureControl::FlashPower:
+ return QString("Flash Power");
+ case QCameraExposureControl::FlashCompensation:
+ return QString("Flash Compensation");
+
+ default:
+ return QString();
+ }
+}
+
+int SimulatorCameraExposureControl::isoSensitivity() const
+{
+ return mSettings->isoSensitivity();
+}
+
+bool SimulatorCameraExposureControl::isIsoSensitivitySupported(const int iso) const
+{
+ return mSettings->supportedIsoSensitivities().contains(iso);
+}
+
+bool SimulatorCameraExposureControl::setManualIsoSensitivity(int iso)
+{
+ if (isIsoSensitivitySupported(iso)) {
+ mSettings->setManualIsoSensitivity(iso);
+ return true;
+ } else {
+ QList<int> supportedIsoValues = mSettings->supportedIsoSensitivities();
+ int minIso = supportedIsoValues.first();
+ int maxIso = supportedIsoValues.last();
+
+ if (iso < minIso) { // Smaller than minimum
+ iso = minIso;
+ } else if (iso > maxIso) { // Bigger than maximum
+ iso = maxIso;
+ } else { // Find closest
+ int indexOfClosest = 0;
+ int smallestDiff = 10000000; // Sensible max diff
+ for(int i = 0; i < supportedIsoValues.count(); ++i) {
+ int currentDiff = qAbs(iso - supportedIsoValues[i]);
+ if(currentDiff < smallestDiff) {
+ smallestDiff = currentDiff;
+ indexOfClosest = i;
+ }
+ }
+ iso = supportedIsoValues[indexOfClosest];
+ }
+ mSettings->setManualIsoSensitivity(iso);
+ }
+
+ return false;
+}
+
+void SimulatorCameraExposureControl::setAutoIsoSensitivity()
+{
+ mSettings->setAutoIsoSensitivity();
+}
+
+
+qreal SimulatorCameraExposureControl::aperture() const
+{
+ return mSettings->aperture();
+}
+
+bool SimulatorCameraExposureControl::isApertureSupported(const qreal aperture) const
+{
+ return mSettings->supportedApertures().contains(aperture);
+}
+
+bool SimulatorCameraExposureControl::setManualAperture(qreal aperture)
+{
+ if (isApertureSupported(aperture)) {
+ mSettings->setManualAperture(aperture);
+ return true;
+ } else {
+ QList<qreal> supportedApertureValues = mSettings->supportedApertures();
+ qreal minAperture = supportedApertureValues.first();
+ qreal maxAperture = supportedApertureValues.last();
+
+ if (aperture < minAperture) { // Smaller than minimum
+ aperture = minAperture;
+ } else if (aperture > maxAperture) { // Bigger than maximum
+ aperture = maxAperture;
+ } else { // Find closest
+ int indexOfClosest = 0;
+ qreal smallestDiff = 100000000; // Sensible max diff
+ for(int i = 0; i < supportedApertureValues.count(); ++i) {
+ qreal currentDiff = qAbs(aperture - supportedApertureValues[i]);
+ if(currentDiff < smallestDiff) {
+ smallestDiff = currentDiff;
+ indexOfClosest = i;
+ }
+ }
+ aperture = supportedApertureValues[indexOfClosest];
+ }
+ mSettings->setManualAperture(aperture);
+ }
+
+ return false;
+}
+
+void SimulatorCameraExposureControl::setAutoAperture()
+{
+ mSettings->setAutoAperture();
+}
+
+qreal SimulatorCameraExposureControl::shutterSpeed() const
+{
+ return mSettings->shutterSpeed();
+}
+
+bool SimulatorCameraExposureControl::isShutterSpeedSupported(const qreal seconds) const
+{
+ return mSettings->supportedShutterSpeeds().contains(seconds);
+}
+
+bool SimulatorCameraExposureControl::setManualShutterSpeed(qreal seconds)
+{
+ if (isShutterSpeedSupported(seconds)) {
+ mSettings->setManualShutterSpeed(seconds);
+ return true;
+ } else {
+ QList<qreal> supportedShutterSpeeds = mSettings->supportedShutterSpeeds();
+
+ qreal minShutterSpeed = supportedShutterSpeeds.first();
+ qreal maxShutterSpeed = supportedShutterSpeeds.last();
+
+ if (seconds < minShutterSpeed) { // Smaller than minimum
+ seconds = minShutterSpeed;
+ } else if (seconds > maxShutterSpeed) { // Bigger than maximum
+ seconds = maxShutterSpeed;
+ } else { // Find closest
+ int indexOfClosest = 0;
+ qreal smallestDiff = 100000000; // Sensible max diff
+ for(int i = 0; i < supportedShutterSpeeds.count(); ++i) {
+ qreal currentDiff = qAbs(seconds - supportedShutterSpeeds[i]);
+ if(currentDiff < smallestDiff) {
+ smallestDiff = currentDiff;
+ indexOfClosest = i;
+ }
+ }
+ seconds = supportedShutterSpeeds[indexOfClosest];
+ }
+ mSettings->setManualShutterSpeed(seconds);
+ }
+
+ return false;
+}
+
+void SimulatorCameraExposureControl::setAutoShutterSpeed()
+{
+ mSettings->setAutoShutterSpeed();
+}
+
+qreal SimulatorCameraExposureControl::exposureCompensation() const
+{
+ return mSettings->exposureCompensation();
+}
+
+bool SimulatorCameraExposureControl::isExposureCompensationSupported(const qreal ev) const
+{
+ QList<qreal> supportedValues = mSettings->supportedExposureCompensationValues();
+ return (ev >= supportedValues.first() && ev <= supportedValues.last());
+}
+
+bool SimulatorCameraExposureControl::setManualExposureCompensation(qreal ev)
+{
+ if (isExposureCompensationSupported(ev)) {
+ mSettings->setExposureCompensation(ev);
+ return true;
+ }
+
+ return false;
+}
+
+void SimulatorCameraExposureControl::setAutoExposureCompensation()
+{
+ mSettings->setAutoExposureCompensation();
+}
+
+// End of file
diff --git a/src/plugins/simulator/camera/simulatorcameraexposurecontrol.h b/src/plugins/simulator/camera/simulatorcameraexposurecontrol.h
new file mode 100644
index 000000000..5ffa362e1
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorcameraexposurecontrol.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** 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 SIMULATORCAMERAEXPOSURECONTROL_H
+#define SIMULATORCAMERAEXPOSURECONTROL_H
+
+#include <qcameraexposurecontrol.h>
+
+#include "simulatorcamerasettings.h"
+
+QT_BEGIN_NAMESPACE
+
+class SimulatorCameraSession;
+
+/*
+ * Control for exposure related camera operation.
+ */
+class SimulatorCameraExposureControl : public QCameraExposureControl
+{
+ Q_OBJECT
+
+public:
+
+ SimulatorCameraExposureControl(SimulatorCameraSession *session, QObject *parent = 0);
+ ~SimulatorCameraExposureControl();
+
+ // QCameraExposureControl
+ // Exposure Mode
+ QCameraExposure::ExposureMode exposureMode() const;
+ void setExposureMode(QCameraExposure::ExposureMode mode);
+ bool isExposureModeSupported(QCameraExposure::ExposureMode mode) const;
+
+ // Metering Mode
+ QCameraExposure::MeteringMode meteringMode() const;
+ void setMeteringMode(QCameraExposure::MeteringMode mode);
+ bool isMeteringModeSupported(QCameraExposure::MeteringMode mode) const;
+
+ // Exposure Parameter
+ bool isParameterSupported(ExposureParameter parameter) const;
+ QVariant exposureParameter(ExposureParameter parameter) const;
+ QCameraExposureControl::ParameterFlags exposureParameterFlags(ExposureParameter parameter) const;
+ QVariantList supportedParameterRange(ExposureParameter parameter) const;
+ bool setExposureParameter(ExposureParameter parameter, const QVariant& value);
+
+ QString extendedParameterName(ExposureParameter parameter);
+
+private Q_SLOTS: // Internal Slots
+ void apertureChanged();
+ void apertureRangeChanged();
+ void shutterSpeedChanged();
+ void isoSensitivityChanged();
+
+private: // Internal - Implementing ExposureParameter
+ // ISO Sensitivity
+ int isoSensitivity() const;
+ bool setManualIsoSensitivity(int iso);
+ void setAutoIsoSensitivity();
+ bool isIsoSensitivitySupported(const int iso) const;
+
+ // Aperture
+ qreal aperture() const;
+ bool setManualAperture(qreal aperture);
+ void setAutoAperture();
+ bool isApertureSupported(const qreal aperture) const;
+
+ // Shutter Speed
+ qreal shutterSpeed() const;
+ bool setManualShutterSpeed(qreal seconds);
+ void setAutoShutterSpeed();
+ bool isShutterSpeedSupported(const qreal seconds) const;
+
+ // Exposure Compensation
+ qreal exposureCompensation() const;
+ bool setManualExposureCompensation(qreal ev);
+ void setAutoExposureCompensation();
+ bool isExposureCompensationSupported(const qreal ev) const;
+
+private: // Data
+ QCameraExposure::ExposureMode mExposureMode;
+ QCameraExposure::MeteringMode mMeteringMode;
+ SimulatorCameraSession *mSession;
+ SimulatorCameraSettings *mSettings;
+};
+
+QT_END_NAMESPACE
+
+#endif // SIMULATORCAMERAEXPOSURECONTROL_H
diff --git a/src/plugins/simulator/camera/simulatorcameraimagecapturecontrol.cpp b/src/plugins/simulator/camera/simulatorcameraimagecapturecontrol.cpp
new file mode 100644
index 000000000..a0c8dce66
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorcameraimagecapturecontrol.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** 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 <QtCore/qstring.h>
+
+#include "simulatorcameraimagecapturecontrol.h"
+#include "simulatorcameraservice.h"
+#include "simulatorcamerasession.h"
+#include "simulatorcameracontrol.h"
+
+SimulatorCameraImageCaptureControl::SimulatorCameraImageCaptureControl(SimulatorCameraSession *session, SimulatorCameraService *service) :
+ QCameraImageCaptureControl(service),
+ mReadyForCapture(true),
+ m_driveMode(QCameraImageCapture::SingleImageCapture) // Default DriveMode
+{
+ m_session = session;
+
+ m_service = service;
+ m_cameraControl = qobject_cast<SimulatorCameraControl *>(m_service->requestControl(QCameraControl_iid));
+
+ // Chain these signals from session class
+ connect(m_session, SIGNAL(imageCaptured(const int, QImage)),
+ this, SIGNAL(imageCaptured(const int, QImage)));
+ connect(m_session, SIGNAL(imageSaved(const int, const QString&)),
+ this, SIGNAL(imageSaved(const int, const QString&)));
+ connect(m_session, SIGNAL(imageExposed(int)),
+ this, SIGNAL(imageExposed(int)));
+ connect(m_session, SIGNAL(captureError(int, int, const QString&)),
+ this, SIGNAL(error(int, int, const QString&)));
+}
+
+SimulatorCameraImageCaptureControl::~SimulatorCameraImageCaptureControl()
+{
+}
+
+bool SimulatorCameraImageCaptureControl::isReadyForCapture() const
+{
+ if (m_cameraControl && m_cameraControl->captureMode() != QCamera::CaptureStillImage) {
+ return false;
+ }
+
+ return mReadyForCapture;
+}
+
+QCameraImageCapture::DriveMode SimulatorCameraImageCaptureControl::driveMode() const
+{
+ return m_driveMode;
+}
+
+void SimulatorCameraImageCaptureControl::setDriveMode(QCameraImageCapture::DriveMode mode)
+{
+ if (mode != QCameraImageCapture::SingleImageCapture) {
+ emit error(0, QCamera::NotSupportedFeatureError, tr("DriveMode not supported."));
+ return;
+ }
+
+ m_driveMode = mode;
+}
+
+int SimulatorCameraImageCaptureControl::capture(const QString &fileName)
+{
+ if (m_cameraControl && m_cameraControl->captureMode() != QCamera::CaptureStillImage) {
+ emit error(0, QCameraImageCapture::NotReadyError, tr("Incorrect CaptureMode."));
+ return 0;
+ }
+ updateReadyForCapture(false);
+ int imageId = m_session->captureImage(fileName);
+ updateReadyForCapture(true);
+ return imageId;
+}
+
+void SimulatorCameraImageCaptureControl::cancelCapture()
+{
+}
+
+void SimulatorCameraImageCaptureControl::updateReadyForCapture(bool ready)
+{
+ mReadyForCapture = ready;
+ emit readyForCaptureChanged(mReadyForCapture);
+}
+
+// End of file
diff --git a/src/plugins/simulator/camera/simulatorcameraimagecapturecontrol.h b/src/plugins/simulator/camera/simulatorcameraimagecapturecontrol.h
new file mode 100644
index 000000000..e45483e72
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorcameraimagecapturecontrol.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 SIMULATORCAMERAIMAGECAPTURECONTROL_H
+#define SIMULATORCAMERAIMAGECAPTURECONTROL_H
+
+#include "qcameraimagecapturecontrol.h"
+
+QT_USE_NAMESPACE
+
+class SimulatorCameraService;
+class SimulatorCameraSession;
+class SimulatorCameraControl;
+
+/*
+ * Control for image capture operations.
+ */
+class SimulatorCameraImageCaptureControl : public QCameraImageCaptureControl
+{
+ Q_OBJECT
+
+public: // Contructors & Destrcutor
+
+ SimulatorCameraImageCaptureControl(SimulatorCameraSession *session, SimulatorCameraService *service);
+ ~SimulatorCameraImageCaptureControl();
+
+public: // QCameraImageCaptureControl
+
+ bool isReadyForCapture() const;
+
+ // Drive Mode
+ QCameraImageCapture::DriveMode driveMode() const;
+ void setDriveMode(QCameraImageCapture::DriveMode mode);
+
+ // Capture
+ int capture(const QString &fileName);
+ void cancelCapture();
+
+private:
+ void updateReadyForCapture(bool ready);
+
+ bool mReadyForCapture;
+ SimulatorCameraSession *m_session;
+ SimulatorCameraService *m_service;
+ SimulatorCameraControl *m_cameraControl;
+ QCameraImageCapture::DriveMode m_driveMode;
+};
+
+#endif // SIMULATORCAMERAIMAGECAPTURECONTROL_H
diff --git a/src/plugins/simulator/camera/simulatorcameraservice.cpp b/src/plugins/simulator/camera/simulatorcameraservice.cpp
new file mode 100644
index 000000000..6eee2ec02
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorcameraservice.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** 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$
+** 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 "simulatorcameraservice.h"
+#include "simulatorcamerasession.h"
+#include "simulatorcameracontrol.h"
+#include "simulatorcameraimagecapturecontrol.h"
+#include "simulatorcameraexposurecontrol.h"
+
+#include "simulatorvideoinputdevicecontrol.h"
+#include "simulatorvideorenderercontrol.h"
+#include "../qsimulatormultimediaconnection_p.h"
+
+#include <qmediaserviceprovider.h>
+#include <QtCore/QDebug>
+
+QTM_USE_NAMESPACE;
+using namespace Simulator;
+
+SimulatorCameraService::SimulatorCameraService(const QString &service, MultimediaConnection *multimediaConnection,
+ QObject *parent):
+ QMediaService(parent)
+{
+ Q_UNUSED(service)
+ mCaptureSession = new SimulatorCameraSession(this);
+ mCameraControl = new SimulatorCameraControl(mCaptureSession);
+ mVideoInputDeviceControl = new QSimulatorVideoInputDeviceControl(mCaptureSession);
+ mVideoInputDeviceControl->updateDeviceList(get_qtCameraData());
+ mVideoRendererControl = new SimulatorVideoRendererControl(mCaptureSession, this);
+ mImageCaptureControl = new SimulatorCameraImageCaptureControl(mCaptureSession, this);
+ mExposureControl = new SimulatorCameraExposureControl(mCaptureSession, this);
+
+ connect(multimediaConnection, SIGNAL(cameraDataChanged(QtMobility::QCameraData)),
+ SLOT(updateCameraData(QtMobility::QCameraData)));
+ connect(multimediaConnection, SIGNAL(cameraAdded(QString,QtMobility::QCameraData::QCameraDetails)),
+ mVideoInputDeviceControl, SLOT(addDevice(QString,QtMobility::QCameraData::QCameraDetails)));
+ connect(multimediaConnection, SIGNAL(cameraRemoved(QString)),
+ mVideoInputDeviceControl, SLOT(removeDevice(QString)));
+ connect(multimediaConnection, SIGNAL(cameraChanged(QString,QtMobility::QCameraData::QCameraDetails)),
+ mVideoInputDeviceControl, SLOT(changeDevice(QString,QtMobility::QCameraData::QCameraDetails)));
+ connect(multimediaConnection, SIGNAL(cameraChanged(QString,QtMobility::QCameraData::QCameraDetails)),
+ SLOT(changeCamera(QString,QtMobility::QCameraData::QCameraDetails)));
+ connect(mCameraControl, SIGNAL(startCamera()),
+ mVideoRendererControl, SLOT(showImage()));
+ connect(mCameraControl, SIGNAL(stopCamera()),
+ mVideoRendererControl, SLOT(stop()));
+ connect(mVideoInputDeviceControl, SIGNAL(selectedDeviceChanged(QString)),
+ SLOT(updateCameraPicture(QString)));
+ connect(mCaptureSession->settings(), SIGNAL(isoSensitivityChanged()), mVideoRendererControl, SLOT(showImage()));
+ connect(mCaptureSession->settings(), SIGNAL(apertureChanged()), mVideoRendererControl, SLOT(showImage()));
+ connect(mCaptureSession->settings(), SIGNAL(shutterSpeedChanged()), mVideoRendererControl, SLOT(showImage()));
+ connect(mCaptureSession->settings(), SIGNAL(exposureCompensationChanged()), mVideoRendererControl, SLOT(showImage()));
+ mCaptureSession->setImage(mVideoRendererControl->image());
+ mVideoInputDeviceControl->setSelectedDevice(mVideoInputDeviceControl->defaultDevice());
+}
+
+SimulatorCameraService::~SimulatorCameraService()
+{
+}
+
+QMediaControl *SimulatorCameraService::requestControl(const char *name)
+{
+ if (!mCaptureSession)
+ return 0;
+
+ if (qstrcmp(name,QCameraControl_iid) == 0)
+ return mCameraControl;
+
+ if (qstrcmp(name,QVideoDeviceControl_iid) == 0)
+ return mVideoInputDeviceControl;
+
+ if (qstrcmp(name, QVideoRendererControl_iid) == 0)
+ return mVideoRendererControl;
+
+ if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
+ return mImageCaptureControl;
+
+ if (qstrcmp(name, QCameraExposureControl_iid) == 0)
+ return mExposureControl;
+
+ return 0;
+}
+
+void SimulatorCameraService::releaseControl(QMediaControl *control)
+{
+ Q_UNUSED(control)
+}
+
+void SimulatorCameraService::updateCameraData(const QtMobility::QCameraData &data)
+{
+ mVideoInputDeviceControl->updateDeviceList(data);
+ QString currentDevice = mVideoInputDeviceControl->deviceName(mVideoInputDeviceControl->selectedDevice());
+ if (!data.cameras.contains(currentDevice))
+ return;
+
+ updateCurrentDeviceImage(data.cameras.value(currentDevice).imagePath);
+}
+
+void SimulatorCameraService::changeCamera(const QString &name, const QtMobility::QCameraData::QCameraDetails &details)
+{
+ QString currentDevice = mVideoInputDeviceControl->deviceName(mVideoInputDeviceControl->selectedDevice());
+ if (currentDevice != name)
+ return;
+
+ updateCurrentDeviceImage(details.imagePath);
+}
+
+void SimulatorCameraService::updateCameraPicture(const QString &name)
+{
+ QtMobility::QCameraData data = QtMobility::get_qtCameraData();
+ if (!data.cameras.contains(name))
+ return;
+
+ updateCurrentDeviceImage(data.cameras.value(name).imagePath);
+}
+
+void SimulatorCameraService::updateCurrentDeviceImage(const QString &imagePath)
+{
+ mVideoRendererControl->setImagePath(imagePath);
+ mCaptureSession->setImage(mVideoRendererControl->image());
+}
+
+#include "moc_simulatorcameraservice.cpp"
diff --git a/src/plugins/simulator/camera/simulatorcameraservice.h b/src/plugins/simulator/camera/simulatorcameraservice.h
new file mode 100644
index 000000000..b159eb393
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorcameraservice.h
@@ -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$
+** 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 SIMULATORCAMERACAPTURESERVICE_H
+#define SIMULATORCAMERACAPTURESERVICE_H
+
+#include <qmediaservice.h>
+
+#include "../qsimulatormultimediaconnection_p.h"
+
+QTM_BEGIN_NAMESPACE
+namespace Simulator {
+class MultimediaConnection;
+}
+QTM_END_NAMESPACE
+class SimulatorCameraSession;
+class SimulatorCameraControl;
+class SimulatorCameraImageCaptureControl;
+class SimulatorCameraExposureControl;
+class SimulatorVideoRendererControl;
+class QSimulatorVideoInputDeviceControl;
+
+class SimulatorCameraService : public QMediaService
+{
+ Q_OBJECT
+
+public:
+ SimulatorCameraService(const QString &service, QTM_PREPEND_NAMESPACE(Simulator::MultimediaConnection) *cameraConnection,
+ QObject *parent = 0);
+ virtual ~SimulatorCameraService();
+
+ QMediaControl *requestControl(const char *name);
+ void releaseControl(QMediaControl *);
+
+private slots:
+ void updateCameraData(const QtMobility::QCameraData &data);
+ void changeCamera(const QString &name, const QtMobility::QCameraData::QCameraDetails &details);
+ void updateCameraPicture(const QString &name);
+
+private:
+ void updateCurrentDeviceImage(const QString &imagePath);
+ SimulatorCameraSession *mCaptureSession;
+ SimulatorCameraControl *mCameraControl;
+ SimulatorCameraImageCaptureControl *mImageCaptureControl;
+ SimulatorCameraExposureControl *mExposureControl;
+
+ QSimulatorVideoInputDeviceControl *mVideoInputDeviceControl;
+
+ QMediaControl *mVideoOutput;
+
+ SimulatorVideoRendererControl *mVideoRendererControl;
+};
+
+#endif // CAMERACAPTURESERVICE_H
diff --git a/src/plugins/simulator/camera/simulatorcamerasession.cpp b/src/plugins/simulator/camera/simulatorcamerasession.cpp
new file mode 100644
index 000000000..17dd2f762
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorcamerasession.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** 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$
+** 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 "simulatorcamerasession.h"
+#include "simulatorcamerasettings.h"
+#include "../qsimulatormultimediaconnection_p.h"
+#include <qmediarecorder.h>
+#include <qcameraimagecapture.h>
+
+#include <QtCore/qdebug.h>
+#include <QCoreApplication>
+#include <QtCore/qmetaobject.h>
+
+#include <QtGui/qimage.h>
+
+//#define CAMERA_DEBUG 1
+
+SimulatorCameraSession::SimulatorCameraSession(QObject *parent)
+ :QObject(parent),
+ mViewfinder(0),
+ mImage(0),
+ mRequestId(0)
+{
+ mSettings = new SimulatorCameraSettings(this);
+}
+
+SimulatorCameraSession::~SimulatorCameraSession()
+{
+}
+
+int SimulatorCameraSession::captureImage(const QString &fileName)
+{
+ QTM_USE_NAMESPACE;
+ ++mRequestId;
+ emit imageExposed(mRequestId);
+
+ QString actualFileName = fileName;
+ if (actualFileName.isEmpty()) {
+ actualFileName = generateFileName("img_", defaultDir(QCamera::CaptureStillImage), "jpg");
+ }
+
+ emit imageCaptured(mRequestId, *mImage);
+
+ if (!mImage->save(actualFileName)) {
+ emit captureError(mRequestId, QCameraImageCapture::ResourceError, "Could not save file");
+ return mRequestId;
+ }
+ emit imageSaved(mRequestId, actualFileName);
+ return mRequestId;
+}
+
+void SimulatorCameraSession::setCaptureMode(QCamera::CaptureMode mode)
+{
+ mCaptureMode = mode;
+}
+
+QDir SimulatorCameraSession::defaultDir(QCamera::CaptureMode) const
+{
+ const QString temp = QDir::tempPath();
+ if (QFileInfo(temp).isWritable())
+ return QDir(temp);
+
+ return QDir();
+}
+
+QString SimulatorCameraSession::generateFileName(const QString &prefix, const QDir &dir, const QString &ext) const
+{
+ int lastClip = 0;
+ foreach(QString fileName, dir.entryList(QStringList() << QString("%1*.%2").arg(prefix).arg(ext))) {
+ int imgNumber = fileName.mid(prefix.length(), fileName.size()-prefix.length()-ext.length()-1).toInt();
+ lastClip = qMax(lastClip, imgNumber);
+ }
+
+ QString name = QString("%1%2.%3").arg(prefix)
+ .arg(lastClip+1,
+ 4, //fieldWidth
+ 10,
+ QLatin1Char('0'))
+ .arg(ext);
+
+ return dir.absoluteFilePath(name);
+}
+
+void SimulatorCameraSession::setViewfinder(QObject *viewfinder)
+{
+ if (mViewfinder != viewfinder) {
+ mViewfinder = viewfinder;
+ emit viewfinderChanged();
+ }
+}
+
+QCamera::CaptureMode SimulatorCameraSession::captureMode()
+{
+ return mCaptureMode;
+}
+
+void SimulatorCameraSession::setImage(const QImage *image)
+{
+ mImage = image;
+}
+
+QObject *SimulatorCameraSession::viewfinder() const
+{
+ return mViewfinder;
+}
+
+SimulatorCameraSettings *SimulatorCameraSession::settings() const
+{
+ return mSettings;
+}
diff --git a/src/plugins/simulator/camera/simulatorcamerasession.h b/src/plugins/simulator/camera/simulatorcamerasession.h
new file mode 100644
index 000000000..6d1078e8d
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorcamerasession.h
@@ -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$
+** 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 SIMULATORCAMERACAPTURESESSION_H
+#define SIMULATORCAMERACAPTURESESSION_H
+
+#include <qmediarecordercontrol.h>
+
+#include <QtCore/qurl.h>
+#include <QtCore/qdir.h>
+
+#include "qcamera.h"
+
+class SimulatorCameraSettings;
+
+class SimulatorCameraSession : public QObject
+{
+ Q_OBJECT
+public:
+ SimulatorCameraSession(QObject *parent);
+ ~SimulatorCameraSession();
+
+ QCamera::CaptureMode captureMode();
+ void setCaptureMode(QCamera::CaptureMode mode);
+
+ QDir defaultDir(QCamera::CaptureMode mode) const;
+ QString generateFileName(const QString &prefix, const QDir &dir, const QString &ext) const;
+
+ void setImage(const QImage *image);
+ QObject *viewfinder() const;
+ void setViewfinder(QObject *viewfinder);
+
+ int captureImage(const QString &fileName);
+
+ SimulatorCameraSettings *settings() const;
+
+signals:
+ void stateChanged(QCamera::State state);
+ void captureError(int id, int error, const QString &errorString);
+ void error(int error, const QString &errorString);
+ void imageExposed(int requestId);
+ void imageCaptured(int requestId, const QImage &img);
+ void imageSaved(int requestId, const QString &fileName);
+ void viewfinderChanged();
+
+private:
+ QCamera::CaptureMode mCaptureMode;
+
+ QObject *mViewfinder;
+ const QImage *mImage;
+
+ SimulatorCameraSettings *mSettings;
+
+public:
+ int mRequestId;
+};
+
+#endif // SIMULATORCAMERACAPTURESESSION_H
diff --git a/src/plugins/simulator/camera/simulatorcamerasettings.cpp b/src/plugins/simulator/camera/simulatorcamerasettings.cpp
new file mode 100644
index 000000000..dd617549b
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorcamerasettings.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** 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 "simulatorcamerasettings.h"
+
+SimulatorCameraSettings::SimulatorCameraSettings(QObject *parent)
+ : QObject(parent)
+ , mIsoSensitivity(400)
+ , mAperture(4)
+ , mShutterSpeed(0.008)
+ , mExposureCompensation(0)
+{
+ mSupportedIsoSensitivities << 50 << 100 << 200 << 400 << 800;
+ mSupportedApertures << 1.8 << 2.8 << 4 << 5.6 << 8;
+ mSupportedShutterSpeeds << 0.002 << 0.004 << 0.008 << 1./60 << 1./30;
+ mSupportedExposureCompensations << -2 << 2;
+}
+
+SimulatorCameraSettings::~SimulatorCameraSettings()
+{
+}
+
+int SimulatorCameraSettings::isoSensitivity() const
+{
+ return mIsoSensitivity;
+}
+
+QList<int> SimulatorCameraSettings::supportedIsoSensitivities() const
+{
+ return mSupportedIsoSensitivities;
+}
+
+void SimulatorCameraSettings::setManualIsoSensitivity(int iso)
+{
+ if (iso != mIsoSensitivity && supportedIsoSensitivities().contains(iso)) {
+ mIsoSensitivity = iso;
+ emit isoSensitivityChanged();
+ }
+}
+
+void SimulatorCameraSettings::setAutoIsoSensitivity()
+{
+ setManualIsoSensitivity(defaultIsoSensitivity());
+}
+
+qreal SimulatorCameraSettings::aperture() const
+{
+ return mAperture;
+}
+
+QList<qreal> SimulatorCameraSettings::supportedApertures() const
+{
+ return mSupportedApertures;
+}
+
+void SimulatorCameraSettings::setManualAperture(qreal aperture)
+{
+ if (aperture != mAperture && supportedApertures().contains(aperture)) {
+ mAperture = aperture;
+ emit apertureChanged();
+ }
+}
+
+void SimulatorCameraSettings::setAutoAperture()
+{
+ setManualAperture(defaultAperture());
+}
+
+qreal SimulatorCameraSettings::shutterSpeed() const
+{
+ return mShutterSpeed;
+}
+
+QList<qreal> SimulatorCameraSettings::supportedShutterSpeeds() const
+{
+ return mSupportedShutterSpeeds;
+}
+
+void SimulatorCameraSettings::setManualShutterSpeed(qreal speed)
+{
+ if (speed != mShutterSpeed && supportedShutterSpeeds().contains(speed)) {
+ mShutterSpeed = speed;
+ emit shutterSpeedChanged();
+ }
+}
+
+void SimulatorCameraSettings::setAutoShutterSpeed()
+{
+ setManualShutterSpeed(defaultShutterSpeed());
+}
+
+void SimulatorCameraSettings::setExposureCompensation(qreal ev)
+{
+ if (ev != mExposureCompensation && ev >= mSupportedExposureCompensations.first()
+ && ev <= mSupportedExposureCompensations.last()) {
+ mExposureCompensation = ev;
+ emit exposureCompensationChanged();
+ }
+}
+
+qreal SimulatorCameraSettings::exposureCompensation() const
+{
+ return mExposureCompensation;
+}
+
+QList<qreal> SimulatorCameraSettings::supportedExposureCompensationValues() const
+{
+ return mSupportedExposureCompensations;
+}
+
+void SimulatorCameraSettings::setAutoExposureCompensation()
+{
+ setExposureCompensation(defaultExposureCompensation());
+}
+
+int SimulatorCameraSettings::defaultIsoSensitivity() const
+{
+ return 400;
+}
+
+qreal SimulatorCameraSettings::defaultAperture() const
+{
+ return 4;
+}
+
+qreal SimulatorCameraSettings::defaultShutterSpeed() const
+{
+ return 0.008;
+}
+
+qreal SimulatorCameraSettings::defaultExposureCompensation() const
+{
+ return 0;
+}
+
+// End of file
diff --git a/src/plugins/simulator/camera/simulatorcamerasettings.h b/src/plugins/simulator/camera/simulatorcamerasettings.h
new file mode 100644
index 000000000..173a11549
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorcamerasettings.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** 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 SIMULATORCAMERASETTINGS_H
+#define SIMULATORCAMERASETTINGS_H
+
+#include "qcamera.h"
+
+QT_BEGIN_NAMESPACE
+
+class SimulatorCameraSettings : public QObject
+{
+ Q_OBJECT
+
+public:
+ SimulatorCameraSettings(QObject *parent);
+ ~SimulatorCameraSettings();
+
+ // ISO Sensitivity
+ int isoSensitivity() const;
+ int defaultIsoSensitivity() const;
+ void setManualIsoSensitivity(int iso);
+ void setAutoIsoSensitivity();
+ QList<int> supportedIsoSensitivities() const;
+
+ // Aperture
+ qreal aperture() const;
+ qreal defaultAperture() const;
+ void setManualAperture(qreal aperture);
+ void setAutoAperture();
+ QList<qreal> supportedApertures() const;
+
+ // Shutter Speed
+ qreal shutterSpeed() const;
+ qreal defaultShutterSpeed() const;
+ void setManualShutterSpeed(qreal speed);
+ void setAutoShutterSpeed();
+ QList<qreal> supportedShutterSpeeds() const;
+
+ // ExposureCompensation
+ qreal exposureCompensation() const;
+ qreal defaultExposureCompensation() const;
+ void setExposureCompensation(qreal ev);
+ void setAutoExposureCompensation();
+ QList<qreal> supportedExposureCompensationValues() const;
+
+Q_SIGNALS: // Notifications
+ // For QCameraExposureControl
+ void flashReady(bool ready);
+ void apertureChanged();
+ void apertureRangeChanged();
+ void shutterSpeedChanged();
+ void isoSensitivityChanged();
+ void exposureCompensationChanged();
+
+ // Errors
+ void error(int, const QString&);
+
+private: // Data
+ int mIsoSensitivity;
+ QList<int> mSupportedIsoSensitivities;
+ qreal mAperture;
+ QList<qreal> mSupportedApertures;
+ qreal mShutterSpeed;
+ QList<qreal> mSupportedShutterSpeeds;
+ qreal mExposureCompensation;
+ QList<qreal> mSupportedExposureCompensations;
+};
+
+QT_END_NAMESPACE
+
+#endif // SIMULATORCAMERASETTINGS_H
diff --git a/src/plugins/simulator/camera/simulatorvideoinputdevicecontrol.cpp b/src/plugins/simulator/camera/simulatorvideoinputdevicecontrol.cpp
new file mode 100644
index 000000000..154777392
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorvideoinputdevicecontrol.cpp
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** 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$
+** 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 "simulatorvideoinputdevicecontrol.h"
+
+#include <QtGui/QIcon>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <QtCore/QStringList>
+
+using namespace QTM_NAMESPACE;
+QSimulatorVideoInputDeviceControl::QSimulatorVideoInputDeviceControl(QObject *parent)
+ : QVideoDeviceControl(parent)
+ , mSelectedDevice(-1)
+{
+}
+
+QSimulatorVideoInputDeviceControl::~QSimulatorVideoInputDeviceControl()
+{
+}
+
+int QSimulatorVideoInputDeviceControl::deviceCount() const
+{
+ return mDevices.count();
+}
+
+QString QSimulatorVideoInputDeviceControl::deviceName(int index) const
+{
+ if (index >= mDevices.count() || index < 0)
+ return QString();
+ return mDevices.at(index);
+}
+
+QString QSimulatorVideoInputDeviceControl::deviceDescription(int index) const
+{
+ if (index >= mDevices.count() || index < 0)
+ return QString();
+
+ return mDescriptions[index];
+}
+
+QIcon QSimulatorVideoInputDeviceControl::deviceIcon(int index) const
+{
+ Q_UNUSED(index);
+ return QIcon();
+}
+
+int QSimulatorVideoInputDeviceControl::defaultDevice() const
+{
+ if (mDevices.isEmpty())
+ return -1;
+ return 0;
+}
+
+int QSimulatorVideoInputDeviceControl::selectedDevice() const
+{
+ return mSelectedDevice;
+}
+
+
+void QSimulatorVideoInputDeviceControl::setSelectedDevice(int index)
+{
+ if (index != mSelectedDevice) {
+ mSelectedDevice = index;
+ emit selectedDeviceChanged(index);
+ emit selectedDeviceChanged(deviceName(index));
+ }
+}
+
+void QSimulatorVideoInputDeviceControl::updateDeviceList(const QtMobility::QCameraData &data)
+{
+ mDevices.clear();
+ mDescriptions.clear();
+ QHashIterator<QString, QCameraData::QCameraDetails> iter(data.cameras);
+ while(iter.hasNext()) {
+ iter.next();
+ mDevices.append(iter.key());
+ mDescriptions.append(iter.value().description);
+ }
+ emit devicesChanged();
+}
+
+void QSimulatorVideoInputDeviceControl::addDevice(const QString &name, const QtMobility::QCameraData::QCameraDetails &details)
+{
+ if (mDevices.contains(name))
+ return;
+
+ mDevices.append(name);
+ mDescriptions.append(details.description);
+ emit devicesChanged();
+}
+
+void QSimulatorVideoInputDeviceControl::removeDevice(const QString &name)
+{
+ int index = mDevices.indexOf(name);
+ if (index == -1)
+ return;
+
+ mDevices.removeAt(index);
+ mDescriptions.removeAt(index);
+ if (index == mSelectedDevice)
+ setSelectedDevice(defaultDevice());
+ emit devicesChanged();
+}
+
+void QSimulatorVideoInputDeviceControl::changeDevice(const QString &name, const QtMobility::QCameraData::QCameraDetails &details)
+{
+ int index = mDevices.indexOf(name);
+ if (index == -1)
+ return;
+
+ if (mDescriptions.at(index) != details.description)
+ mDescriptions[index] = details.description;
+}
diff --git a/src/plugins/simulator/camera/simulatorvideoinputdevicecontrol.h b/src/plugins/simulator/camera/simulatorvideoinputdevicecontrol.h
new file mode 100644
index 000000000..cd5b7d04e
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorvideoinputdevicecontrol.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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$
+** 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 QSIMULATORVIDEOINPUTDEVICECONTROL_H
+#define QSIMULATORVIDEOINPUTDEVICECONTROL_H
+
+#include <qvideodevicecontrol.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qhash.h>
+
+#include "../qsimulatormultimediaconnection_p.h"
+
+QT_USE_NAMESPACE
+
+class QSimulatorVideoInputDeviceControl : public QVideoDeviceControl
+{
+Q_OBJECT
+public:
+ QSimulatorVideoInputDeviceControl(QObject *parent);
+ ~QSimulatorVideoInputDeviceControl();
+
+ int deviceCount() const;
+
+ QString deviceName(int index) const;
+ QString deviceDescription(int index) const;
+ QIcon deviceIcon(int index) const;
+
+ int defaultDevice() const;
+ int selectedDevice() const;
+
+ void updateDeviceList(const QtMobility::QCameraData &data);
+
+public Q_SLOTS:
+ void setSelectedDevice(int index);
+ void addDevice(const QString &name, const QtMobility::QCameraData::QCameraDetails &details);
+ void removeDevice(const QString &name);
+ void changeDevice(const QString &name, const QtMobility::QCameraData::QCameraDetails &details);
+
+private:
+ int mSelectedDevice;
+ QList<QString> mDevices;
+ QList<QString> mDescriptions;
+};
+
+#endif // QSIMULATORVIDEOINPUTDEVICECONTROL_H
diff --git a/src/plugins/simulator/camera/simulatorvideorenderercontrol.cpp b/src/plugins/simulator/camera/simulatorvideorenderercontrol.cpp
new file mode 100644
index 000000000..65cf38334
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorvideorenderercontrol.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** 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$
+** 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 "simulatorvideorenderercontrol.h"
+#include "simulatorcamerasettings.h"
+#include "simulatorcamerasession.h"
+#include <qabstractvideosurface.h>
+#include <qvideoframe.h>
+#include <qvideosurfaceformat.h>
+#include <QFile>
+#include <QColor>
+#include <QPainter>
+
+SimulatorVideoRendererControl::SimulatorVideoRendererControl(SimulatorCameraSession *session, QObject *parent) :
+ QVideoRendererControl(parent)
+ , mSession(session)
+ , mSurface(0)
+ , mRunning(false)
+{
+}
+
+SimulatorVideoRendererControl::~SimulatorVideoRendererControl()
+{
+}
+
+QAbstractVideoSurface *SimulatorVideoRendererControl::surface() const
+{
+ return mSurface;
+}
+
+void SimulatorVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
+{
+ mSurface = surface;
+}
+
+void SimulatorVideoRendererControl::setImagePath(const QString &imagePath)
+{
+ if (QFile::exists(imagePath)) {
+ mImage = QImage(imagePath);
+ } else {
+ mImage = QImage(800, 600, QImage::Format_RGB32);
+ mImage.fill(qRgb(200, 50, 50));
+ QPainter painter(&mImage);
+ painter.drawText(0, 0, 800, 600, Qt::AlignCenter, imagePath);
+ }
+ if (mRunning)
+ showImage();
+}
+
+void SimulatorVideoRendererControl::showImage()
+{
+ if (!mSurface)
+ return;
+ stop();
+ mShownImage = mImage;
+ SimulatorCameraSettings *settings = mSession->settings();
+ qreal colorDiff = .0;
+ colorDiff += settings->aperture() - settings->defaultAperture();
+ colorDiff += (settings->shutterSpeed() - settings->defaultShutterSpeed()) * 400;
+ colorDiff += ((qreal)settings->isoSensitivity() - settings->defaultIsoSensitivity()) / 100;
+ colorDiff += settings->exposureCompensation();
+ int diffToApply = qAbs(colorDiff * 20);
+ QPainter painter(&mShownImage);
+ if (colorDiff < 0)
+ painter.fillRect(mShownImage.rect(), QColor(0, 0, 0, qMin(diffToApply, 255)));
+ else
+ painter.fillRect(mShownImage.rect(), QColor(255, 255, 255, qMin(diffToApply, 255)));
+ QVideoFrame::PixelFormat pixelFormat = QVideoFrame::pixelFormatFromImageFormat(mShownImage.format());
+ if (pixelFormat == QVideoFrame::Format_Invalid) {
+ mShownImage = mShownImage.convertToFormat(QImage::Format_RGB32);
+ pixelFormat = QVideoFrame::Format_RGB32;
+ }
+ QVideoSurfaceFormat format(mShownImage.size(), pixelFormat);
+ mSurface->start(format);
+ mSurface->present(mShownImage);
+ mRunning = true;
+}
+
+void SimulatorVideoRendererControl::stop()
+{
+ if (!mSurface)
+ return;
+
+ if (mSurface->isActive())
+ mSurface->stop();
+ mRunning = false;
+}
+
+const QImage * SimulatorVideoRendererControl::image() const
+{
+ return &mShownImage;
+}
diff --git a/src/plugins/simulator/camera/simulatorvideorenderercontrol.h b/src/plugins/simulator/camera/simulatorvideorenderercontrol.h
new file mode 100644
index 000000000..3085ad079
--- /dev/null
+++ b/src/plugins/simulator/camera/simulatorvideorenderercontrol.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** 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$
+** 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 QSIMULATORVIDEORENDERERCONTROL_H
+#define QSIMULATORVIDEORENDERERCONTROL_H
+
+#include <qvideorenderercontrol.h>
+#include <QtGui/QImage>
+
+
+class SimulatorCameraSession;
+/*
+ * Control for QGraphicsVideoItem. Viewfinder frames are streamed to a surface
+ * which is drawn to the display by the Qt Graphics Vide Framework.
+ */
+class SimulatorVideoRendererControl : public QVideoRendererControl
+{
+ Q_OBJECT
+
+public:
+ SimulatorVideoRendererControl(SimulatorCameraSession *session, QObject *parent = 0);
+ virtual ~SimulatorVideoRendererControl();
+
+ QAbstractVideoSurface *surface() const;
+ void setSurface(QAbstractVideoSurface *surface);
+
+ void setImagePath(const QString &imagePath);
+ const QImage *image() const;
+
+public slots:
+ void showImage();
+
+private slots:
+ void stop();
+
+private:
+ SimulatorCameraSession *mSession;
+ QAbstractVideoSurface *mSurface;
+ QImage mImage;
+ QImage mShownImage;
+ bool mRunning;
+};
+
+#endif // QSIMULATORVIDEORENDERERCONTROL_H
diff --git a/src/plugins/simulator/qsimulatormultimediaconnection.cpp b/src/plugins/simulator/qsimulatormultimediaconnection.cpp
new file mode 100644
index 000000000..ff9e0508e
--- /dev/null
+++ b/src/plugins/simulator/qsimulatormultimediaconnection.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "../qsimulatormultimediaconnection_p.h"
+#include "mobilitysimulatorglobal.h"
+#include <mobilityconnection_p.h>
+
+#include <private/qsimulatordata_p.h>
+
+#include <QtNetwork/QLocalSocket>
+
+QTM_BEGIN_NAMESPACE
+
+using namespace QtSimulatorPrivate;
+
+Q_GLOBAL_STATIC(QCameraData, qtCameraData)
+
+namespace Simulator
+{
+ MultimediaConnection::MultimediaConnection(MobilityConnection *mobilityCon)
+ : QObject(mobilityCon)
+ , mConnection(mobilityCon)
+ , mInitialDataReceived(false)
+ {
+ qt_registerCameraTypes();
+ mobilityCon->addMessageHandler(this);
+ }
+
+ void MultimediaConnection::getInitialData()
+ {
+ RemoteMetacall<void>::call(mConnection->sendSocket(), NoSync, "setRequestsCameras");
+
+ while (!mInitialDataReceived)
+ mConnection->receiveSocket()->waitForReadyRead(100);
+ }
+
+ void MultimediaConnection::initialCameraDataSent()
+ {
+ mInitialDataReceived = true;
+ }
+
+ void MultimediaConnection::setCameraData(const QCameraData &data)
+ {
+ *qtCameraData() = data;
+ emit cameraDataChanged(data);
+ }
+
+ void MultimediaConnection::addCamera(const QString &name, const QCameraData::QCameraDetails &details)
+ {
+ if (qtCameraData()->cameras.contains(name))
+ return;
+
+ qtCameraData()->cameras.insert(name, details);
+ emit cameraAdded(name, details);
+ }
+
+ void MultimediaConnection::removeCamera(const QString &name)
+ {
+ if (!qtCameraData()->cameras.contains(name))
+ return;
+
+ qtCameraData()->cameras.remove(name);
+ emit cameraRemoved(name);
+ }
+
+ void MultimediaConnection::changeCamera(const QString &name, const QCameraData::QCameraDetails &details)
+ {
+ if (!qtCameraData()->cameras.contains(name))
+ return;
+
+ qtCameraData()->cameras[name] = details;
+ emit cameraChanged(name, details);
+ }
+
+} // namespace
+
+QCameraData get_qtCameraData()
+{
+ return *qtCameraData();
+}
+
+#include "moc_qsimulatormultimediaconnection_p.cpp"
+
+QTM_END_NAMESPACE
diff --git a/src/plugins/simulator/qsimulatormultimediaconnection_p.h b/src/plugins/simulator/qsimulatormultimediaconnection_p.h
new file mode 100644
index 000000000..752c0bfcb
--- /dev/null
+++ b/src/plugins/simulator/qsimulatormultimediaconnection_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** 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$
+** 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 SIMULATORMULTIMEDIACONNECTION_H
+#define SIMULATORMULTIMEDIACONNECTION_H
+
+#include "qsimulatormultimediadata_p.h"
+
+QT_BEGIN_HEADER
+
+QTM_BEGIN_NAMESPACE
+
+namespace Simulator
+{
+ class MobilityConnection;
+
+ class MultimediaConnection : public QObject
+ {
+ Q_OBJECT
+ public:
+ MultimediaConnection (MobilityConnection *mobilityCon);
+ virtual ~MultimediaConnection () {}
+
+ void getInitialData();
+
+ private slots:
+ void setCameraData(const QtMobility::QCameraData &);
+ void addCamera(const QString &, const QtMobility::QCameraData::QCameraDetails &);
+ void removeCamera(const QString &);
+ void changeCamera(const QString &, const QtMobility::QCameraData::QCameraDetails &);
+ void initialCameraDataSent();
+
+ private:
+ MobilityConnection *mConnection;
+ bool mInitialDataReceived;
+
+ signals:
+ void cameraDataChanged(const QtMobility::QCameraData &data);
+ void cameraAdded(const QString &name, const QtMobility::QCameraData::QCameraDetails &details);
+ void cameraRemoved(const QString &name);
+ void cameraChanged(const QString &name, const QtMobility::QCameraData::QCameraDetails &details);
+ };
+} // end namespace Simulator
+
+QCameraData get_qtCameraData();
+
+QTM_END_NAMESPACE
+QT_END_HEADER
+
+#endif
+
diff --git a/src/plugins/simulator/qsimulatormultimediadata.cpp b/src/plugins/simulator/qsimulatormultimediadata.cpp
new file mode 100644
index 000000000..4985bf5d1
--- /dev/null
+++ b/src/plugins/simulator/qsimulatormultimediadata.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qsimulatormultimediadata_p.h"
+
+#include <QtCore/QDataStream>
+
+QTM_BEGIN_NAMESPACE
+
+void qt_registerCameraTypes()
+{
+ qRegisterMetaTypeStreamOperators<QCameraData::QCameraDetails>("QtMobility::QCameraData::QCameraDetails");
+ qRegisterMetaTypeStreamOperators<QCameraData>("QtMobility::QCameraData");
+}
+
+QDataStream &operator<<(QDataStream &out, const QCameraData &s)
+{
+ out << s.cameras;
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, QCameraData &s)
+{
+ in >> s.cameras;
+ return in;
+}
+
+QDataStream &operator<<(QDataStream &out, const QCameraData::QCameraDetails &s)
+{
+ out << s.description << s.imagePath;
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, QCameraData::QCameraDetails &s)
+{
+ in >> s.description >> s.imagePath;
+ return in;
+}
+
+QTM_END_NAMESPACE
diff --git a/src/plugins/simulator/qsimulatormultimediadata_p.h b/src/plugins/simulator/qsimulatormultimediadata_p.h
new file mode 100644
index 000000000..e0fcb046a
--- /dev/null
+++ b/src/plugins/simulator/qsimulatormultimediadata_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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$
+** 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 QSIMULATORMULTIMEDIADATA_P_H
+#define QSIMULATORMULTIMEDIADATA_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/QMetaType>
+#include <QtCore/QDateTime>
+#include <qcamera.h>
+
+QT_BEGIN_HEADER
+QTM_BEGIN_NAMESPACE
+
+struct QCameraData {
+ struct QCameraDetails {
+ QString description;
+ QString imagePath;
+ };
+ QHash<QString, QCameraDetails> cameras;
+};
+
+void qt_registerCameraTypes();
+
+QTM_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QtMobility::QCameraData)
+Q_DECLARE_METATYPE(QtMobility::QCameraData::QCameraDetails)
+
+QT_END_HEADER
+
+#endif // QMULTIMEDIADATA_SIMULATOR_P_H
diff --git a/src/plugins/simulator/qsimulatorserviceplugin.cpp b/src/plugins/simulator/qsimulatorserviceplugin.cpp
new file mode 100644
index 000000000..2039276ba
--- /dev/null
+++ b/src/plugins/simulator/qsimulatorserviceplugin.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qstring.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/QIcon>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+
+#include "qsimulatorserviceplugin.h"
+#include <mobilityconnection_p.h>
+
+#include "simulatorcameraservice.h"
+
+#include <qmediaserviceprovider.h>
+
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+QTM_USE_NAMESPACE
+
+Simulator::MultimediaConnection *QSimulatorServicePlugin::mMultimediaConnection = 0;
+
+QSimulatorServicePlugin::QSimulatorServicePlugin()
+{
+ ensureSimulatorConnection();
+}
+
+QStringList QSimulatorServicePlugin::keys() const
+{
+ QStringList retList;
+ retList << QLatin1String(Q_MEDIASERVICE_CAMERA);
+ return retList;
+}
+
+QMediaService* QSimulatorServicePlugin::create(const QString &key)
+{
+ if (key == QLatin1String(Q_MEDIASERVICE_CAMERA))
+ return new SimulatorCameraService(key, mMultimediaConnection);
+
+ qWarning() << "Simulator service plugin: unsupported key:" << key;
+ return 0;
+}
+
+void QSimulatorServicePlugin::release(QMediaService *service)
+{
+ delete service;
+}
+
+QList<QByteArray> QSimulatorServicePlugin::devices(const QByteArray &service) const
+{
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ QCameraData cams = get_qtCameraData();
+ QList<QByteArray> returnList;
+ foreach(const QString &key, cams.cameras.keys())
+ returnList.append(key.toAscii());
+ return returnList;
+ }
+
+ return QList<QByteArray>();
+}
+
+QString QSimulatorServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
+{
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ QCameraData cams = get_qtCameraData();
+ return cams.cameras.value(device).description;
+ }
+
+ return QString();
+}
+
+void QSimulatorServicePlugin::ensureSimulatorConnection()
+{
+ using namespace QtMobility::Simulator;
+
+ static bool connected = false;
+ if (connected)
+ return;
+
+ connected = true;
+ MobilityConnection *connection = MobilityConnection::instance();
+ mMultimediaConnection = new MultimediaConnection(connection);
+ mMultimediaConnection->getInitialData();
+}
+
+Q_EXPORT_PLUGIN2(qtmedia_simulatorengine, QSimulatorServicePlugin);
diff --git a/src/plugins/simulator/qsimulatorserviceplugin.h b/src/plugins/simulator/qsimulatorserviceplugin.h
new file mode 100644
index 000000000..02e4d6321
--- /dev/null
+++ b/src/plugins/simulator/qsimulatorserviceplugin.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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$
+** 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 QSIMULATORSERVICEPLUGIN_H
+#define QSIMULATORSERVICEPLUGIN_H
+
+#include <qmediaserviceproviderplugin.h>
+#include "qsimulatormultimediaconnection_p.h"
+
+QT_USE_NAMESPACE
+
+class QSimulatorServicePlugin : public QMediaServiceProviderPlugin, public QMediaServiceSupportedDevicesInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
+public:
+ QSimulatorServicePlugin();
+
+ // QMediaServiceProviderPlugin
+ QStringList keys() const;
+ QMediaService* create(QString const& key);
+ void release(QMediaService *service);
+
+ // QMediaServiceSupportedDevicesInterface
+ QList<QByteArray> devices(const QByteArray &service) const;
+ QString deviceDescription(const QByteArray &service, const QByteArray &device);
+
+private:
+ static void ensureSimulatorConnection();
+ static QTM_PREPEND_NAMESPACE(Simulator::MultimediaConnection) *mMultimediaConnection;
+
+signals:
+ void cameraDataChanged();
+};
+
+#endif // QSIMULATORSERVICEPLUGIN_H
diff --git a/src/plugins/simulator/simulator.pro b/src/plugins/simulator/simulator.pro
new file mode 100644
index 000000000..81117ca82
--- /dev/null
+++ b/src/plugins/simulator/simulator.pro
@@ -0,0 +1,28 @@
+TEMPLATE = lib
+CONFIG += plugin
+TARGET = $$qtLibraryTarget(qsimulatorengine)
+PLUGIN_TYPE=mediaservice
+
+include(../../../common.pri)
+INCLUDEPATH+=$${SOURCE_DIR}/src/multimedia \
+ $${SOURCE_DIR}/src/multimedia/video \
+ $${SOURCE_DIR}/src/multimedia/audio \
+ $${SOURCE_DIR}/src/mobilitysimulator
+
+CONFIG += mobility
+MOBILITY = multimedia
+
+DEPENDPATH += .
+
+# Input
+HEADERS += \
+ qsimulatormultimediaconnection_p.h \
+ qsimulatormultimediadata_p.h \
+ qsimulatorserviceplugin.h
+
+SOURCES += \
+ qsimulatormultimediaconnection.cpp \
+ qsimulatormultimediadata.cpp \
+ qsimulatorserviceplugin.cpp \
+
+include(camera/simulatorcamera.pri)
diff --git a/src/plugins/symbian/ecam/camera_s60.pri b/src/plugins/symbian/ecam/camera_s60.pri
new file mode 100644
index 000000000..beb44db8d
--- /dev/null
+++ b/src/plugins/symbian/ecam/camera_s60.pri
@@ -0,0 +1,157 @@
+INCLUDEPATH += $$PWD
+
+include (../videooutput/videooutput.pri)
+
+# Camera Service
+DEFINES += QMEDIA_SYMBIAN_CAMERA
+
+# S60 3.1 platform
+contains(S60_VERSION, 3.1) {
+ DEFINES += S60_31_PLATFORM
+ DEFINES *= S60_3X_PLATFORM
+}
+
+# S60 3.2 platform
+contains(S60_VERSION, 3.2) {
+ DEFINES += S60_32_PLATFORM
+ DEFINES *= S60_3X_PLATFORM
+}
+
+# S60 5.0 platform
+!contains(DEFINES, S60_31_PLATFORM) {
+ !contains(DEFINES, S60_32_PLATFORM) {
+ !contains(DEFINES, SYMBIAN_3_PLATFORM) {
+ DEFINES += S60_50_PLATFORM
+ }
+ }
+}
+
+# Symbian 3 platform
+contains(DEFINES, VIDEOOUTPUT_GRAPHICS_SURFACES) {
+ DEFINES += SYMBIAN_3_PLATFORM
+}
+
+# AutoFocusing (CamAutoFocus) from ForumNokia example
+contains(symbian_camera_camautofocus_enabled, yes) {
+ exists($${EPOCROOT}epoc32\\include\\CCamAutoFocus.h) {
+ message ("CameraBE: Using S60 3.1 autofocusing")
+ MMP_RULES += \
+ "$${LITERAL_HASH}ifdef WINSCW" \
+ "LIBRARY camautofocus.lib" \
+ "$${LITERAL_HASH}else" \
+ "STATICLIBRARY camautofocus_s.lib" \
+ "$${LITERAL_HASH}endif // WINS" \
+ "MACRO S60_CAM_AUTOFOCUS_SUPPORT"
+ }
+}
+
+# ECam AdvancedSettings
+contains(symbian_camera_ecamadvsettings_enabled, yes) {
+ exists($${EPOCROOT}epoc32\\include\\ecamadvancedsettings.h) {
+ MMP_RULES += \
+ "$${LITERAL_HASH}ifndef WINSCW" \
+ "LIBRARY ecamadvsettings.lib" \
+ "MACRO USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER" \
+ "$${LITERAL_HASH}endif"
+ message("CameraBE: Using from S60 3.2 CCameraAdvancedSettings header")
+ }
+ exists($${EPOCROOT}epoc32\\include\\ecamadvsettings.h) {
+ symbian:LIBS += -lecamadvsettings
+ DEFINES += USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER
+ message("CameraBE: Using CCameraAdvancedSettings header from S60 5.0 or later")
+ }
+}
+
+# DevVideo API Check (Requires both, DevVideoPlay and DevVideoRecord plugins):
+# DevVideoConstants has been problematic since not being included in SDK plugins
+# For S60 5.0 this has changed with plugin extension 1.1
+# But for S60 3.2 this is still a problem
+contains(symbian_camera_devvideorecord_enabled, yes) {
+ exists($${EPOCROOT}epoc32\\include\\mmf\\devvideo\\devvideorecord.h) {
+ exists($${EPOCROOT}epoc32\\include\\mmf\\devvideo\\devvideobase.h) {
+ exists($${EPOCROOT}epoc32\\include\\mmf\\devvideo\\devvideoconstants.h) {
+ symbian:LIBS += -ldevvideo
+ DEFINES += S60_DEVVIDEO_RECORDING_SUPPORTED
+ message("CameraBE: Devvideo API supported")
+ }
+ }
+ }
+}
+
+# ECam Snapshot API:
+contains(symbian_camera_snapshot_enabled, yes) {
+ exists($${EPOCROOT}epoc32\\include\\platform\\ecam\\camerasnapshot.h) {
+ DEFINES += ECAM_PREVIEW_API
+ message("CameraBE: Using CCameraSnapshot API")
+ symbian:LIBS += -lecamsnapshot
+ } else {
+ message("CameraBE: Using custom snapshot proving methods")
+ }
+} else {
+ message("CameraBE: Using custom snapshot proving methods")
+}
+
+# Libraries:
+symbian:LIBS += -lfbscli \
+ -lmediaclientvideo \
+ -lecam \
+ -lbafl \
+ -lPlatformEnv \
+ -lcharconv \
+ -lconvnames \
+ -lgb2312_shared \
+ -ljisx0201 \
+ -ljisx0208 \
+ -lmmfcontrollerframework \
+ -lfbscli \
+ -lefsrv \
+ -lcone \
+ -lws32 \
+ -limageconversion
+
+# Source:
+HEADERS += $$PWD/s60cameraconstants.h \
+ $$PWD/s60cameralockscontrol.h \
+ $$PWD/s60camerafocuscontrol.h \
+ $$PWD/s60cameraexposurecontrol.h \
+ $$PWD/s60cameraflashcontrol.h \
+ $$PWD/s60cameracontrol.h \
+ $$PWD/s60mediarecordercontrol.h \
+ $$PWD/s60videocapturesession.h \
+ $$PWD/s60imagecapturesession.h \
+ $$PWD/s60mediacontainercontrol.h \
+ $$PWD/s60videoencodercontrol.h \
+ $$PWD/s60audioencodercontrol.h \
+ $$PWD/s60cameraservice.h \
+ $$PWD/s60cameraimageprocessingcontrol.h \
+ $$PWD/s60cameraimagecapturecontrol.h \
+ $$PWD/s60videodevicecontrol.h \
+ $$PWD/s60imageencodercontrol.h \
+ $$PWD/s60camerasettings.h \
+ $$PWD/s60cameraengine.h \
+ $$PWD/s60cameraviewfinderengine.h \
+ $$PWD/s60cameraengineobserver.h \
+ $$PWD/s60videorenderercontrol.h
+
+SOURCES += $$PWD/s60cameralockscontrol.cpp \
+ $$PWD/s60camerafocuscontrol.cpp \
+ $$PWD/s60cameraexposurecontrol.cpp \
+ $$PWD/s60cameraflashcontrol.cpp \
+ $$PWD/s60cameracontrol.cpp \
+ $$PWD/s60mediarecordercontrol.cpp \
+ $$PWD/s60videocapturesession.cpp \
+ $$PWD/s60imagecapturesession.cpp \
+ $$PWD/s60mediacontainercontrol.cpp \
+ $$PWD/s60videoencodercontrol.cpp \
+ $$PWD/s60audioencodercontrol.cpp \
+ $$PWD/s60cameraservice.cpp \
+ $$PWD/s60cameraimageprocessingcontrol.cpp \
+ $$PWD/s60cameraimagecapturecontrol.cpp \
+ $$PWD/s60videodevicecontrol.cpp \
+ $$PWD/s60imageencodercontrol.cpp \
+ $$PWD/s60camerasettings.cpp \
+ $$PWD/s60cameraengine.cpp \
+ $$PWD/s60cameraviewfinderengine.cpp \
+ $$PWD/s60videorenderercontrol.cpp
+
+# End of file
diff --git a/src/plugins/symbian/ecam/ecam.pro b/src/plugins/symbian/ecam/ecam.pro
new file mode 100644
index 000000000..31f30b61c
--- /dev/null
+++ b/src/plugins/symbian/ecam/ecam.pro
@@ -0,0 +1,40 @@
+######################################################################
+#
+# Mobility API project - Symbian Camera backend
+#
+######################################################################
+
+TEMPLATE = lib
+CONFIG += plugin
+
+TARGET = $$qtLibraryTarget(qtmultimediakit_ecamengine)
+PLUGIN_TYPE = mediaservice
+include (../../../../common.pri)
+
+CONFIG += mobility
+MOBILITY += multimedia
+
+# Include here so that all defines are added here also
+include(camera_s60.pri)
+
+DEPENDPATH += .
+
+INCLUDEPATH += . \
+ $${SOURCE_DIR}/include \
+ $${SOURCE_DIR}/src/multimedia \
+ $${SOURCE_DIR}/src/multimedia/audio \
+ $${SOURCE_DIR}/src/multimedia/video \
+ $${SOURCE_DIR}
+
+HEADERS += s60cameraserviceplugin.h
+SOURCES += s60cameraserviceplugin.cpp
+
+load(data_caging_paths)
+TARGET.EPOCALLOWDLLDATA = 1
+TARGET.UID3 = 0x2002BFC2
+TARGET.CAPABILITY = ALL -TCB
+
+# Make a sis package from plugin + api + stub (plugin)
+pluginDep.sources = $${TARGET}.dll
+pluginDep.path = $${QT_PLUGINS_BASE_DIR}/$${PLUGIN_TYPE}
+DEPLOYMENT += pluginDep
diff --git a/src/plugins/symbian/ecam/s60audioencodercontrol.cpp b/src/plugins/symbian/ecam/s60audioencodercontrol.cpp
new file mode 100644
index 000000000..bd8f0147d
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60audioencodercontrol.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** 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 "s60audioencodercontrol.h"
+#include "s60videocapturesession.h"
+
+S60AudioEncoderControl::S60AudioEncoderControl(QObject *parent) :
+ QAudioEncoderControl(parent)
+{
+}
+
+S60AudioEncoderControl::S60AudioEncoderControl(S60VideoCaptureSession *session, QObject *parent) :
+ QAudioEncoderControl(parent)
+{
+ m_session = session;
+}
+
+S60AudioEncoderControl::~S60AudioEncoderControl()
+{
+}
+
+QStringList S60AudioEncoderControl::supportedAudioCodecs() const
+{
+ return m_session->supportedAudioCaptureCodecs();
+}
+
+QString S60AudioEncoderControl::codecDescription(const QString &codecName) const
+{
+ // According to ForumNokia MMF camcorder plugin supports AAC, AMR and QCELP
+ // QCELP is speech codec and can be discarded
+ if (qstrcmp(codecName.toLocal8Bit().constData(), "audio/aac") == 0)
+ return QLatin1String("Advanced Audio Coding");
+ else if (qstrcmp(codecName.toLocal8Bit().constData(), "audio/amr") == 0)
+ return QLatin1String("Adaptive Multi-Rate Audio Codec");
+
+ return QString();
+}
+
+QStringList S60AudioEncoderControl::supportedEncodingOptions(const QString &codec) const
+{
+ // Possible settings: EncodingMode, Codec, BitRate, ChannelCount, SampleRate, Quality
+ // Possible (codec specific) Options: None
+ Q_UNUSED(codec);
+ return QStringList();
+}
+
+QVariant S60AudioEncoderControl::encodingOption(const QString &codec, const QString &name) const
+{
+ // Possible settings: EncodingMode, Codec, BitRate, ChannelCount, SampleRate, Quality
+ // Possible (codec specific) Options: None
+ Q_UNUSED(codec);
+ Q_UNUSED(name);
+ return QVariant();
+}
+
+void S60AudioEncoderControl::setEncodingOption(
+ const QString &codec, const QString &name, const QVariant &value)
+{
+ m_session->setError(KErrNotSupported, tr("Audio encoding option is not supported"));
+
+ // The audio settings can currently be set only using setAudioSettings() function
+ Q_UNUSED(value)
+ Q_UNUSED(codec)
+ Q_UNUSED(name)
+}
+
+QList<int> S60AudioEncoderControl::supportedSampleRates(
+ const QAudioEncoderSettings &settings, bool *continuous) const
+{
+ return m_session->supportedSampleRates(settings, continuous);
+}
+
+QAudioEncoderSettings S60AudioEncoderControl::audioSettings() const
+{
+ QAudioEncoderSettings settings;
+ m_session->audioEncoderSettings(settings);
+
+ return settings;
+}
+
+void S60AudioEncoderControl::setAudioSettings(const QAudioEncoderSettings &settings)
+{
+ // Notify that settings have been implicitly set and there's no need to
+ // initialize them in case camera is changed
+ m_session->notifySettingsSet();
+
+ // Quality defines SampleRate/BitRate combination if either or both are missing
+ if (settings.codec().isEmpty()) { // Empty settings
+ m_session->setAudioCaptureQuality(settings.quality(), S60VideoCaptureSession::EOnlyAudioQuality);
+
+ } else if (settings.bitRate() == -1 && settings.sampleRate() != -1) { // Only SampleRate set
+ m_session->setAudioCaptureCodec(settings.codec());
+ m_session->setAudioChannelCount(settings.channelCount());
+ m_session->setAudioSampleRate(settings.sampleRate());
+ m_session->setAudioEncodingMode(settings.encodingMode());
+ m_session->setAudioCaptureQuality(settings.quality(), S60VideoCaptureSession::EAudioQualityAndSampleRate);
+
+ } else if (settings.bitRate() != -1 && settings.sampleRate() == -1) { // Only BitRate set
+ m_session->setAudioCaptureCodec(settings.codec());
+ m_session->setAudioChannelCount(settings.channelCount());
+ m_session->setAudioBitRate(settings.bitRate());
+ m_session->setAudioEncodingMode(settings.encodingMode());
+ m_session->setAudioCaptureQuality(settings.quality(), S60VideoCaptureSession::EAudioQualityAndBitRate);
+
+ } else if (settings.bitRate() == -1 && settings.sampleRate() == -1) { // No BitRate or SampleRate set
+ m_session->setAudioCaptureCodec(settings.codec());
+ m_session->setAudioChannelCount(settings.channelCount());
+ m_session->setAudioEncodingMode(settings.encodingMode());
+ m_session->setAudioCaptureQuality(settings.quality(), S60VideoCaptureSession::EOnlyAudioQuality);
+
+ } else { // Both SampleRate and BitRate set
+ m_session->setAudioCaptureCodec(settings.codec());
+ m_session->setAudioChannelCount(settings.channelCount());
+ m_session->setAudioSampleRate(settings.sampleRate());
+ m_session->setAudioBitRate(settings.bitRate());
+ m_session->setAudioEncodingMode(settings.encodingMode());
+ m_session->setAudioCaptureQuality(settings.quality(), S60VideoCaptureSession::ENoAudioQuality);
+ }
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60audioencodercontrol.h b/src/plugins/symbian/ecam/s60audioencodercontrol.h
new file mode 100644
index 000000000..db6ada5d1
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60audioencodercontrol.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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 S60AUDIOENCODERCONTROL_H
+#define S60AUDIOENCODERCONTROL_H
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+
+#include <qaudioencodercontrol.h>
+
+QT_USE_NAMESPACE
+
+class S60VideoCaptureSession;
+
+/*
+ * Control for audio settings when recording video using QMediaRecorder.
+ */
+class S60AudioEncoderControl : public QAudioEncoderControl
+{
+ Q_OBJECT
+
+public: // Constructor & Destructor
+
+ S60AudioEncoderControl(QObject *parent = 0);
+ S60AudioEncoderControl(S60VideoCaptureSession *session, QObject *parent = 0);
+ virtual ~S60AudioEncoderControl();
+
+public: // QAudioEncoderControl
+
+ // Audio Codec
+ QStringList supportedAudioCodecs() const;
+ QString codecDescription(const QString &codecName) const;
+
+ // Sample Rate
+ QList<int> supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous = 0) const;
+
+ // Audio Settings
+ QAudioEncoderSettings audioSettings() const;
+ void setAudioSettings(const QAudioEncoderSettings &settings);
+
+ // Encoding Option
+ QStringList supportedEncodingOptions(const QString &codec) const;
+ QVariant encodingOption(const QString &codec, const QString &name) const;
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
+
+private: // Data
+
+ S60VideoCaptureSession* m_session;
+};
+
+#endif // S60AUDIOENCODERCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameraconstants.h b/src/plugins/symbian/ecam/s60cameraconstants.h
new file mode 100644
index 000000000..4b415c3e8
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraconstants.h
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** 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 S60CAMERACONSTANTS_H
+#define S60CAMERACONSTANTS_H
+
+//=============================================================================
+
+// GENERAL SETTINGS
+
+#define KDefaultCameraDevice 0
+#define KECamCameraPriority 0
+#define KInactivityTimerTimeout 30000 // msec
+#define KSymbianFineResolutionFactor 100.0
+#define KDefaultOpticalZoom 1.0
+#define KDefaultDigitalZoom 1.0
+#define KSmoothZoomStep 1
+#define KDefaultFocusMode QCameraFocus::AutoFocus
+
+#define KDefaultViewfinderSize QSize(320,240)
+#define KDefaultSizePreview_Normal TSize(640,480)
+#define KDefaultSizePreview_Wide TSize(640,360)
+#define KDefaultSizePreview_CIF TSize(352,288)
+#define KDefaultSizePreview_PAL TSize(640,512)
+#define KDefaultSizePreview_NTSC TSize(640,426)
+#define KDefaultFormatPreview CCamera::EFormatFbsBitmapColor16MU
+#define KViewfinderFrameRate 30
+#define KMaxVFErrorsSignalled 3
+
+//=============================================================================
+
+// IMAGE SETTINGS
+
+#define KDefaultImagePath QLatin1String("c:\\Data\\Images")
+#define KDefaultImageFileName QLatin1String("image.jpg")
+#define KDefaultImageCodec QLatin1String("image/jpeg")
+#define KDefaultImageFormatPrimaryCam CCamera::EFormatExif
+#ifdef SYMBIAN_3_PLATFORM
+#define KDefaultImageFormatSecondaryCam CCamera::EFormatExif
+#define KDefaultImageResolution QSize(3264, 2448)
+#else // Pre-Symbian3 Platforms
+#define KDefaultImageFormatSecondaryCam CCamera::EFormatFbsBitmapColor64K
+#define KDefaultImageResolution QSize(2048, 1536)
+#endif // SYMBIAN_3_PLATFORM
+#define KSymbianImageQualityCoefficient 25
+// This must be divisible by 4 and creater or equal to 8
+#define KSnapshotDownScaleFactor 8
+#define KSnapshotMinWidth 640
+#define KSnapshotMinHeight 360
+#define KJpegQualityVeryLow 40
+#define KJpegQualityLow 50
+#define KJpegQualityNormal 75
+#define KJpegQualityHigh 85
+#define KJpegQualityVeryHigh 95
+#define KDefaultImageQuality KJpegQualityHigh
+
+//=============================================================================
+
+// VIDEO SETTINGS
+
+// ================
+// General settings
+// ================
+
+// Dummy file name to execute CVideoRecorderUtility::OpenFileL() without
+// knowing the actual outputLocation. This is needed to be able to query/set
+// supported video settings.
+_LIT(KDummyVideoFile, "c:\\data\\temp");
+
+// Default container MIME type
+#define KMimeTypeDefaultContainer QLatin1String("video/mp4")
+#define KDefaultVideoPath QLatin1String("c:\\Data\\Videos")
+#define KDefaultVideoFileName QLatin1String("video.mp4")
+#define KDurationChangedInterval 1000 // 1 second
+
+// ==============
+// Audio Settings
+// ==============
+
+// Default audio codec MIME type
+#define KMimeTypeDefaultAudioCodec QLatin1String("audio/aac")
+
+// Default audio settings for video recording
+#define KDefaultChannelCount -1 // Not Supported on Symbian
+#define KDefaultBitRate 32000 // 32kbps
+#define KDefaultSampleRate -1 // Not Supported on Symbian
+
+// ==============
+// Video Settings
+// ==============
+
+// Default video codec MIME type
+#ifdef SYMBIAN_3_PLATFORM
+ // H.264: BaselineProfile Level 3.1, Max resolution: 1280x720
+ #define KMimeTypeDefaultVideoCodec QLatin1String("video/H264; profile-level-id=42801F")
+#else
+ // MPEG-4: Simple Profile, Level 4, Max resolution: 640x480
+ #define KMimeTypeDefaultVideoCodec QLatin1String("video/mp4v-es; profile-level-id=4")
+#endif
+
+// Maximum resolutions for encoder MIME Types
+// H.263
+#define KResH263 QSize(176,144);
+#define KResH263_Profile0 QSize(176,144);
+#define KResH263_Profile0_Level10 QSize(176,144);
+#define KResH263_Profile0_Level20 QSize(352,288);
+#define KResH263_Profile0_Level30 QSize(352,288);
+#define KResH263_Profile0_Level40 QSize(352,288);
+#define KResH263_Profile0_Level45 QSize(176,144);
+#define KResH263_Profile0_Level50 QSize(352,288);
+#define KResH263_Profile3 QSize(176,144);
+// MPEG-4
+#define KResMPEG4 QSize(176,144);
+#define KResMPEG4_PLID_1 QSize(176,144);
+#define KResMPEG4_PLID_2 QSize(352,288);
+#define KResMPEG4_PLID_3 QSize(352,288);
+#define KResMPEG4_PLID_4 QSize(640,480);
+#define KResMPEG4_PLID_5 QSize(720,576);
+#define KResMPEG4_PLID_6 QSize(1280,720);
+#define KResMPEG4_PLID_8 QSize(176,144);
+#define KResMPEG4_PLID_9 QSize(176,144);
+// H.264 (Baseline Profile, same resolutions apply to Main and High Profile)
+#define KResH264 QSize(176,144);
+#define KResH264_PLID_42800A QSize(176,144);
+#define KResH264_PLID_42900B QSize(176,144);
+#define KResH264_PLID_42800B QSize(352,288);
+#define KResH264_PLID_42800C QSize(352,288);
+#define KResH264_PLID_42800D QSize(352,288);
+#define KResH264_PLID_428014 QSize(352,288);
+#define KResH264_PLID_428015 QSize(352,288);
+#define KResH264_PLID_428016 QSize(640,480);
+#define KResH264_PLID_42801E QSize(640,480);
+#define KResH264_PLID_42801F QSize(1280,720);
+#define KResH264_PLID_428020 QSize(1280,720);
+#define KResH264_PLID_428028 QSize(1920,1080);
+
+// Maximum framerates for encoder MIME Types
+// H.263
+#define KFrR_H263 qreal(15);
+#define KFrR_H263_Profile0 qreal(15);
+#define KFrR_H263_Profile0_Level10 qreal(15);
+#define KFrR_H263_Profile0_Level20 qreal(15);
+#define KFrR_H263_Profile0_Level30 qreal(30);
+#define KFrR_H263_Profile0_Level40 qreal(30);
+#define KFrR_H263_Profile0_Level45 qreal(15);
+#define KFrR_H263_Profile0_Level50 qreal(15);
+#define KFrR_H263_Profile3 qreal(15);
+// MPEG-4
+#define KFrR_MPEG4 qreal(15);
+#define KFrR_MPEG4_PLID_1 qreal(15);
+#define KFrR_MPEG4_PLID_2 qreal(15);
+#define KFrR_MPEG4_PLID_3 qreal(30);
+// This is a workaround for a known platform bug
+#if (defined(S60_31_PLATFORM) | defined(S60_32_PLATFORM))
+#define KFrR_MPEG4_PLID_4 qreal(15);
+#else // All other platforms
+#define KFrR_MPEG4_PLID_4 qreal(30);
+#endif // S60 3.1 or 3.2
+#define KFrR_MPEG4_PLID_5 qreal(30);
+#define KFrR_MPEG4_PLID_6 qreal(30);
+#define KFrR_MPEG4_PLID_8 qreal(15);
+#define KFrR_MPEG4_PLID_9 qreal(15);
+// H.264 (Baseline Profile, same framerates apply to Main and High Profile)
+#define KFrR_H264 qreal(15);
+#define KFrR_H264_PLID_42800A qreal(15);
+#define KFrR_H264_PLID_42900B qreal(15);
+#define KFrR_H264_PLID_42800B qreal(7.5);
+#define KFrR_H264_PLID_42800C qreal(15);
+#define KFrR_H264_PLID_42800D qreal(30);
+#define KFrR_H264_PLID_428014 qreal(30);
+#define KFrR_H264_PLID_428015 qreal(50);
+#define KFrR_H264_PLID_428016 qreal(16.9);
+#define KFrR_H264_PLID_42801E qreal(33.8);
+#define KFrR_H264_PLID_42801F qreal(30);
+#define KFrR_H264_PLID_428020 qreal(60);
+#define KFrR_H264_PLID_428028 qreal(30);
+
+// Maximum bitrates for encoder MIME Types
+// H.263
+#define KBiR_H263 int(64000);
+#define KBiR_H263_Profile0 int(64000);
+#define KBiR_H263_Profile0_Level10 int(64000);
+#define KBiR_H263_Profile0_Level20 int(128000);
+#define KBiR_H263_Profile0_Level30 int(384000);
+#define KBiR_H263_Profile0_Level40 int(2048000);
+#define KBiR_H263_Profile0_Level45 int(128000);
+#define KBiR_H263_Profile0_Level50 int(4096000);
+#define KBiR_H263_Profile3 int(64000);
+// MPEG-4
+#define KBiR_MPEG4 int(64000);
+#define KBiR_MPEG4_PLID_1 int(64000);
+#define KBiR_MPEG4_PLID_2 int(128000);
+#define KBiR_MPEG4_PLID_3 int(384000);
+// This is a workaround for a known platform bug
+#if (defined(S60_31_PLATFORM) | defined(S60_32_PLATFORM))
+#define KBiR_MPEG4_PLID_4 int(2000000);
+#else // All other platforms
+#define KBiR_MPEG4_PLID_4 int(4000000);
+#endif // S60 3.1 or 3.2
+#define KBiR_MPEG4_PLID_5 int(8000000);
+#define KBiR_MPEG4_PLID_6 int(12000000);
+#define KBiR_MPEG4_PLID_8 int(64000);
+#define KBiR_MPEG4_PLID_9 int(128000);
+// H.264 (Baseline Profile, same bitrates apply to Main and High Profile)
+#define KBiR_H264 int(64000);
+#define KBiR_H264_PLID_42800A int(64000);
+#define KBiR_H264_PLID_42900B int(128000);
+#define KBiR_H264_PLID_42800B int(192000);
+#define KBiR_H264_PLID_42800C int(384000);
+#define KBiR_H264_PLID_42800D int(768000);
+#define KBiR_H264_PLID_428014 int(2000000);
+#define KBiR_H264_PLID_428015 int(4000000);
+#define KBiR_H264_PLID_428016 int(4000000);
+#define KBiR_H264_PLID_42801E int(10000000);
+#define KBiR_H264_PLID_42801F int(14000000);
+#define KBiR_H264_PLID_428020 int(20000000);
+#define KBiR_H264_PLID_428028 int(20000000);
+
+#endif // S60CAMERACONSTANTS_H
diff --git a/src/plugins/symbian/ecam/s60cameracontrol.cpp b/src/plugins/symbian/ecam/s60cameracontrol.cpp
new file mode 100644
index 000000000..64a3ff37e
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameracontrol.cpp
@@ -0,0 +1,983 @@
+/****************************************************************************
+**
+** 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 <QtCore/qstring.h>
+#include <QTimer>
+
+#include "s60cameraservice.h"
+#include "s60cameraengine.h"
+#include "s60cameracontrol.h"
+#include "s60imagecapturesession.h"
+#include "s60videowidgetcontrol.h"
+#include "s60cameraviewfinderengine.h"
+#include "s60cameraconstants.h"
+
+S60CameraControl::S60CameraControl(QObject *parent) :
+ QCameraControl(parent)
+{
+}
+
+S60CameraControl::S60CameraControl(S60VideoCaptureSession *videosession,
+ S60ImageCaptureSession *imagesession,
+ QObject *parent):
+ QCameraControl(parent),
+ m_cameraEngine(0),
+ m_viewfinderEngine(0),
+ m_imageSession(0),
+ m_videoSession(0),
+ m_advancedSettings(0),
+ m_videoOutput(0),
+ m_inactivityTimer(0),
+ m_captureMode(QCamera::CaptureStillImage), // Default CaptureMode
+ m_requestedCaptureMode(QCamera::CaptureStillImage),
+ m_settingCaptureModeInternally(false),
+ m_internalState(QCamera::UnloadedStatus), // Default Status
+ m_requestedState(QCamera::UnloadedState), // Default State
+ m_deviceIndex(KDefaultCameraDevice),
+ m_error(KErrNone),
+ m_changeCaptureModeWhenReady(false),
+ m_rotateCameraWhenReady(false),
+ m_videoCaptureState(S60VideoCaptureSession::ENotInitialized)
+{
+ m_videoSession = videosession;
+ m_imageSession = imagesession;
+
+ m_inactivityTimer = new QTimer;
+ if (m_inactivityTimer)
+ m_inactivityTimer->setSingleShot(true);
+
+ TRAPD(err, m_cameraEngine = CCameraEngine::NewL(m_deviceIndex, KECamCameraPriority, this));
+ if (err) {
+ m_error = err;
+ if (err == KErrPermissionDenied)
+ qWarning("Failed to create camera. Possibly missing capabilities.");
+ else
+ qWarning("Failed to create camera.");
+ return;
+ }
+
+ m_viewfinderEngine = new S60CameraViewfinderEngine(this, m_cameraEngine, this);
+ if (m_viewfinderEngine == 0) {
+ m_error = KErrNoMemory;
+ qWarning("Failed to create viewfinder engine.");
+ return;
+ }
+
+ // Connect signals
+ connect(m_inactivityTimer, SIGNAL(timeout()), this, SLOT(toStandByStatus()));
+ connect(this, SIGNAL(statusChanged(QCamera::Status)),
+ m_imageSession, SLOT(cameraStatusChanged(QCamera::Status)));
+ connect(this, SIGNAL(statusChanged(QCamera::Status)),
+ m_videoSession, SLOT(cameraStatusChanged(QCamera::Status)));
+ connect(m_videoSession, SIGNAL(stateChanged(S60VideoCaptureSession::TVideoCaptureState)),
+ this, SLOT(videoStateChanged(S60VideoCaptureSession::TVideoCaptureState)));
+ connect(m_imageSession, SIGNAL(advancedSettingChanged()), this, SLOT(advancedSettingsCreated()));
+ connect(this, SIGNAL(cameraReadyChanged(bool)), m_imageSession, SIGNAL(readyForCaptureChanged(bool)));
+ connect(m_viewfinderEngine, SIGNAL(error(int, const QString&)), this, SIGNAL(error(int,const QString&)));
+ connect(m_imageSession, SIGNAL(cameraError(int, const QString&)), this, SIGNAL(error(int, const QString&)));
+ connect(m_imageSession, SIGNAL(captureSizeChanged(const QSize&)),
+ m_viewfinderEngine, SLOT(handleContentAspectRatioChange(const QSize&)));
+ connect(m_videoSession, SIGNAL(captureSizeChanged(const QSize&)),
+ m_viewfinderEngine, SLOT(handleContentAspectRatioChange(const QSize&)));
+
+ setCameraHandles();
+}
+
+S60CameraControl::~S60CameraControl()
+{
+ unloadCamera();
+
+ if (m_viewfinderEngine) {
+ delete m_viewfinderEngine;
+ m_viewfinderEngine = 0;
+ }
+
+ // Make sure AdvancedSettings are destructed
+ m_imageSession->deleteAdvancedSettings();
+
+ if (m_cameraEngine) {
+ delete m_cameraEngine;
+ m_cameraEngine = 0;
+ }
+
+ if (m_inactivityTimer) {
+ delete m_inactivityTimer;
+ m_inactivityTimer = 0;
+ }
+}
+
+void S60CameraControl::setState(QCamera::State state)
+{
+ if (m_error) { // Most probably failure in contructor
+ setError(m_error, tr("Unexpected camera error."));
+ return;
+ }
+
+ if (m_requestedState == state)
+ return;
+
+ if (m_inactivityTimer->isActive())
+ m_inactivityTimer->stop();
+
+ // Save the target state
+ m_requestedState = state;
+ emit stateChanged(m_requestedState);
+
+ switch (state) {
+ case QCamera::UnloadedState: // To UnloadedState - Release resources
+ switch (m_internalState) {
+ case QCamera::UnloadedStatus:
+ // Do nothing
+ break;
+ case QCamera::LoadingStatus:
+ case QCamera::StartingStatus:
+ // Release resources when ready (setting state handles this)
+ return;
+ case QCamera::LoadedStatus:
+ case QCamera::StandbyStatus:
+ // Unload
+ unloadCamera();
+ break;
+ case QCamera::ActiveStatus:
+ // Stop and Unload
+ stopCamera();
+ unloadCamera();
+ break;
+
+ default:
+ // Unrecognized internal state (Status)
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+ break;
+
+ case QCamera::LoadedState: // To LoadedState - Reserve resources OR Stop ViewFinder and Cancel Capture
+ switch (m_internalState) {
+ case QCamera::UnloadedStatus:
+ case QCamera::StandbyStatus:
+ // Load
+ loadCamera();
+ break;
+ case QCamera::LoadingStatus:
+ // Discard, already moving to LoadedStatus
+ return;
+ case QCamera::StartingStatus:
+ // Stop when ready (setting state handles this)
+ return;
+ case QCamera::LoadedStatus:
+ m_inactivityTimer->start(KInactivityTimerTimeout);
+ break;
+ case QCamera::ActiveStatus:
+ // Stop
+ stopCamera();
+ break;
+
+ default:
+ // Unregocnized internal state (Status)
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+ break;
+
+ case QCamera::ActiveState: // To ActiveState - (Reserve Resources and) Start ViewFinder
+ switch (m_internalState) {
+ case QCamera::UnloadedStatus:
+ case QCamera::StandbyStatus:
+ // Load and Start (setting state handles starting)
+ loadCamera();
+ break;
+ case QCamera::LoadingStatus:
+ // Start when loaded (setting state handles this)
+ break;
+ case QCamera::StartingStatus:
+ // Discard, already moving to ActiveStatus
+ return;
+ case QCamera::LoadedStatus:
+ // Start
+ startCamera();
+ break;
+ case QCamera::ActiveStatus:
+ // Do nothing
+ break;
+
+ default:
+ // Unregocnized internal state (Status)
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+ break;
+
+ default:
+ setError(KErrNotSupported, tr("Requested state is not supported."));
+ return;
+ }
+}
+
+QCamera::State S60CameraControl::state() const
+{
+ return m_requestedState;
+}
+
+QCamera::Status S60CameraControl::status() const
+{
+ return m_internalState;
+}
+
+QCamera::CaptureMode S60CameraControl::captureMode() const
+{
+ return m_captureMode;
+}
+
+void S60CameraControl::setCaptureMode(QCamera::CaptureMode mode)
+{
+ if (m_error) { // Most probably failure in contructor
+ setError(m_error, tr("Unexpected camera error."));
+ return;
+ }
+
+ if (m_captureMode == mode)
+ return;
+
+ // Setting CaptureMode Internally or Externally (Client)
+ if (!m_settingCaptureModeInternally) {
+ // Save the requested mode
+ m_requestedCaptureMode = mode;
+
+ // CaptureMode change pending (backend busy), wait
+ if (m_changeCaptureModeWhenReady)
+ return;
+ } else {
+ m_changeCaptureModeWhenReady = false; // Reset
+ }
+ m_settingCaptureModeInternally = false; // Reset
+
+ if (!isCaptureModeSupported(mode)) {
+ setError(KErrNotSupported, tr("Requested capture mode is not supported."));
+ return;
+ }
+
+ if (m_inactivityTimer->isActive())
+ m_inactivityTimer->stop();
+
+ switch (m_internalState) {
+ case QCamera::UnloadedStatus:
+ case QCamera::LoadedStatus:
+ case QCamera::StandbyStatus:
+ switch (mode) {
+ case QCamera::CaptureStillImage:
+ m_videoSession->releaseVideoRecording();
+ m_captureMode = QCamera::CaptureStillImage;
+ if (m_internalState == QCamera::LoadedStatus)
+ m_inactivityTimer->start(KInactivityTimerTimeout);
+ else if (m_internalState == QCamera::StandbyStatus)
+ loadCamera();
+ break;
+ case QCamera::CaptureVideo:
+ m_imageSession->releaseImageCapture();
+ m_captureMode = QCamera::CaptureVideo;
+ if (m_internalState == QCamera::LoadedStatus) {
+ // Revet InternalState as we need to wait for the video
+ // side initialization to complete
+ m_internalState = QCamera::LoadingStatus;
+ emit statusChanged(m_internalState);
+ int prepareSuccess = m_videoSession->initializeVideoRecording();
+ setError(prepareSuccess, tr("Loading video capture failed."));
+ } else if (m_internalState == QCamera::StandbyStatus)
+ loadCamera();
+ break;
+ }
+ break;
+ case QCamera::LoadingStatus:
+ case QCamera::StartingStatus:
+ m_changeCaptureModeWhenReady = true;
+ return;
+ case QCamera::ActiveStatus:
+ // Stop, Change Mode and Start again
+ stopCamera();
+ switch (mode) {
+ case QCamera::CaptureStillImage:
+ m_videoSession->releaseVideoRecording();
+ m_captureMode = QCamera::CaptureStillImage;
+ startCamera();
+ break;
+ case QCamera::CaptureVideo:
+ m_imageSession->releaseImageCapture();
+ m_captureMode = QCamera::CaptureVideo;
+ // Revet InternalState as we need to wait for the video
+ // side initialization to complete
+ m_internalState = QCamera::LoadingStatus;
+ emit statusChanged(m_internalState);
+ int prepareSuccess = m_videoSession->initializeVideoRecording();
+ setError(prepareSuccess, tr("Loading video recorder failed."));
+ break;
+ }
+ break;
+
+ default:
+ // Unregocnized internal state (Status)
+ setError(KErrNotSupported, tr("Requested capture mode is not supported."));
+ break;
+ }
+
+ emit captureModeChanged(mode);
+}
+
+bool S60CameraControl::isCaptureModeSupported(QCamera::CaptureMode mode) const
+{
+ switch (mode) {
+ case QCamera::CaptureStillImage:
+ return true;
+ case QCamera::CaptureVideo:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool S60CameraControl::canChangeProperty(QCameraControl::PropertyChangeType changeType, QCamera::Status status) const
+{
+ Q_UNUSED(status);
+
+ bool returnValue = false;
+
+ switch (changeType) {
+ case QCameraControl::CaptureMode:
+ case QCameraControl::VideoEncodingSettings:
+ case QCameraControl::ImageEncodingSettings:
+ returnValue = true;
+ break;
+
+ case QCameraControl::Viewfinder:
+ returnValue = false;
+ break;
+
+ default:
+ // Safer to revert state before the unknown operation
+ returnValue = false;
+ break;
+ }
+
+ return returnValue;
+}
+
+void S60CameraControl::setVideoOutput(QObject *output,
+ S60CameraViewfinderEngine::ViewfinderOutputType type)
+{
+ if (!m_viewfinderEngine) {
+ setError(KErrGeneral, tr("Failed to set viewfinder"));
+ return;
+ }
+
+ switch (type) {
+ case S60CameraViewfinderEngine::OutputTypeVideoWidget:
+ m_viewfinderEngine->setVideoWidgetControl(output);
+ break;
+ case S60CameraViewfinderEngine::OutputTypeRenderer:
+ m_viewfinderEngine->setVideoRendererControl(output);
+ break;
+ case S60CameraViewfinderEngine::OutputTypeVideoWindow:
+ m_viewfinderEngine->setVideoWindowControl(output);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void S60CameraControl::releaseVideoOutput(const S60CameraViewfinderEngine::ViewfinderOutputType type)
+{
+ m_viewfinderEngine->releaseControl(type);
+}
+
+void S60CameraControl::loadCamera()
+{
+ if (m_internalState < QCamera::LoadingStatus) {
+ m_internalState = QCamera::LoadingStatus;
+ emit statusChanged(m_internalState);
+ } else if (m_internalState == QCamera::LoadedStatus
+ || m_internalState >= QCamera::StartingStatus) {
+ // Nothing to load (already loaded)
+ return;
+ }
+ // Status = Loading or Standby
+
+ m_cameraEngine->ReserveAndPowerOn();
+
+ // Completion notified in MceoCameraReady()
+}
+
+void S60CameraControl::unloadCamera()
+{
+ if (m_internalState > QCamera::LoadingStatus) {
+ m_internalState = QCamera::LoadingStatus;
+ emit statusChanged(m_internalState);
+ } else if (m_internalState < QCamera::LoadingStatus) {
+ // Nothing to unload
+ return;
+ }
+ // Status = Loading
+
+ if (m_inactivityTimer->isActive())
+ m_inactivityTimer->stop();
+
+ m_cameraEngine->ReleaseAndPowerOff();
+
+ m_internalState = QCamera::UnloadedStatus;
+ emit statusChanged(m_internalState);
+}
+
+void S60CameraControl::startCamera()
+{
+ if (m_internalState < QCamera::StartingStatus) {
+ m_internalState = QCamera::StartingStatus;
+ emit statusChanged(m_internalState);
+ } else if (m_internalState > QCamera::StartingStatus) {
+ // Nothing to start (already started)
+ return;
+ }
+ // Status = Starting
+
+ if (m_inactivityTimer->isActive())
+ m_inactivityTimer->stop();
+
+ if (m_viewfinderEngine)
+ m_viewfinderEngine->startViewfinder();
+ else
+ setError(KErrGeneral, tr("Failed to start viewfinder."));
+
+ m_internalState = QCamera::ActiveStatus;
+ emit statusChanged(m_internalState);
+
+ emit cameraReadyChanged(true);
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ MceoCameraReady(); // Signal that we are ready
+#endif
+}
+
+void S60CameraControl::stopCamera()
+{
+ if (m_internalState > QCamera::StartingStatus) {
+ m_internalState = QCamera::StartingStatus;
+ emit statusChanged(m_internalState);
+ } else if (m_internalState < QCamera::StartingStatus) {
+ // Nothing to stop
+ return;
+ }
+ // Status = Starting
+
+ // Cancel ongoing operations if any
+ m_imageSession->cancelCapture();
+ m_videoSession->stopRecording();
+
+ emit cameraReadyChanged(false);
+ if (m_viewfinderEngine)
+ m_viewfinderEngine->stopViewfinder();
+ else
+ setError(KErrGeneral, tr("Failed to stop viewfinder."));
+
+ m_internalState = QCamera::LoadedStatus;
+ emit statusChanged(m_internalState);
+
+ m_inactivityTimer->start(KInactivityTimerTimeout);
+}
+
+void S60CameraControl::videoStateChanged(const S60VideoCaptureSession::TVideoCaptureState state)
+{
+ // Save video state
+ m_videoCaptureState = state;
+
+ if (m_rotateCameraWhenReady) {
+ if (m_videoCaptureState != S60VideoCaptureSession::ERecording &&
+ m_videoCaptureState != S60VideoCaptureSession::EPaused)
+ resetCameraOrientation();
+ }
+
+ // If video recording was stopped, video state reverts back to
+ // Initializing. In that case revert also Camera status to notify that
+ // video initialization needs to be completed.
+ if (state == S60VideoCaptureSession::EInitializing) {
+ if (m_internalState > QCamera::LoadingStatus) {
+ m_internalState = QCamera::LoadingStatus;
+ emit statusChanged(m_internalState);
+ }
+
+ // Handle video initialization completion
+ } else if (state == S60VideoCaptureSession::EInitialized) {
+
+ // Make sure state is not downgraded
+ if (m_internalState == QCamera::LoadedStatus
+ || m_internalState == QCamera::ActiveStatus) {
+ // Do nothing (already in target state)
+ } else if (m_internalState == QCamera::StartingStatus) {
+ m_internalState = QCamera::ActiveStatus;
+ emit statusChanged(m_internalState);
+ } else {
+ m_internalState = QCamera::LoadedStatus;
+ emit statusChanged(m_internalState);
+ }
+
+ switch (m_requestedState) {
+ case QCamera::UnloadedState:
+ stopCamera();
+ unloadCamera();
+ if (m_changeCaptureModeWhenReady) {
+ m_settingCaptureModeInternally = true;
+ setCaptureMode(m_requestedCaptureMode);
+ }
+ break;
+ case QCamera::LoadedState:
+ stopCamera();
+ if (m_changeCaptureModeWhenReady) {
+ m_settingCaptureModeInternally = true;
+ setCaptureMode(m_requestedCaptureMode);
+ }
+ m_inactivityTimer->start(KInactivityTimerTimeout);
+ break;
+ case QCamera::ActiveState:
+ if (m_changeCaptureModeWhenReady) {
+ m_settingCaptureModeInternally = true;
+ setCaptureMode(m_requestedCaptureMode);
+ }
+ startCamera();
+ break;
+
+ default:
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+ }
+}
+
+void S60CameraControl::imageCaptured(const int imageId, const QImage& preview)
+{
+ Q_UNUSED(imageId);
+ Q_UNUSED(preview);
+
+ // Unsubscribe the readyForCaptureChanged notification
+ disconnect(m_imageSession, SIGNAL(imageCaptured(const int, const QImage&)),
+ this, SLOT(imageCaptured(const int, const QImage&)));
+
+ if (m_rotateCameraWhenReady)
+ resetCameraOrientation();
+}
+
+void S60CameraControl::advancedSettingsCreated()
+{
+ m_advancedSettings = m_imageSession->advancedSettings();
+
+ if (m_advancedSettings)
+ connect(m_advancedSettings, SIGNAL(error(int, const QString&)), this, SIGNAL(error(int, const QString&)));
+}
+
+void S60CameraControl::MceoCameraReady()
+{
+ // Rotate camera if requested
+ if (m_rotateCameraWhenReady) {
+ resetCameraOrientation();
+ return;
+ }
+
+ if (m_internalState != QCamera::LoadedStatus) {
+
+ switch (m_requestedState) {
+ case QCamera::UnloadedState:
+ m_internalState = QCamera::LoadedStatus;
+ emit statusChanged(QCamera::LoadedStatus);
+
+ stopCamera();
+ unloadCamera();
+
+ if (m_changeCaptureModeWhenReady) {
+ m_settingCaptureModeInternally = true;
+ setCaptureMode(m_requestedCaptureMode);
+ }
+ break;
+
+ case QCamera::LoadedState:
+ if (m_captureMode == QCamera::CaptureVideo) {
+ int prepareSuccess = m_videoSession->initializeVideoRecording();
+ setError(prepareSuccess, tr("Loading video capture failed."));
+
+ // State change signalled when reservation is complete (in videoStateChanged())
+ return;
+ }
+ m_internalState = QCamera::LoadedStatus;
+ emit statusChanged(QCamera::LoadedStatus);
+
+ if (m_changeCaptureModeWhenReady) {
+ setCaptureMode(m_requestedCaptureMode);
+ m_changeCaptureModeWhenReady = false; // Reset
+ }
+
+ if (m_requestedState == QCamera::LoadedStatus &&
+ m_internalState == QCamera::LoadedStatus)
+ m_inactivityTimer->start(KInactivityTimerTimeout);
+ break;
+
+ case QCamera::ActiveState:
+ if (m_captureMode == QCamera::CaptureVideo) {
+ int prepareSuccess = m_videoSession->initializeVideoRecording();
+ setError(prepareSuccess, tr("Loading video capture failed."));
+
+ // State change signalled when reservation is complete (in videoStateChanged())
+ return;
+ }
+
+ m_internalState = QCamera::LoadedStatus;
+ emit statusChanged(QCamera::LoadedStatus);
+
+ if (m_changeCaptureModeWhenReady) {
+ setCaptureMode(m_requestedCaptureMode);
+ m_changeCaptureModeWhenReady = false; // Reset
+ }
+ startCamera();
+ break;
+
+ default:
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+ }
+}
+
+void S60CameraControl::MceoHandleError(TCameraEngineError aErrorType, TInt aError)
+{
+ Q_UNUSED(aErrorType);
+
+ if (aError == KErrAccessDenied) {
+ setError(KErrGeneral, tr("Access to camera device was rejected."));
+ } else if (aError == KErrHardwareNotAvailable) {
+ setError(aError, tr("Camera resources were lost."));
+ toStandByStatus();
+ }
+ else
+ setError(aError, tr("Unexpected camera error."));
+}
+
+void S60CameraControl::setError(const TInt error, const QString &description)
+{
+ if (error == KErrNone)
+ return;
+
+ m_error = error;
+ QCamera::Error cameraError = fromSymbianErrorToQtMultimediaError(m_error);
+
+ emit this->error(int(cameraError), description);
+
+ // Reset everything, if other than not supported error or resource loss
+ if (error != KErrNotSupported && error != KErrHardwareNotAvailable)
+ resetCamera(true); // Try to recover from error
+ else
+ m_error = KErrNone; // Reset error
+}
+
+QCamera::Error S60CameraControl::fromSymbianErrorToQtMultimediaError(int aError)
+{
+ switch(aError) {
+ case KErrNone:
+ return QCamera::NoError; // No errors have occurred
+
+ case KErrNotSupported:
+ return QCamera::NotSupportedFeatureError; // The feature is not supported
+ case KErrNotFound:
+ case KErrBadHandle:
+ return QCamera::ServiceMissingError; // No camera service available
+ case KErrArgument:
+ case KErrNotReady:
+ return QCamera::InvalidRequestError; // Invalid parameter or state
+
+ default:
+ return QCamera::CameraError; // An error has occurred (i.e. General Error)
+ }
+}
+
+// For S60CameraVideoDeviceControl
+int S60CameraControl::deviceCount()
+{
+#ifdef Q_CC_NOKIAX86 // Emulator
+ return 1;
+#endif
+
+ return CCameraEngine::CamerasAvailable();
+}
+
+int S60CameraControl::defaultDevice() const
+{
+ return KDefaultCameraDevice;
+}
+
+int S60CameraControl::selectedDevice() const
+{
+ return m_deviceIndex;
+}
+
+void S60CameraControl::setSelectedDevice(const int index)
+{
+ if (m_deviceIndex != index) {
+ if (index >= 0 && index < deviceCount()) {
+ m_deviceIndex = index;
+ resetCamera();
+ } else {
+ setError(KErrNotSupported, tr("Requested camera is not available."));
+ }
+ }
+}
+
+QString S60CameraControl::name(const int index)
+{
+ QString cameraName;
+ switch (index) {
+ case 0:
+ cameraName = tr("Primary camera");
+ break;
+ case 1:
+ cameraName = tr("Secondary camera");
+ break;
+ case 2:
+ cameraName = tr("Tertiary camera");
+ break;
+
+ default:
+ cameraName = tr("Unidentified Camera");
+ break;
+ }
+
+ return cameraName;
+}
+
+QString S60CameraControl::description(const int index)
+{
+ QString cameraDesc;
+ switch (index) {
+ case 0:
+ cameraDesc = tr("Device primary camera");
+ break;
+ case 1:
+ cameraDesc = tr("Device secondary camera");
+ break;
+ case 2:
+ cameraDesc = tr("Device tertiary camera");
+ break;
+
+ default:
+ cameraDesc = tr("Unidentified Camera");
+ break;
+ }
+
+ return cameraDesc;
+}
+
+void S60CameraControl::resetCamera(bool errorHandling)
+{
+ if (m_inactivityTimer->isActive())
+ m_inactivityTimer->stop();
+
+ // Cancel ongoing activity
+ m_imageSession->cancelCapture();
+ m_videoSession->stopRecording(false); // Don't re-initialize video
+
+ // Advanced settings must be destructed before the camera
+ m_imageSession->deleteAdvancedSettings();
+
+ // Release resources
+ stopCamera();
+ unloadCamera();
+
+ disconnect(m_viewfinderEngine, SIGNAL(error(int, const QString&)), this, SIGNAL(error(int,const QString&)));
+ if (m_viewfinderEngine) {
+ delete m_viewfinderEngine;
+ m_viewfinderEngine = 0;
+ }
+
+ if (m_cameraEngine) {
+ delete m_cameraEngine;
+ m_cameraEngine = 0;
+ }
+
+ TRAPD(err, m_cameraEngine = CCameraEngine::NewL(m_deviceIndex, 0, this));
+ if (err) {
+ m_cameraEngine = 0;
+ if (errorHandling) {
+ qWarning("Failed to recover from error.");
+ if (err == KErrPermissionDenied)
+ emit error(int(QCamera::ServiceMissingError), tr("Recovering from error failed. Possibly missing capabilities."));
+ else
+ emit error(int(QCamera::CameraError), tr("Recovering from error failed."));
+ } else {
+ if (err == KErrPermissionDenied)
+ setError(err, tr("Camera device creation failed. Possibly missing capabilities."));
+ else
+ setError(err, tr("Camera device creation failed."));
+ }
+ return;
+ }
+
+ // Notify list of available camera devices has been updated
+ emit devicesChanged();
+
+ m_viewfinderEngine = new S60CameraViewfinderEngine(this, m_cameraEngine, this);
+ if (m_viewfinderEngine == 0)
+ setError(KErrNoMemory, tr("Viewfinder device creation failed."));
+ connect(m_viewfinderEngine, SIGNAL(error(int, const QString&)), this, SIGNAL(error(int,const QString&)));
+
+ setCameraHandles();
+
+ // Reset state
+ //setState(QCamera::UnloadedState);
+ if (m_internalState != QCamera::UnloadedStatus) {
+ m_internalState = QCamera::UnloadedStatus;
+ emit statusChanged(m_internalState);
+ }
+ if (m_requestedState != QCamera::UnloadedState) {
+ m_requestedState = QCamera::UnloadedState;
+ emit stateChanged(m_requestedState);
+ }
+
+ // Reset error
+ m_error = KErrNone;
+}
+
+/*
+ * Reset everything else than viewfinder engine and errors.
+ */
+void S60CameraControl::resetCameraOrientation()
+{
+ // If camera has not been created, it will be created automatically to correct orientation
+ if (!m_cameraEngine)
+ return;
+
+ // Check Image/VideoCapture allow rotation
+ if ((!m_cameraEngine->IsCameraReady() && m_internalState != QCamera::UnloadedStatus) ||
+ m_videoCaptureState == S60VideoCaptureSession::ERecording ||
+ m_videoCaptureState == S60VideoCaptureSession::EPaused) {
+
+ // If image capture is ongoing, request notification about the
+ // completion (imageCaptured() is used because that comes asynchronously
+ // after the image is captured)
+ // Obs! If preview creation is changed to be synchnonously done during
+ // the image capture this implementation needs to be changed)
+ if (m_videoCaptureState != S60VideoCaptureSession::ERecording &&
+ m_videoCaptureState != S60VideoCaptureSession::EPaused &&
+ m_internalState == QCamera::ActiveStatus)
+ connect(m_imageSession, SIGNAL(imageCaptured(const int, const QImage&)),
+ this, SLOT(imageCaptured(const int, const QImage&)));
+
+ m_rotateCameraWhenReady = true;
+ return;
+ }
+
+ m_rotateCameraWhenReady = false; // Reset
+
+ QCamera::State originalState = m_requestedState;
+
+ // Cancel ongoing activity
+ m_imageSession->cancelCapture();
+ m_videoSession->stopRecording(false); // Don't re-initialize video
+
+ // Advanced settings must be destructed before the camera
+ m_imageSession->deleteAdvancedSettings();
+
+ // Release resources
+ stopCamera();
+ unloadCamera();
+
+ // Unset CameraEngine to ViewfinderEngine
+ m_viewfinderEngine->setNewCameraEngine(0);
+ if (m_cameraEngine) {
+ delete m_cameraEngine;
+ m_cameraEngine = 0;
+ }
+
+ TRAPD(err, m_cameraEngine = CCameraEngine::NewL(m_deviceIndex, 0, this));
+ if (err) {
+ setError(err, tr("Camera device creation failed."));
+ return;
+ }
+ // Reset CameraEngine to ViewfinderEngine
+ m_viewfinderEngine->setNewCameraEngine(m_cameraEngine);
+
+ // Notify list of available camera devices has been updated
+ emit devicesChanged();
+
+ setCameraHandles();
+
+ // Reset state
+ if (m_internalState != QCamera::UnloadedStatus) {
+ m_internalState = QCamera::UnloadedStatus;
+ emit statusChanged(m_internalState);
+ }
+ if (m_requestedState != QCamera::UnloadedState) {
+ m_requestedState = QCamera::UnloadedState;
+ emit stateChanged(m_requestedState);
+ }
+
+ setState(originalState);
+}
+
+void S60CameraControl::setCameraHandles()
+{
+ m_imageSession->setCurrentDevice(m_deviceIndex);
+ m_imageSession->setCameraHandle(m_cameraEngine);
+ m_cameraEngine->SetImageCaptureObserver(m_imageSession);
+ m_videoSession->setCameraHandle(m_cameraEngine);
+}
+
+void S60CameraControl::toStandByStatus()
+{
+ // Cancel ongoing operations if any
+ m_imageSession->cancelCapture();
+ m_videoSession->stopRecording(false); // Don't re-initialize video
+
+ emit cameraReadyChanged(false);
+ if (m_viewfinderEngine)
+ m_viewfinderEngine->stopViewfinder();
+ else
+ setError(KErrGeneral, tr("Failed to stop viewfinder."));
+
+ m_cameraEngine->ReleaseAndPowerOff();
+
+ m_internalState = QCamera::StandbyStatus;
+ emit statusChanged(m_internalState);
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameracontrol.h b/src/plugins/symbian/ecam/s60cameracontrol.h
new file mode 100644
index 000000000..95c31fb34
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameracontrol.h
@@ -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 S60CAMERACONTROL_H
+#define S60CAMERACONTROL_H
+
+#include <qcameracontrol.h>
+
+#include "s60cameraengineobserver.h" // MCameraEngineObserver
+#include "s60videocapturesession.h" // TVideoCaptureState
+#include "s60cameraviewfinderengine.h" // ViewfinderOutputType
+
+#include <e32base.h>
+#include <fbs.h>
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+class S60VideoCaptureSession;
+class S60CameraSettings;
+class CCameraEngine;
+class S60CameraViewfinderEngine;
+class QTimer;
+
+/*
+ * Control for controlling camera base operations (e.g. start/stop and capture
+ * mode).
+ */
+class S60CameraControl : public QCameraControl, public MCameraEngineObserver
+{
+ Q_OBJECT
+
+public: // Constructors & Destructor
+
+ S60CameraControl(QObject *parent = 0);
+ S60CameraControl(S60VideoCaptureSession *videosession,
+ S60ImageCaptureSession *imagesession,
+ QObject *parent = 0);
+ ~S60CameraControl();
+
+public: // QCameraControl
+
+ // State
+ QCamera::State state() const;
+ void setState(QCamera::State state);
+
+ // Status
+ QCamera::Status status() const;
+
+ // Capture Mode
+ QCamera::CaptureMode captureMode() const;
+ void setCaptureMode(QCamera::CaptureMode);
+ bool isCaptureModeSupported(QCamera::CaptureMode mode) const;
+
+ // Property Setting
+ bool canChangeProperty(QCameraControl::PropertyChangeType changeType, QCamera::Status status) const;
+
+/*
+Q_SIGNALS:
+ void stateChanged(QCamera::State);
+ void statusChanged(QCamera::Status);
+ void error(int error, const QString &errorString);
+ void captureModeChanged(QCamera::CaptureMode);
+*/
+
+public: // Internal
+
+ void setError(const TInt error, const QString &description);
+ void resetCameraOrientation();
+
+ // To provide QVideoDeviceControl info
+ static int deviceCount();
+ static QString name(const int index);
+ static QString description(const int index);
+ int defaultDevice() const;
+ int selectedDevice() const;
+ void setSelectedDevice(const int index);
+
+ void setVideoOutput(QObject *output,
+ const S60CameraViewfinderEngine::ViewfinderOutputType type);
+ void releaseVideoOutput(const S60CameraViewfinderEngine::ViewfinderOutputType type);
+
+private slots: // Internal Slots
+
+ void videoStateChanged(const S60VideoCaptureSession::TVideoCaptureState state);
+ // Needed to detect image capture completion when trying to rotate the camera
+ void imageCaptured(const int imageId, const QImage& preview);
+ /*
+ * This method moves the camera to the StandBy status:
+ * - If camera access was lost
+ * - If camera has been inactive in LoadedStatus for a long time
+ */
+ void toStandByStatus();
+ void advancedSettingsCreated();
+
+protected: // MCameraEngineObserver
+
+ void MceoCameraReady();
+ void MceoHandleError(TCameraEngineError aErrorType, TInt aError);
+
+private: // Internal
+
+ QCamera::Error fromSymbianErrorToQtMultimediaError(int aError);
+
+ void loadCamera();
+ void unloadCamera();
+ void startCamera();
+ void stopCamera();
+
+ void resetCamera(bool errorHandling = false);
+ void setCameraHandles();
+
+signals: // Internal Signals
+
+ void cameraReadyChanged(bool);
+ void devicesChanged();
+
+private: // Data
+
+ CCameraEngine *m_cameraEngine;
+ S60CameraViewfinderEngine *m_viewfinderEngine;
+ S60ImageCaptureSession *m_imageSession;
+ S60VideoCaptureSession *m_videoSession;
+ S60CameraSettings *m_advancedSettings;
+ QObject *m_videoOutput;
+ QTimer *m_inactivityTimer;
+ QCamera::CaptureMode m_captureMode;
+ QCamera::CaptureMode m_requestedCaptureMode;
+ bool m_settingCaptureModeInternally;
+ QCamera::Status m_internalState;
+ QCamera::State m_requestedState;
+ int m_deviceIndex;
+ mutable int m_error;
+ bool m_changeCaptureModeWhenReady;
+ bool m_rotateCameraWhenReady;
+ S60VideoCaptureSession::TVideoCaptureState m_videoCaptureState;
+};
+
+#endif // S60CAMERACONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameraengine.cpp b/src/plugins/symbian/ecam/s60cameraengine.cpp
new file mode 100644
index 000000000..dbd5fb33e
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraengine.cpp
@@ -0,0 +1,824 @@
+/****************************************************************************
+ **
+ ** 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 "s60cameraengine.h"
+#include "s60cameraengineobserver.h"
+#include "s60cameraconstants.h"
+#include <QtCore/qglobal.h>
+#include <fbs.h> // CFbsBitmap
+#ifdef ECAM_PREVIEW_API
+ #include <platform/ecam/camerasnapshot.h>
+#endif // ECAM_PREVIEW_API
+
+CCameraEngine::CCameraEngine()
+{
+}
+
+CCameraEngine::CCameraEngine(TInt aCameraHandle,
+ TInt aPriority,
+ MCameraEngineObserver* aObserver) :
+ // CBase initializes member variables to NULL
+ iObserver(aObserver),
+ iCameraIndex(aCameraHandle),
+ iPriority(aPriority),
+ iEngineState(EEngineNotReady),
+ iCaptureResolution(TSize(0,0)),
+ iNew2LImplementation(false),
+ iLatestImageBufferIndex(1) // Thus we start from index 0
+{
+ // Observer is mandatory
+ ASSERT(aObserver != NULL);
+}
+
+CCameraEngine::~CCameraEngine()
+{
+ StopViewFinder();
+ ReleaseViewFinderBuffer(); // Releases iViewFinderBuffer
+ ReleaseImageBuffer(); // Releases iImageBuffer + iImageBitmap
+
+ iAdvancedSettingsObserver = NULL;
+ iImageCaptureObserver = NULL;
+ iViewfinderObserver = NULL;
+
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ delete iAutoFocus;
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+
+ if (iCamera) {
+ iCamera->Release();
+ delete iCamera;
+ iCamera = NULL;
+ }
+}
+
+TInt CCameraEngine::CamerasAvailable()
+{
+ return CCamera::CamerasAvailable();
+}
+
+CCameraEngine* CCameraEngine::NewL(TInt aCameraHandle,
+ TInt aPriority,
+ MCameraEngineObserver* aObserver)
+{
+ CCameraEngine* self = new (ELeave) CCameraEngine(aCameraHandle, aPriority, aObserver);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+void CCameraEngine::ConstructL()
+{
+ if (!CCamera::CamerasAvailable())
+ User::Leave(KErrHardwareNotAvailable);
+
+#ifndef Q_CC_NOKIAX86 // Not Emulator
+ TInt err(KErrNone);
+#else // Emulator
+ TInt err(KErrNotFound);
+#endif // !(Q_CC_NOKIAX86)
+
+#ifdef S60_31_PLATFORM
+ // Construct CCamera object for S60 3.1 (NewL)
+ iNew2LImplementation = false;
+ TRAP(err, iCamera = CCamera::NewL(*this, iCameraIndex));
+ if (err)
+ User::Leave(err);
+#else // For S60 3.2 onwards - use this constructor (New2L)
+ iNew2LImplementation = true;
+ TRAP(err, iCamera = CCamera::New2L(*this, iCameraIndex, iPriority));
+ if (err)
+ User::Leave(err);
+#endif // S60_31_PLATFORM
+
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ // Might not be supported for secondary camera, discard errors
+ TRAP(err, iAutoFocus = CCamAutoFocus::NewL(iCamera));
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+
+ if (iCamera == NULL)
+ User::Leave(KErrNoMemory);
+
+ iCamera->CameraInfo(iCameraInfo);
+}
+
+void CCameraEngine::SetAdvancedObserver(MAdvancedSettingsObserver* aAdvancedSettingsObserver)
+{
+ iAdvancedSettingsObserver = aAdvancedSettingsObserver;
+}
+
+void CCameraEngine::SetImageCaptureObserver(MCameraEngineImageCaptureObserver* aImageCaptureObserver)
+{
+ iImageCaptureObserver = aImageCaptureObserver;
+}
+
+void CCameraEngine::SetViewfinderObserver(MCameraViewfinderObserver* aViewfinderObserver)
+{
+ iViewfinderObserver = aViewfinderObserver;
+}
+
+void CCameraEngine::ReserveAndPowerOn()
+{
+ if (!iCamera || iEngineState > EEngineNotReady) {
+ iObserver->MceoHandleError(EErrReserve, KErrNotReady);
+ return;
+ }
+
+ iCamera->Reserve();
+}
+
+void CCameraEngine::ReleaseAndPowerOff()
+{
+ if (iEngineState >= EEngineIdle) {
+ CancelCapture();
+ StopViewFinder();
+ FocusCancel();
+ iCamera->PowerOff();
+ iCamera->Release();
+ }
+ iEngineState = EEngineNotReady;
+}
+
+void CCameraEngine::StartViewFinderL(TSize& aSize)
+{
+ if (iEngineState < EEngineIdle)
+ User::Leave(KErrNotReady);
+
+ if (0 == (iCameraInfo.iOptionsSupported & TCameraInfo::EViewFinderBitmapsSupported))
+ User::Leave(KErrNotSupported);
+
+ if (!iCamera->ViewFinderActive()) {
+ if (iCameraIndex != 0)
+ iCamera->SetViewFinderMirrorL(true);
+ iCamera->StartViewFinderBitmapsL(aSize);
+ }
+}
+
+void CCameraEngine::StopViewFinder()
+{
+ if (iCamera && iCamera->ViewFinderActive())
+ iCamera->StopViewFinder();
+}
+
+void CCameraEngine::StartDirectViewFinderL(RWsSession& aSession,
+ CWsScreenDevice& aScreenDevice,
+ RWindowBase& aWindow,
+ TRect& aScreenRect,
+ TRect& aClipRect)
+{
+ if (iEngineState < EEngineIdle)
+ User::Leave(KErrNotReady);
+
+ if (0 == (iCameraInfo.iOptionsSupported & TCameraInfo::EViewFinderDirectSupported))
+ User::Leave(KErrNotSupported);
+
+ if (!iCamera->ViewFinderActive()) {
+ // Viewfinder extent needs to be clipped according to the clip rect.
+ // This is because the native camera framework does not support
+ // clipping and starting viewfinder with bigger than the display(S60
+ // 5.0 and older)/window(Symbian^3 and later) would cause viewfinder
+ // starting to fail entirely. This causes shrinking effect in some
+ // cases, but is better than not having the viewfinder at all.
+ if (aScreenRect.Intersects(aClipRect))
+ aScreenRect.Intersection(aClipRect);
+
+ if (iCameraIndex != 0)
+ iCamera->SetViewFinderMirrorL(true);
+ if (aScreenRect.Width() > 0 && aScreenRect.Height() > 0) {
+ iCamera->StartViewFinderDirectL(aSession, aScreenDevice, aWindow, aScreenRect);
+ } else {
+ if (iObserver)
+ iObserver->MceoHandleError(EErrViewFinderReady, KErrArgument);
+ }
+ }
+}
+
+void CCameraEngine::PrepareL(TSize& aCaptureSize, CCamera::TFormat aFormat)
+{
+ iImageCaptureFormat = aFormat;
+
+ TInt closestVar = KMaxTInt, selected = 0;
+ TSize size;
+
+ // Scan through supported capture sizes and select the closest match
+ for (TInt index = 0; index < iCameraInfo.iNumImageSizesSupported; index++) {
+
+ iCamera->EnumerateCaptureSizes(size, index, aFormat);
+ if (size == aCaptureSize) {
+ selected = index;
+ break;
+ }
+
+ TSize varSz = size - aCaptureSize;
+ TInt variation = varSz.iWidth * varSz.iHeight;
+ if (variation < closestVar) {
+ closestVar = variation;
+ selected = index;
+ }
+ }
+
+ iCamera->EnumerateCaptureSizes(aCaptureSize, selected, aFormat);
+ iCaptureResolution = aCaptureSize;
+ iCamera->PrepareImageCaptureL(aFormat, selected);
+}
+
+void CCameraEngine::CaptureL()
+{
+ if (iEngineState < EEngineIdle)
+ User::Leave(KErrNotReady);
+
+ iCamera->CaptureImage();
+ iEngineState = EEngineCapturing;
+}
+
+void CCameraEngine::CancelCapture()
+{
+ if (iEngineState == EEngineCapturing) {
+ iCamera->CancelCaptureImage();
+ iEngineState = EEngineIdle;
+ }
+}
+
+void CCameraEngine::HandleEvent(const TECAMEvent &aEvent)
+{
+ if (aEvent.iEventType == KUidECamEventReserveComplete) {
+ ReserveComplete(aEvent.iErrorCode);
+ return;
+ }
+
+ if (aEvent.iEventType == KUidECamEventPowerOnComplete) {
+ PowerOnComplete(aEvent.iErrorCode);
+ return;
+ }
+
+ if (aEvent.iEventType == KUidECamEventCameraNoLongerReserved) {
+ // All camera related operations need to be stopped
+ iObserver->MceoHandleError(EErrReserve, KErrHardwareNotAvailable);
+ return;
+ }
+
+#ifdef ECAM_PREVIEW_API
+ if (aEvent.iEventType == KUidECamEventCameraSnapshot) {
+ HandlePreview();
+ return;
+ }
+#endif // ECAM_PREVIEW_API
+
+#if !defined(Q_CC_NOKIAX86) // Not Emulator
+ // Other events; Exposure, Zoom, etc. (See ecamadvancedsettings.h)
+ if (iAdvancedSettingsObserver)
+ iAdvancedSettingsObserver->HandleAdvancedEvent(aEvent);
+
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleOtherEvent(aEvent);
+#endif // !Q_CC_NOKIAX86
+}
+
+void CCameraEngine::ReserveComplete(TInt aError)
+{
+ if (aError == KErrNone) {
+ iCamera->PowerOn();
+#ifdef S60_31_PLATFORM
+ } else if (aError == KErrAlreadyExists) { // Known Issue on some S60 3.1 devices
+ User::After(500000); // Wait for 0,5 second and try again
+ iCamera->Reserve();
+#endif // S60_31_PLATFORM
+ } else {
+ iObserver->MceoHandleError(EErrReserve, aError);
+ }
+}
+
+void CCameraEngine::PowerOnComplete(TInt aError)
+{
+ if (aError) {
+ iObserver->MceoHandleError(EErrPowerOn, aError);
+ iEngineState = EEngineNotReady;
+ return;
+ }
+
+ // Init AutoFocus
+#ifndef Q_CC_NOKIAX86 // Not Emulator
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT // S60 3.1
+ if( iAutoFocus ) {
+ TRAPD(afErr, iAutoFocus->InitL( *this ));
+ if (afErr) {
+ delete iAutoFocus;
+ iAutoFocus = 0;
+ }
+ }
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+#endif // !Q_CC_NOKIAX86
+
+ iEngineState = EEngineIdle;
+ iObserver->MceoCameraReady();
+}
+
+#ifdef ECAM_PREVIEW_API
+/**
+ * This method creates the CCameraPreview object and requests the previews to
+ * be provided during the image or video capture
+ */
+void CCameraEngine::EnablePreviewProvider(MCameraPreviewObserver *aPreviewObserver)
+{
+ // Delete old one if exists
+ if (iCameraSnapshot)
+ delete iCameraSnapshot;
+
+ iPreviewObserver = aPreviewObserver;
+
+ TInt error = KErrNone;
+
+ if (iCamera) {
+ TRAP(error, iCameraSnapshot = CCamera::CCameraSnapshot::NewL(*iCamera));
+ if (error) {
+ if (iObserver)
+ iObserver->MceoHandleError(EErrPreview, error);
+ return;
+ }
+
+ TRAP(error, iCameraSnapshot->PrepareSnapshotL(KDefaultFormatPreview, SelectPreviewResolution(), EFalse));
+ if (error) {
+ if (iObserver)
+ iObserver->MceoHandleError(EErrPreview, error);
+ return;
+ }
+
+ iCameraSnapshot->StartSnapshot();
+ } else {
+ if (iObserver)
+ iObserver->MceoHandleError(EErrPreview, KErrNotReady);
+ }
+}
+
+/**
+ * This method disables and destroys the CCameraPreview object. Thus previews
+ * will not be provided during the image or video capture.
+ */
+void CCameraEngine::DisablePreviewProvider()
+{
+ if (!iCameraSnapshot)
+ return;
+
+ iCameraSnapshot->StopSnapshot();
+
+ delete iCameraSnapshot;
+ iCameraSnapshot = 0;
+
+ iPreviewObserver = 0;
+}
+#endif // ECAM_PREVIEW_API
+
+/*
+ * MCameraObserver2:
+ * New viewfinder frame available
+ */
+void CCameraEngine::ViewFinderReady(MCameraBuffer &aCameraBuffer, TInt aError)
+{
+ iViewFinderBuffer = &aCameraBuffer;
+
+ if (aError == KErrNone) {
+ if (iViewfinderObserver) {
+ TRAPD(err, iViewfinderObserver->MceoViewFinderFrameReady(aCameraBuffer.BitmapL(0)));
+ if (err)
+ iObserver->MceoHandleError(EErrViewFinderReady, err);
+ } else {
+ iObserver->MceoHandleError(EErrViewFinderReady, KErrNotReady);
+ }
+ }
+ else {
+ iObserver->MceoHandleError(EErrViewFinderReady, aError);
+ }
+}
+
+/*
+ * MCameraObserver:
+ * New viewfinder frame available
+ */
+void CCameraEngine::ViewFinderFrameReady(CFbsBitmap& aFrame)
+{
+ if (iViewfinderObserver)
+ iViewfinderObserver->MceoViewFinderFrameReady(aFrame);
+ else
+ iObserver->MceoHandleError(EErrViewFinderReady, KErrNotReady);
+}
+
+void CCameraEngine::ReleaseViewFinderBuffer()
+{
+ if (iNew2LImplementation) { // NewL Implementation does not use MCameraBuffer
+ if (iViewFinderBuffer) {
+ iViewFinderBuffer->Release();
+ iViewFinderBuffer = NULL;
+ }
+ }
+}
+
+void CCameraEngine::ReleaseImageBuffer()
+{
+ // Reset Bitmap
+ if (iLatestImageBufferIndex == 1 || iImageBitmap2 == NULL) {
+ if (iImageBitmap1) {
+ if (!iNew2LImplementation) { // NewL - Ownership transferred
+ iImageBitmap1->Reset(); // Reset/Delete Bitmap
+ delete iImageBitmap1;
+ }
+ iImageBitmap1 = NULL;
+ }
+ } else {
+ if (iImageBitmap2) {
+ if (!iNew2LImplementation) { // NewL - Ownership transferred
+ iImageBitmap2->Reset(); // Reset/Delete Bitmap
+ delete iImageBitmap2;
+ }
+ iImageBitmap2 = NULL;
+ }
+ }
+
+ // Reset Data pointers
+ if (iLatestImageBufferIndex == 1 || iImageData2 == NULL) {
+ if (!iNew2LImplementation) // NewL - Ownership transfers with buffer
+ delete iImageData1;
+ iImageData1 = NULL;
+ } else {
+ if (!iNew2LImplementation) // NewL - Ownership transfers with buffer
+ delete iImageData2;
+ iImageData2 = NULL;
+ }
+
+ // Reset ImageBuffer - New2L Implementation only
+ if (iLatestImageBufferIndex == 1 || iImageBuffer2 == NULL) {
+ if (iImageBuffer1) {
+ iImageBuffer1->Release();
+ iImageBuffer1 = NULL;
+ }
+ } else {
+ if (iImageBuffer2) {
+ iImageBuffer2->Release();
+ iImageBuffer2 = NULL;
+ }
+ }
+}
+
+/*
+ * MCameraObserver2
+ * Captured image is ready (New2L version)
+ */
+void CCameraEngine::ImageBufferReady(MCameraBuffer &aCameraBuffer, TInt aError)
+{
+ // Use the buffer that is available
+ if (!iImageBuffer1) {
+ iLatestImageBufferIndex = 0;
+ iImageBuffer1 = &aCameraBuffer;
+ } else {
+ iLatestImageBufferIndex = 1;
+ iImageBuffer2 = &aCameraBuffer;
+ }
+
+ bool isBitmap = true;
+ TInt err = KErrNone;
+
+ switch (iImageCaptureFormat) {
+ case CCamera::EFormatFbsBitmapColor4K:
+ case CCamera::EFormatFbsBitmapColor64K:
+ case CCamera::EFormatFbsBitmapColor16M:
+ case CCamera::EFormatFbsBitmapColor16MU:
+ if (iLatestImageBufferIndex == 0) {
+ TRAP(err, iImageBitmap1 = &iImageBuffer1->BitmapL(0));
+ if (err) {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, err);
+ }
+ } else {
+ TRAP(err, iImageBitmap2 = &iImageBuffer2->BitmapL(0));
+ if (err) {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, err);
+ }
+ }
+ isBitmap = true;
+ break;
+ case CCamera::EFormatExif:
+ if (iLatestImageBufferIndex == 0) {
+ TRAP(err, iImageData1 = iImageBuffer1->DataL(0));
+ if (err) {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, err);
+ }
+ } else {
+ TRAP(err, iImageData2 = iImageBuffer2->DataL(0));
+ if (err) {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, err);
+ }
+ }
+ isBitmap = false;
+ break;
+
+ default:
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, KErrNotSupported);
+ return;
+ }
+
+ // Handle captured image
+ HandleImageReady(aError, isBitmap);
+}
+
+/*
+ * MCameraObserver
+ * Captured image is ready (NewL version)
+ */
+void CCameraEngine::ImageReady(CFbsBitmap* aBitmap, HBufC8* aData, TInt aError)
+{
+ bool isBitmap = true;
+
+ // Toggle between the 2 buffers
+ if (iLatestImageBufferIndex == 1) {
+ iLatestImageBufferIndex = 0;
+ } else {
+ iLatestImageBufferIndex = 1;
+ }
+
+ switch (iImageCaptureFormat) {
+ case CCamera::EFormatFbsBitmapColor4K:
+ case CCamera::EFormatFbsBitmapColor64K:
+ case CCamera::EFormatFbsBitmapColor16M:
+ case CCamera::EFormatFbsBitmapColor16MU:
+ if (iLatestImageBufferIndex == 0)
+ iImageBitmap1 = aBitmap;
+ else
+ iImageBitmap2 = aBitmap;
+ isBitmap = true;
+ break;
+ case CCamera::EFormatExif:
+ if (iLatestImageBufferIndex == 0)
+ iImageData1 = aData;
+ else
+ iImageData2 = aData;
+ isBitmap = false;
+ break;
+
+ default:
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, KErrNotSupported);
+ return;
+ }
+
+ // Handle captured image
+ HandleImageReady(aError, isBitmap);
+}
+
+void CCameraEngine::HandleImageReady(const TInt aError, const bool isBitmap)
+{
+ iEngineState = EEngineIdle;
+
+ if (aError == KErrNone) {
+ if (isBitmap)
+ if (iImageCaptureObserver) {
+ if (iLatestImageBufferIndex == 0)
+ iImageCaptureObserver->MceoCapturedBitmapReady(iImageBitmap1);
+ else
+ iImageCaptureObserver->MceoCapturedBitmapReady(iImageBitmap2);
+ }
+ else
+ ReleaseImageBuffer();
+ else {
+ if (iImageCaptureObserver) {
+ if (iLatestImageBufferIndex == 0)
+ iImageCaptureObserver->MceoCapturedDataReady(iImageData1);
+ else
+ iImageCaptureObserver->MceoCapturedDataReady(iImageData2);
+ }
+ else
+ ReleaseImageBuffer();
+ }
+ } else {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrImageReady, aError);
+ }
+}
+
+#ifdef ECAM_PREVIEW_API
+void CCameraEngine::HandlePreview()
+{
+ if (!iCameraSnapshot) {
+ if (iObserver)
+ iObserver->MceoHandleError(EErrPreview, KErrGeneral);
+ return;
+ }
+
+ RArray<TInt> previewIndices;
+ CleanupClosePushL(previewIndices);
+
+ MCameraBuffer &newPreview = iCameraSnapshot->SnapshotDataL(previewIndices);
+
+ for (TInt i = 0; i < previewIndices.Count(); ++i)
+ iPreviewObserver->MceoPreviewReady(newPreview.BitmapL(0));
+
+ CleanupStack::PopAndDestroy(); // RArray<TInt> previewIndices
+}
+
+TSize CCameraEngine::SelectPreviewResolution()
+{
+ TSize currentResolution(iCaptureResolution);
+
+ TSize previewResolution(0, 0);
+ if (currentResolution == TSize(4000,2248) ||
+ currentResolution == TSize(3264,1832) ||
+ currentResolution == TSize(2592,1456) ||
+ currentResolution == TSize(1920,1080) ||
+ currentResolution == TSize(1280,720)) {
+ previewResolution = KDefaultSizePreview_Wide;
+ } else if (currentResolution == TSize(352,288) ||
+ currentResolution == TSize(176,144)) {
+ previewResolution = KDefaultSizePreview_CIF;
+ } else if (currentResolution == TSize(720,576)) {
+ previewResolution = KDefaultSizePreview_PAL;
+ } else if (currentResolution == TSize(720,480)) {
+ previewResolution = KDefaultSizePreview_NTSC;
+ } else {
+ previewResolution = KDefaultSizePreview_Normal;
+ }
+
+ return previewResolution;
+}
+#endif // ECAM_PREVIEW_API
+
+//=============================================================================
+// S60 3.1 - AutoFocus support (Other platforms, see S60CameraSettings class)
+//=============================================================================
+
+void CCameraEngine::InitComplete(TInt aError)
+{
+ if (aError) {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrAutoFocusInit, aError);
+ }
+}
+
+void CCameraEngine::OptimisedFocusComplete(TInt aError)
+{
+ iEngineState = EEngineIdle;
+
+ if (aError == KErrNone)
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoFocusComplete();
+ else {
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrOptimisedFocusComplete, aError);
+ }
+}
+
+TBool CCameraEngine::IsCameraReady() const
+{
+ // If reserved and powered on, but not focusing or capturing
+ if (iEngineState == EEngineIdle)
+ return ETrue;
+
+ return EFalse;
+}
+
+TBool CCameraEngine::IsDirectViewFinderSupported() const
+{
+ if (iCameraInfo.iOptionsSupported & TCameraInfo::EViewFinderDirectSupported)
+ return true;
+ else
+ return false;
+}
+
+TCameraInfo *CCameraEngine::CameraInfo()
+{
+ return &iCameraInfo;
+}
+
+TBool CCameraEngine::IsAutoFocusSupported() const
+{
+#ifndef Q_CC_NOKIAX86 // Not Emulator
+
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT // S60 3.1
+ return (iAutoFocus) ? ETrue : EFalse;
+#else // !S60_CAM_AUTOFOCUS_SUPPORT
+ return EFalse;
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+
+#else // Q_CC_NOKIAX86 - Emulator
+ return EFalse;
+#endif // !Q_CC_NOKIAX86
+}
+
+/*
+ * This function is used for focusing in S60 3.1 platform. Platforms from S60
+ * 3.2 onwards should use the focusing provided by the S60CameraSettings class.
+ */
+void CCameraEngine::StartFocusL()
+{
+ if (iEngineState != EEngineIdle)
+ return;
+
+#ifndef Q_CC_NOKIAX86 // Not Emulator
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT // S60 3.1
+ if (iAutoFocus) {
+ if (!iAFRange) {
+ iAFRange = CCamAutoFocus::ERangeNormal;
+ iAutoFocus->SetFocusRangeL(iAFRange);
+ }
+
+ iAutoFocus->AttemptOptimisedFocusL();
+ iEngineState = EEngineFocusing;
+ }
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+#endif // !Q_CC_NOKIAX86
+}
+
+/*
+ * This function is used for cancelling focusing in S60 3.1 platform. Platforms
+ * from S60 3.2 onwards should use the focusing provided by the
+ * S60CameraSettings class.
+ */
+void CCameraEngine::FocusCancel()
+{
+#ifndef Q_CC_NOKIAX86 // Not Emulator
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ if (iAutoFocus) {
+ iAutoFocus->Cancel();
+ iEngineState = EEngineIdle;
+ }
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+#endif // !Q_CC_NOKIAX86
+}
+
+void CCameraEngine::SupportedFocusRanges(TInt& aSupportedRanges) const
+{
+ aSupportedRanges = 0;
+
+#ifndef Q_CC_NOKIAX86 // Not Emulator
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ if (iAutoFocus) {
+ // CCamAutoFocus doesn't provide a method for getting supported ranges!
+ // Assume everything is supported (rather optimistic)
+ aSupportedRanges = CCamAutoFocus::ERangeMacro |
+ CCamAutoFocus::ERangePortrait |
+ CCamAutoFocus::ERangeNormal |
+ CCamAutoFocus::ERangeInfinite;
+ }
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+#endif // !Q_CC_NOKIAX86
+}
+
+void CCameraEngine::SetFocusRange(TInt aFocusRange)
+{
+#if !defined(Q_CC_NOKIAX86) // Not Emulator
+
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ if (iAutoFocus) {
+ TRAPD(focusErr, iAutoFocus->SetFocusRangeL((CCamAutoFocus::TAutoFocusRange)aFocusRange));
+ if (focusErr)
+ iObserver->MceoHandleError(EErrAutoFocusRange, focusErr);
+ }
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+
+#else // Q_CC_NOKIAX86 // Emulator
+ Q_UNUSED(aFocusRange);
+ if (iImageCaptureObserver)
+ iImageCaptureObserver->MceoHandleError(EErrAutoFocusRange, KErrNotSupported);
+#endif // !Q_CC_NOKIAX86
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraengine.h b/src/plugins/symbian/ecam/s60cameraengine.h
new file mode 100644
index 000000000..7a925c0ba
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraengine.h
@@ -0,0 +1,407 @@
+/****************************************************************************
+ **
+ ** 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 S60CCAMERAENGINE_H
+#define S60CCAMERAENGINE_H
+
+// INCLUDES
+#include <e32base.h>
+#include <ecam.h> // for MCameraObserver(2)
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+#include <ccamautofocus.h> // for CCamAutoFocus, MCamAutoFocusObserver
+#endif
+
+// FORWARD DECLARATIONS
+class MCameraEngineObserver;
+class MCameraEngineImageCaptureObserver;
+class MAdvancedSettingsObserver;
+class MCameraViewfinderObserver;
+class MCameraPreviewObserver;
+
+/*
+ * CameraEngine handling ECam operations needed.
+ */
+NONSHARABLE_CLASS( CCameraEngine ) : public CBase,
+ public MCameraObserver,
+ public MCameraObserver2
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ ,public MCamAutoFocusObserver
+#endif
+
+{
+public: // Enums
+
+ enum TCameraEngineState
+ {
+ EEngineNotReady = 0, // 0 - No resources reserved
+ EEngineInitializing, // 1 - Reserving and Powering On
+ EEngineIdle, // 2 - Reseved and Powered On
+ EEngineCapturing, // 3 - Capturing Still Image
+ EEngineFocusing // 4 - Focusing
+ };
+
+public: // Constructor & Destructor
+
+ static CCameraEngine* NewL( TInt aCameraHandle,
+ TInt aPriority,
+ MCameraEngineObserver* aObserver );
+ ~CCameraEngine();
+
+public:
+
+ /**
+ * External Advanced Settings callback observer.
+ */
+ void SetAdvancedObserver(MAdvancedSettingsObserver *aAdvancedSettingsObserver);
+
+ /**
+ * External Image Capture callback observer.
+ */
+ void SetImageCaptureObserver(MCameraEngineImageCaptureObserver *aImageCaptureObserver);
+
+ /**
+ * External Viewfinder callback observer.
+ */
+ void SetViewfinderObserver(MCameraViewfinderObserver *aViewfinderObserver);
+
+ /**
+ * Static function that returns the number of cameras on the device.
+ */
+ static TInt CamerasAvailable();
+
+ /**
+ * Returns the index of the currently active camera device
+ */
+ TInt CurrentCameraIndex() const { return iCameraIndex; }
+
+ /**
+ * Returns the current state (TCameraEngineState)
+ * of the camera engine.
+ */
+ TCameraEngineState State() const { return iEngineState; }
+
+ /**
+ * Returns true if the camera has been reserved and
+ * powered on, and not recording or capturing image
+ */
+ TBool IsCameraReady() const;
+
+ /**
+ * Returns whether DirectScreen ViewFinder is supported by the platform
+ */
+ TBool IsDirectViewFinderSupported() const;
+
+ /**
+ * Returns true if the camera supports AutoFocus.
+ */
+ TBool IsAutoFocusSupported() const;
+
+ /**
+ * Returns camera info
+ */
+ TCameraInfo *CameraInfo();
+
+ /**
+ * Captures an image. When complete, observer will receive
+ * MceoCapturedDataReady() or MceoCapturedBitmapReady() callback,
+ * depending on which image format was used in PrepareL().
+ * @leave May leave with KErrNotReady if camera is not
+ * reserved or prepared for capture.
+ */
+ void CaptureL();
+
+ /**
+ * Cancels ongoing image capture
+ */
+ void CancelCapture();
+
+ /**
+ * Reserves and powers on the camera. When complete,
+ * observer will receive MceoCameraReady() callback
+ *
+ */
+ void ReserveAndPowerOn();
+
+ /**
+ * Releases and powers off the camera
+ *
+ */
+ void ReleaseAndPowerOff();
+
+ /**
+ * Prepares for image capture.
+ * @param aCaptureSize requested capture size. On return,
+ * contains the selected size (closest match)
+ * @param aFormat Image format to use. Default is JPEG with
+ * EXIF information as provided by the camera module
+ * @leave KErrNotSupported, KErrNoMemory, KErrNotReady
+ */
+ void PrepareL( TSize& aCaptureSize,
+ CCamera::TFormat aFormat = CCamera::EFormatExif );
+
+ /**
+ * Starts the viewfinder. Observer will receive
+ * MceoViewFinderFrameReady() callbacks periodically.
+ * @param aSize requested viewfinder size. On return,
+ * contains the selected size.
+ *
+ * @leave KErrNotSupported is viewfinding with bitmaps is not
+ * supported, KErrNotReady
+ */
+ void StartViewFinderL( TSize& aSize );
+
+ /**
+ * Stops the viewfinder if active.
+ */
+ void StopViewFinder();
+
+ void StartDirectViewFinderL(RWsSession& aSession,
+ CWsScreenDevice& aScreenDevice,
+ RWindowBase& aWindow,
+ TRect& aScreenRect,
+ TRect& aClipRect);
+
+ /**
+ * Releases memory for the last received viewfinder frame.
+ * Client must call this in response to MceoViewFinderFrameReady()
+ * callback, after drawing the viewfinder frame is complete.
+ */
+ void ReleaseViewFinderBuffer();
+
+ /**
+ * Releases memory for the last captured image.
+ * Client must call this in response to MceoCapturedDataReady()
+ * or MceoCapturedBitmapReady()callback, after processing the
+ * data/bitmap is complete.
+ */
+ void ReleaseImageBuffer();
+
+ /**
+ * Starts focusing. Does nothing if AutoFocus is not supported.
+ * When complete, observer will receive MceoFocusComplete()
+ * callback.
+ * @leave KErrInUse, KErrNotReady
+ */
+ void StartFocusL();
+
+ /**
+ * Cancels the ongoing focusing operation.
+ */
+ void FocusCancel();
+
+ /**
+ * Gets a bitfield of supported focus ranges.
+ * @param aSupportedRanges a bitfield of either TAutoFocusRange
+ * (S60 3.0/3.1 devices) or TFocusRange (S60 3.2 and onwards) values
+ */
+ void SupportedFocusRanges( TInt& aSupportedRanges ) const;
+
+ /**
+ * Sets the focus range
+ * @param aFocusRange one of the values returned by
+ * SupportedFocusRanges().
+ */
+ void SetFocusRange( TInt aFocusRange );
+
+ /**
+ * Returns a pointer to CCamera object used by the engine.
+ * Allows getting access to additional functionality
+ * from CCamera - do not use for functionality already provided
+ * by CCameraEngine methods.
+ */
+ CCamera* Camera() { return iCamera; }
+
+#ifdef ECAM_PREVIEW_API
+ /**
+ * This enables the preview creation during the capture (image or video).
+ */
+ void EnablePreviewProvider(MCameraPreviewObserver *aPreviewObserver);
+
+ /**
+ * This disabled the preview creation during the capture (image or video)
+ */
+ void DisablePreviewProvider();
+#endif // ECAM_PREVIEW_API
+
+protected: // Protected constructors
+
+ CCameraEngine();
+ CCameraEngine( TInt aCameraHandle,
+ TInt aPriority,
+ MCameraEngineObserver* aObserver );
+ void ConstructL();
+
+protected: // MCameraObserver
+
+ /**
+ * From MCameraObserver
+ * Gets called when CCamera::Reserve() is completed.
+ * (V2: Called internally from HandleEvent)
+ */
+ virtual void ReserveComplete(TInt aError);
+
+ /**
+ * From MCameraObserver.
+ * Gets called when CCamera::PowerOn() is completed.
+ * (V2: Called internally from HandleEvent)
+ */
+ virtual void PowerOnComplete(TInt aError);
+
+ /**
+ * From MCameraObserver.
+ * Gets called when CCamera::StartViewFinderBitmapsL() is completed.
+ * (V2: Called internally from ViewFinderReady)
+ */
+ virtual void ViewFinderFrameReady( CFbsBitmap& aFrame );
+
+ /**
+ * From MCameraObserver.
+ * Gets called when CCamera::CaptureImage() is completed.
+ */
+ virtual void ImageReady( CFbsBitmap* aBitmap, HBufC8* aData, TInt aError );
+
+ /**
+ * From MCameraObserver.
+ * Video capture not implemented.
+ */
+ virtual void FrameBufferReady( MFrameBuffer* /*aFrameBuffer*/, TInt /*aError*/ ) {}
+
+protected: // MCameraObserver2
+
+ /**
+ * From MCameraObserver2
+ * Camera event handler
+ */
+ virtual void HandleEvent(const TECAMEvent &aEvent);
+
+ /**
+ * From MCameraObserver2
+ * Notifies the client of new viewfinder data
+ */
+ virtual void ViewFinderReady(MCameraBuffer &aCameraBuffer, TInt aError);
+
+ /**
+ * From MCameraObserver2
+ * Notifies the client of a new captured image
+ */
+ virtual void ImageBufferReady(MCameraBuffer &aCameraBuffer, TInt aError);
+
+ /**
+ * From MCameraObserver2
+ * Video capture not implemented.
+ */
+ virtual void VideoBufferReady(MCameraBuffer& /*aCameraBuffer*/, TInt /*aError*/) {}
+
+protected: // MCamAutoFocusObserver
+
+ /**
+ * From MCamAutoFocusObserver.
+ * Delivers notification of completion of auto focus initialisation to
+ * an interested party.
+ * @param aError Reason for completion of focus request.
+ */
+ virtual void InitComplete( TInt aError );
+
+ /**
+ * From MCamAutoFocusObserver.
+ * Gets called when CCamAutoFocus::AttemptOptimisedFocusL() is
+ * completed.
+ * (V2: Called internally from HandleEvent)
+ */
+ virtual void OptimisedFocusComplete( TInt aError );
+
+private: // Internal functions
+
+ /**
+ * Internal function to handle ImageReady callbacks from
+ * both observer (V1 & V2) interfaces
+ */
+ void HandleImageReady(const TInt aError, const bool isBitmap);
+
+#ifdef ECAM_PREVIEW_API
+ /**
+ * Handle preview. Retrieve preview data and notify observer about the
+ * preview availability.
+ */
+ void HandlePreview();
+
+ /**
+ * Calculate proper resolution for the SnapShot (Preview) image.
+ */
+ TSize SelectPreviewResolution();
+#endif // ECAM_PREVIEW_API
+
+private: // Data
+
+ CCamera *iCamera;
+ MCameraEngineObserver *iObserver;
+ MCameraEngineImageCaptureObserver *iImageCaptureObserver;
+ MAdvancedSettingsObserver *iAdvancedSettingsObserver;
+ MCameraViewfinderObserver *iViewfinderObserver;
+ MCameraPreviewObserver *iPreviewObserver;
+ MCameraBuffer *iViewFinderBuffer;
+ /*
+ * Following pointers are for the image buffers:
+ * * Makes buffering of 2 concurrent image buffers possible
+ */
+ MCameraBuffer *iImageBuffer1;
+ MCameraBuffer *iImageBuffer2;
+ TDesC8 *iImageData1;
+ TDesC8 *iImageData2;
+ CFbsBitmap *iImageBitmap1;
+ CFbsBitmap *iImageBitmap2;
+ TInt iCameraIndex;
+ TInt iPriority;
+ TCameraEngineState iEngineState;
+ TCameraInfo iCameraInfo;
+ CCamera::TFormat iImageCaptureFormat;
+ TSize iCaptureResolution;
+ bool iNew2LImplementation;
+ int iLatestImageBufferIndex; // 0 = Buffer1, 1 = Buffer2
+#ifdef ECAM_PREVIEW_API
+ CCamera::CCameraSnapshot *iCameraSnapshot;
+#endif // ECAM_PREVIEW_API
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT
+ CCamAutoFocus* iAutoFocus;
+ CCamAutoFocus::TAutoFocusRange iAFRange;
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+};
+
+#endif // S60CCAMERAENGINE_H
diff --git a/src/plugins/symbian/ecam/s60cameraengineobserver.h b/src/plugins/symbian/ecam/s60cameraengineobserver.h
new file mode 100644
index 000000000..b1e669d70
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraengineobserver.h
@@ -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 S60CCAMERAENGINEOBSERVER_H
+#define S60CCAMERAENGINEOBSERVER_H
+
+// FORWARD DECLARATIONS
+class CFbsBitmap;
+class TECAMEvent;
+
+enum TCameraEngineError
+{
+ EErrReserve,
+ EErrPowerOn,
+ EErrViewFinderReady,
+ EErrImageReady,
+ EErrPreview,
+ EErrAutoFocusInit,
+ EErrAutoFocusMode,
+ EErrAutoFocusArea,
+ EErrAutoFocusRange,
+ EErrAutoFocusType,
+ EErrOptimisedFocusComplete,
+};
+
+/*
+ * CameraEngine Observer class towards Camera AdvancedSettings
+ */
+class MAdvancedSettingsObserver
+{
+public:
+
+ virtual void HandleAdvancedEvent( const TECAMEvent &aEvent ) = 0;
+
+};
+
+//=============================================================================
+
+/*
+ * CameraEngine Observer class towards Camera Control
+ */
+class MCameraEngineObserver
+{
+public:
+
+ /**
+ * Camera is ready to use for capturing images.
+ */
+ virtual void MceoCameraReady() = 0;
+
+ /**
+ * Notifies clients about errors in camera engine
+ * @param aErrorType type of error (see TCameraEngineError)
+ * @param aError Symbian system-wide error code
+ */
+ virtual void MceoHandleError( TCameraEngineError aErrorType, TInt aError ) = 0;
+
+};
+
+//=============================================================================
+
+/*
+ * CameraEngine Observer class towards Camera ImageCaptureSession
+ */
+class MCameraEngineImageCaptureObserver
+{
+public:
+
+ /**
+ * Camera AF lens has attained optimal focus
+ */
+ virtual void MceoFocusComplete() = 0;
+
+ /**
+ * Captured data is ready - call CCameraEngine::ReleaseImageBuffer()
+ * after processing/saving the data (typically, JPG-encoded image)
+ * @param aData Pointer to a descriptor containing a frame of camera data.
+ */
+ virtual void MceoCapturedDataReady( TDesC8* aData ) = 0;
+
+ /**
+ * Captured bitmap is ready.
+ * after processing/saving the image, call
+ * CCameraEngine::ReleaseImageBuffer() to free the bitmap.
+ * @param aBitmap Pointer to an FBS bitmap containing a captured image.
+ */
+ virtual void MceoCapturedBitmapReady( CFbsBitmap* aBitmap ) = 0;
+
+ /**
+ * Notifies clients about errors in camera engine
+ * @param aErrorType type of error (see TCameraEngineError)
+ * @param aError Symbian system-wide error code
+ */
+ virtual void MceoHandleError( TCameraEngineError aErrorType, TInt aError ) = 0;
+
+ /**
+ * Notifies client about other events not recognized by camera engine.
+ * The default implementation is empty.
+ * @param aEvent camera event (see MCameraObserver2::HandleEvent())
+ */
+ virtual void MceoHandleOtherEvent( const TECAMEvent& /*aEvent*/ ) {}
+};
+
+//=============================================================================
+
+/*
+ * CameraEngine Observer class towards Camera ViewFinderEngine
+ */
+class MCameraViewfinderObserver
+{
+public:
+ /**
+ * A new viewfinder frame is ready.
+ * after displaying the frame, call
+ * CCameraEngine::ReleaseViewFinderBuffer()
+ * to free the bitmap.
+ * @param aFrame Pointer to an FBS bitmap containing a viewfinder frame.
+ */
+ virtual void MceoViewFinderFrameReady( CFbsBitmap& aFrame ) = 0;
+};
+
+//=============================================================================
+
+#ifdef ECAM_PREVIEW_API
+/*
+ * CameraEngine Observer class towards Camera ViewFinderEngine
+ */
+class MCameraPreviewObserver
+{
+public:
+ /**
+ * A new preview is available.
+ * @param aPreview Pointer to an FBS bitmap containing a preview.
+ */
+ virtual void MceoPreviewReady( CFbsBitmap& aPreview ) = 0;
+};
+#endif // ECAM_PREVIEW_API
+
+#endif // CCAMERAENGINEOBSERVER_H
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraexposurecontrol.cpp b/src/plugins/symbian/ecam/s60cameraexposurecontrol.cpp
new file mode 100644
index 000000000..9ebdd2c6e
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraexposurecontrol.cpp
@@ -0,0 +1,584 @@
+/****************************************************************************
+**
+** 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 <QtCore/qstring.h>
+
+#include "s60cameraexposurecontrol.h"
+#include "s60cameraservice.h"
+#include "s60imagecapturesession.h"
+
+S60CameraExposureControl::S60CameraExposureControl(QObject *parent) :
+ QCameraExposureControl(parent)
+{
+}
+
+S60CameraExposureControl::S60CameraExposureControl(S60ImageCaptureSession *session, QObject *parent) :
+ QCameraExposureControl(parent),
+ m_session(0),
+ m_service(0),
+ m_advancedSettings(0),
+ m_exposureMode(QCameraExposure::ExposureAuto),
+ m_meteringMode(QCameraExposure::MeteringMatrix)
+{
+ m_session = session;
+
+ connect(m_session, SIGNAL(advancedSettingChanged()), this, SLOT(resetAdvancedSetting()));
+ m_advancedSettings = m_session->advancedSettings();
+
+ if (m_advancedSettings) {
+ connect(m_advancedSettings, SIGNAL(apertureChanged()), this, SLOT(apertureChanged()));
+ connect(m_advancedSettings, SIGNAL(apertureRangeChanged()), this, SLOT(apertureRangeChanged()));
+ connect(m_advancedSettings, SIGNAL(shutterSpeedChanged()), this, SLOT(shutterSpeedChanged()));
+ connect(m_advancedSettings, SIGNAL(isoSensitivityChanged()), this, SLOT(isoSensitivityChanged()));
+ connect(m_advancedSettings, SIGNAL(evChanged()), this, SLOT(evChanged()));
+ }
+}
+
+S60CameraExposureControl::~S60CameraExposureControl()
+{
+ m_advancedSettings = 0;
+}
+
+void S60CameraExposureControl::resetAdvancedSetting()
+{
+ m_advancedSettings = m_session->advancedSettings();
+ if (m_advancedSettings) {
+ connect(m_advancedSettings, SIGNAL(apertureChanged()), this, SLOT(apertureChanged()));
+ connect(m_advancedSettings, SIGNAL(apertureRangeChanged()), this, SLOT(apertureRangeChanged()));
+ connect(m_advancedSettings, SIGNAL(shutterSpeedChanged()), this, SLOT(shutterSpeedChanged()));
+ connect(m_advancedSettings, SIGNAL(isoSensitivityChanged()), this, SLOT(isoSensitivityChanged()));
+ connect(m_advancedSettings, SIGNAL(evChanged()), this, SLOT(evChanged()));
+ }
+}
+
+void S60CameraExposureControl::apertureChanged()
+{
+ emit exposureParameterChanged(QCameraExposureControl::Aperture);
+}
+
+void S60CameraExposureControl::apertureRangeChanged()
+{
+ emit exposureParameterRangeChanged(QCameraExposureControl::Aperture);
+}
+
+void S60CameraExposureControl::shutterSpeedChanged()
+{
+ emit exposureParameterChanged(QCameraExposureControl::ShutterSpeed);
+}
+
+void S60CameraExposureControl::isoSensitivityChanged()
+{
+ emit exposureParameterChanged(QCameraExposureControl::ISO);
+}
+
+void S60CameraExposureControl::evChanged()
+{
+ emit exposureParameterChanged(QCameraExposureControl::ExposureCompensation);
+}
+
+QCameraExposure::ExposureMode S60CameraExposureControl::exposureMode() const
+{
+ return m_session->exposureMode();
+}
+
+void S60CameraExposureControl::setExposureMode(QCameraExposure::ExposureMode mode)
+{
+ if (isExposureModeSupported(mode)) {
+ m_exposureMode = mode;
+ m_session->setExposureMode(m_exposureMode);
+ return;
+ }
+
+ m_session->setError(KErrNotSupported, tr("Requested exposure mode is not supported."));
+}
+
+bool S60CameraExposureControl::isExposureModeSupported(QCameraExposure::ExposureMode mode) const
+{
+ if (m_session->isExposureModeSupported(mode))
+ return true;
+
+ return false;
+}
+
+QCameraExposure::MeteringMode S60CameraExposureControl::meteringMode() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->meteringMode();
+
+ return QCameraExposure::MeteringMode();
+}
+
+void S60CameraExposureControl::setMeteringMode(QCameraExposure::MeteringMode mode)
+{
+ if (m_advancedSettings) {
+ if (isMeteringModeSupported(mode)) {
+ m_meteringMode = mode;
+ m_advancedSettings->setMeteringMode(mode);
+ return;
+ }
+ }
+
+ m_session->setError(KErrNotSupported, tr("Requested metering mode is not supported."));
+}
+
+bool S60CameraExposureControl::isMeteringModeSupported(QCameraExposure::MeteringMode mode) const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->isMeteringModeSupported(mode);
+
+ return false;
+}
+
+bool S60CameraExposureControl::isParameterSupported(ExposureParameter parameter) const
+{
+ // Settings supported only if advanced settings available
+ if (m_advancedSettings) {
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ if (m_advancedSettings->supportedIsoSensitivities().count() > 0)
+ return true;
+ else
+ return false;
+ case QCameraExposureControl::Aperture:
+ if (m_advancedSettings->supportedApertures().count() > 0)
+ return true;
+ else
+ return false;
+ case QCameraExposureControl::ShutterSpeed:
+ if (m_advancedSettings->supportedShutterSpeeds().count() > 0)
+ return true;
+ else
+ return false;
+ case QCameraExposureControl::ExposureCompensation:
+ if (m_advancedSettings->supportedExposureCompensationValues().count() > 0)
+ return true;
+ else
+ return false;
+ case QCameraExposureControl::FlashPower:
+ case QCameraExposureControl::FlashCompensation:
+ return false;
+
+ default:
+ return false;
+ }
+ }
+
+ return false;
+}
+
+QVariant S60CameraExposureControl::exposureParameter(ExposureParameter parameter) const
+{
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ return QVariant(isoSensitivity());
+ case QCameraExposureControl::Aperture:
+ return QVariant(aperture());
+ case QCameraExposureControl::ShutterSpeed:
+ return QVariant(shutterSpeed());
+ case QCameraExposureControl::ExposureCompensation:
+ return QVariant(exposureCompensation());
+ case QCameraExposureControl::FlashPower:
+ case QCameraExposureControl::FlashCompensation:
+ // Not supported in Symbian
+ return QVariant();
+
+ default:
+ // Not supported in Symbian
+ return QVariant();
+ }
+}
+
+QCameraExposureControl::ParameterFlags S60CameraExposureControl::exposureParameterFlags(ExposureParameter parameter) const
+{
+ QCameraExposureControl::ParameterFlags flags;
+
+ /*
+ * ISO, ExposureCompensation:
+ * - Automatic/Manual
+ * - Read/Write
+ * - Discrete range
+ *
+ * Aperture, ShutterSpeed, FlashPower, FlashCompensation:
+ * - Not supported
+ */
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ case QCameraExposureControl::ExposureCompensation:
+ flags |= QCameraExposureControl::AutomaticValue;
+ break;
+ case QCameraExposureControl::Aperture:
+ case QCameraExposureControl::ShutterSpeed:
+ case QCameraExposureControl::FlashPower:
+ case QCameraExposureControl::FlashCompensation:
+ // Do nothing - no flags
+ break;
+
+ default:
+ // Do nothing - no flags
+ break;
+ }
+
+ return flags;
+}
+
+QVariantList S60CameraExposureControl::supportedParameterRange(ExposureParameter parameter) const
+{
+ QVariantList valueList;
+
+ if (m_advancedSettings) {
+ switch (parameter) {
+ case QCameraExposureControl::ISO: {
+ foreach (int iso, m_advancedSettings->supportedIsoSensitivities())
+ valueList << QVariant(iso);
+ break;
+ }
+ case QCameraExposureControl::Aperture: {
+ foreach (qreal aperture, m_advancedSettings->supportedApertures())
+ valueList << QVariant(aperture);
+ break;
+ }
+ case QCameraExposureControl::ShutterSpeed: {
+ foreach (qreal shutterSpeed, m_advancedSettings->supportedShutterSpeeds())
+ valueList << QVariant(shutterSpeed);
+ break;
+ }
+ case QCameraExposureControl::ExposureCompensation: {
+ foreach (qreal ev, m_advancedSettings->supportedExposureCompensationValues())
+ valueList << QVariant(ev);
+ break;
+ }
+ case QCameraExposureControl::FlashPower:
+ case QCameraExposureControl::FlashCompensation:
+ // Not supported in Symbian
+ break;
+
+ default:
+ // Not supported in Symbian
+ break;
+ }
+ }
+
+ return valueList;
+}
+
+bool S60CameraExposureControl::setExposureParameter(ExposureParameter parameter, const QVariant& value)
+{
+ bool useDefaultValue = false;
+
+ if (value.isNull())
+ useDefaultValue = true;
+
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ if (useDefaultValue) {
+ setAutoIsoSensitivity();
+ return false;
+ }
+ else
+ return setManualIsoSensitivity(value.toInt());
+
+ case QCameraExposureControl::Aperture:
+ if (useDefaultValue) {
+ setAutoAperture();
+ return false;
+ }
+ else
+ return setManualAperture(value.toFloat());
+
+ case QCameraExposureControl::ShutterSpeed:
+ if (useDefaultValue) {
+ setAutoShutterSpeed();
+ return false;
+ }
+ else
+ return setManualShutterSpeed(value.toFloat());
+
+ case QCameraExposureControl::ExposureCompensation:
+ if (useDefaultValue) {
+ setAutoExposureCompensation();
+ return false;
+ }
+ else
+ return setManualExposureCompensation(value.toFloat());
+
+ case QCameraExposureControl::FlashPower:
+ return false;
+ case QCameraExposureControl::FlashCompensation:
+ return false;
+
+ default:
+ // Not supported in Symbian
+ return false;
+ }
+}
+
+QString S60CameraExposureControl::extendedParameterName(ExposureParameter parameter)
+{
+ switch (parameter) {
+ case QCameraExposureControl::ISO:
+ return QLatin1String("ISO Sensitivity");
+ case QCameraExposureControl::Aperture:
+ return QLatin1String("Aperture");
+ case QCameraExposureControl::ShutterSpeed:
+ return QLatin1String("Shutter Speed");
+ case QCameraExposureControl::ExposureCompensation:
+ return QLatin1String("Exposure Compensation");
+ case QCameraExposureControl::FlashPower:
+ return QLatin1String("Flash Power");
+ case QCameraExposureControl::FlashCompensation:
+ return QLatin1String("Flash Compensation");
+
+ default:
+ return QString();
+ }
+}
+
+int S60CameraExposureControl::isoSensitivity() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->isoSensitivity();
+ return 0;
+}
+
+bool S60CameraExposureControl::isIsoSensitivitySupported(const int iso) const
+{
+ if (m_advancedSettings &&
+ m_advancedSettings->supportedIsoSensitivities().contains(iso))
+ return true;
+ else
+ return false;
+}
+
+bool S60CameraExposureControl::setManualIsoSensitivity(int iso)
+{
+ if (m_advancedSettings) {
+ if (isIsoSensitivitySupported(iso)) {
+ m_advancedSettings->setManualIsoSensitivity(iso);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void S60CameraExposureControl::setAutoIsoSensitivity()
+{
+ if (m_advancedSettings)
+ m_advancedSettings->setAutoIsoSensitivity();
+}
+
+qreal S60CameraExposureControl::aperture() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->aperture();
+ return 0.0;
+}
+
+bool S60CameraExposureControl::isApertureSupported(const qreal aperture) const
+{
+ if (m_advancedSettings) {
+ QList<qreal> supportedValues = m_advancedSettings->supportedApertures();
+ if(supportedValues.indexOf(aperture) != -1)
+ return true;
+ }
+
+ return false;
+}
+
+bool S60CameraExposureControl::setManualAperture(qreal aperture)
+{
+ if (m_advancedSettings) {
+ if (isApertureSupported(aperture)) {
+ m_advancedSettings->setManualAperture(aperture);
+ return true;
+ } else {
+ QList<qreal> supportedApertureValues = m_advancedSettings->supportedApertures();
+ int minAperture = supportedApertureValues.first();
+ int maxAperture = supportedApertureValues.last();
+
+ if (aperture < minAperture) { // Smaller than minimum
+ aperture = minAperture;
+ } else if (aperture > maxAperture) { // Bigger than maximum
+ aperture = maxAperture;
+ } else { // Find closest
+ int indexOfClosest = 0;
+ int smallestDiff = 100000000; // Sensible max diff
+ for(int i = 0; i < supportedApertureValues.count(); ++i) {
+ if((abs((aperture*100) - (supportedApertureValues[i]*100))) < smallestDiff) {
+ smallestDiff = abs((aperture*100) - (supportedApertureValues[i]*100));
+ indexOfClosest = i;
+ }
+ }
+ aperture = supportedApertureValues[indexOfClosest];
+ }
+ m_advancedSettings->setManualAperture(aperture);
+ }
+ }
+
+ return false;
+}
+
+void S60CameraExposureControl::setAutoAperture()
+{
+ // Not supported in Symbian
+}
+
+qreal S60CameraExposureControl::shutterSpeed() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->shutterSpeed();
+ return 0.0;
+}
+
+bool S60CameraExposureControl::isShutterSpeedSupported(const qreal seconds) const
+{
+ if (m_advancedSettings) {
+ QList<qreal> supportedValues = m_advancedSettings->supportedShutterSpeeds();
+ if(supportedValues.indexOf(seconds) != -1)
+ return true;
+ }
+
+ return false;
+}
+
+bool S60CameraExposureControl::setManualShutterSpeed(qreal seconds)
+{
+ if (m_advancedSettings) {
+ if (isShutterSpeedSupported(seconds)) {
+ m_advancedSettings->setManualShutterSpeed(seconds);
+ return true;
+ } else {
+ QList<qreal> supportedShutterSpeeds = m_advancedSettings->supportedShutterSpeeds();
+
+ if (supportedShutterSpeeds.count() == 0)
+ return false;
+
+ int minShutterSpeed = supportedShutterSpeeds.first();
+ int maxShutterSpeed = supportedShutterSpeeds.last();
+
+ if (seconds < minShutterSpeed) { // Smaller than minimum
+ seconds = minShutterSpeed;
+ } else if (seconds > maxShutterSpeed) { // Bigger than maximum
+ seconds = maxShutterSpeed;
+ } else { // Find closest
+ int indexOfClosest = 0;
+ int smallestDiff = 100000000; // Sensible max diff
+ for(int i = 0; i < supportedShutterSpeeds.count(); ++i) {
+ if((abs((seconds*100) - (supportedShutterSpeeds[i]*100))) < smallestDiff) {
+ smallestDiff = abs((seconds*100) - (supportedShutterSpeeds[i]*100));
+ indexOfClosest = i;
+ }
+ }
+ seconds = supportedShutterSpeeds[indexOfClosest];
+ }
+ m_advancedSettings->setManualShutterSpeed(seconds);
+ }
+ }
+
+ return false;
+}
+
+void S60CameraExposureControl::setAutoShutterSpeed()
+{
+ // Not supported in Symbian
+}
+
+qreal S60CameraExposureControl::exposureCompensation() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->exposureCompensation();
+ return 0.0;
+}
+
+bool S60CameraExposureControl::isExposureCompensationSupported(const qreal ev) const
+{
+ if (m_advancedSettings) {
+ QList<qreal> supportedValues = m_advancedSettings->supportedExposureCompensationValues();
+ if(supportedValues.indexOf(ev) != -1)
+ return true;
+ }
+
+ return false;
+}
+
+bool S60CameraExposureControl::setManualExposureCompensation(qreal ev)
+{
+ if (m_advancedSettings) {
+ if (isExposureCompensationSupported(ev)) {
+ m_advancedSettings->setExposureCompensation(ev);
+ return true;
+ } else {
+ QList<qreal> supportedEVs = m_advancedSettings->supportedExposureCompensationValues();
+
+ if (supportedEVs.count() == 0)
+ return false;
+
+ int minEV = supportedEVs.first();
+ int maxEV = supportedEVs.last();
+
+ if (ev < minEV) { // Smaller than minimum
+ ev = minEV;
+ } else if (ev > maxEV) { // Bigger than maximum
+ ev = maxEV;
+ } else { // Find closest
+ int indexOfClosest = 0;
+ int smallestDiff = 100000000; // Sensible max diff
+ for(int i = 0; i < supportedEVs.count(); ++i) {
+ if((abs((ev*100) - (supportedEVs[i]*100))) < smallestDiff) {
+ smallestDiff = abs((ev*100) - (supportedEVs[i]*100));
+ indexOfClosest = i;
+ }
+ }
+ ev = supportedEVs[indexOfClosest];
+ }
+ m_advancedSettings->setExposureCompensation(ev);
+ }
+ }
+
+ return false;
+}
+
+void S60CameraExposureControl::setAutoExposureCompensation()
+{
+ // Not supported in Symbian
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraexposurecontrol.h b/src/plugins/symbian/ecam/s60cameraexposurecontrol.h
new file mode 100644
index 000000000..1c623c774
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraexposurecontrol.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** 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 S60CAMERAEXPOSURECONTROL_H
+#define S60CAMERAEXPOSURECONTROL_H
+
+#include <qcameraexposurecontrol.h>
+
+#include "s60camerasettings.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+
+/*
+ * Control for exposure related camera operation.
+ */
+class S60CameraExposureControl : public QCameraExposureControl
+{
+ Q_OBJECT
+
+public: // Constructors & Destructor
+
+ S60CameraExposureControl(QObject *parent = 0);
+ S60CameraExposureControl(S60ImageCaptureSession *session, QObject *parent = 0);
+ ~S60CameraExposureControl();
+
+public: // QCameraExposureControl
+
+ // Exposure Mode
+ QCameraExposure::ExposureMode exposureMode() const;
+ void setExposureMode(QCameraExposure::ExposureMode mode);
+ bool isExposureModeSupported(QCameraExposure::ExposureMode mode) const;
+
+ // Metering Mode
+ QCameraExposure::MeteringMode meteringMode() const;
+ void setMeteringMode(QCameraExposure::MeteringMode mode);
+ bool isMeteringModeSupported(QCameraExposure::MeteringMode mode) const;
+
+ // Exposure Parameter
+ bool isParameterSupported(ExposureParameter parameter) const;
+ QVariant exposureParameter(ExposureParameter parameter) const;
+ QCameraExposureControl::ParameterFlags exposureParameterFlags(ExposureParameter parameter) const;
+ QVariantList supportedParameterRange(ExposureParameter parameter) const;
+ bool setExposureParameter(ExposureParameter parameter, const QVariant& value);
+
+ QString extendedParameterName(ExposureParameter parameter);
+
+/*
+Q_SIGNALS: // QCameraExposureControl
+ void exposureParameterChanged(int parameter);
+ void exposureParameterRangeChanged(int parameter);
+*/
+
+private slots: // Internal Slots
+
+ void resetAdvancedSetting();
+ void apertureChanged();
+ void apertureRangeChanged();
+ void shutterSpeedChanged();
+ void isoSensitivityChanged();
+ void evChanged();
+
+private: // Internal - Implementing ExposureParameter
+
+ // ISO Sensitivity
+ int isoSensitivity() const;
+ bool setManualIsoSensitivity(int iso);
+ void setAutoIsoSensitivity();
+ bool isIsoSensitivitySupported(const int iso) const;
+
+ // Aperture
+ qreal aperture() const;
+ bool setManualAperture(qreal aperture);
+ void setAutoAperture();
+ bool isApertureSupported(const qreal aperture) const;
+
+ // Shutter Speed
+ qreal shutterSpeed() const;
+ bool setManualShutterSpeed(qreal seconds);
+ void setAutoShutterSpeed();
+ bool isShutterSpeedSupported(const qreal seconds) const;
+
+ // Exposure Compensation
+ qreal exposureCompensation() const;
+ bool setManualExposureCompensation(qreal ev);
+ void setAutoExposureCompensation();
+ bool isExposureCompensationSupported(const qreal ev) const;
+
+private: // Data
+
+ S60ImageCaptureSession *m_session;
+ S60CameraService *m_service;
+ S60CameraSettings *m_advancedSettings;
+ QCameraExposure::ExposureMode m_exposureMode;
+ QCameraExposure::MeteringMode m_meteringMode;
+};
+
+#endif // S60CAMERAEXPOSURECONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameraflashcontrol.cpp b/src/plugins/symbian/ecam/s60cameraflashcontrol.cpp
new file mode 100644
index 000000000..a18c57a03
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraflashcontrol.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** 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 <QtCore/qstring.h>
+
+#include "s60cameraflashcontrol.h"
+#include "s60cameraservice.h"
+#include "s60imagecapturesession.h"
+
+S60CameraFlashControl::S60CameraFlashControl(QObject *parent) :
+ QCameraFlashControl(parent)
+{
+}
+
+S60CameraFlashControl::S60CameraFlashControl(S60ImageCaptureSession *session, QObject *parent) :
+ QCameraFlashControl(parent),
+ m_session(0),
+ m_service(0),
+ m_advancedSettings(0),
+ m_flashMode(QCameraExposure::FlashOff)
+{
+ m_session = session;
+
+ connect(m_session, SIGNAL(advancedSettingChanged()), this, SLOT(resetAdvancedSetting()));
+ m_advancedSettings = m_session->advancedSettings();
+
+ if (m_advancedSettings)
+ connect(m_advancedSettings, SIGNAL(flashReady(bool)), this, SIGNAL(flashReady(bool)));
+}
+
+S60CameraFlashControl::~S60CameraFlashControl()
+{
+ m_advancedSettings = 0;
+}
+
+void S60CameraFlashControl::resetAdvancedSetting()
+{
+ m_advancedSettings = m_session->advancedSettings();
+ if (m_advancedSettings)
+ connect(m_advancedSettings, SIGNAL(flashReady(bool)), this, SIGNAL(flashReady(bool)));
+}
+
+QCameraExposure::FlashModes S60CameraFlashControl::flashMode() const
+{
+ return m_session->flashMode();
+}
+
+void S60CameraFlashControl::setFlashMode(QCameraExposure::FlashModes mode)
+{
+ if (isFlashModeSupported(mode)) {
+ m_flashMode = mode;
+ m_session->setFlashMode(m_flashMode);
+ }
+ else
+ m_session->setError(KErrNotSupported, tr("Requested flash mode is not supported."));
+}
+
+bool S60CameraFlashControl::isFlashModeSupported(QCameraExposure::FlashModes mode) const
+{
+ return m_session->supportedFlashModes() & mode;
+}
+
+bool S60CameraFlashControl::isFlashReady() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->isFlashReady();
+
+ return false;
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraflashcontrol.h b/src/plugins/symbian/ecam/s60cameraflashcontrol.h
new file mode 100644
index 000000000..50dbc41dc
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraflashcontrol.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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 S60CAMERAFLASHCONTROL_H
+#define S60CAMERAFLASHCONTROL_H
+
+#include <qcameraflashcontrol.h>
+
+#include "s60camerasettings.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+
+/*
+ * Control to setup Flash related camera settings.
+ */
+class S60CameraFlashControl : public QCameraFlashControl
+{
+ Q_OBJECT
+
+public: // Constructors & Destructor
+
+ S60CameraFlashControl(QObject *parent = 0);
+ S60CameraFlashControl(S60ImageCaptureSession *session, QObject *parent = 0);
+ ~S60CameraFlashControl();
+
+public: // QCameraExposureControl
+
+ // Flash Mode
+ QCameraExposure::FlashModes flashMode() const;
+ void setFlashMode(QCameraExposure::FlashModes mode);
+ bool isFlashModeSupported(QCameraExposure::FlashModes mode) const;
+
+ bool isFlashReady() const;
+
+/*
+Q_SIGNALS: // QCameraExposureControl
+ void flashReady(bool);
+*/
+
+private slots: // Internal Slots
+
+ void resetAdvancedSetting();
+
+private: // Data
+
+ S60ImageCaptureSession *m_session;
+ S60CameraService *m_service;
+ S60CameraSettings *m_advancedSettings;
+ QCameraExposure::FlashModes m_flashMode;
+};
+
+#endif // S60CAMERAFLASHCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60camerafocuscontrol.cpp b/src/plugins/symbian/ecam/s60camerafocuscontrol.cpp
new file mode 100644
index 000000000..a7941ce20
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60camerafocuscontrol.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** 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 <QtCore/qstring.h>
+
+#include "s60camerafocuscontrol.h"
+#include "s60cameraservice.h"
+#include "s60imagecapturesession.h"
+#include "s60cameraconstants.h"
+
+S60CameraFocusControl::S60CameraFocusControl(QObject *parent) :
+ QCameraFocusControl(parent)
+{
+}
+
+S60CameraFocusControl::S60CameraFocusControl(S60ImageCaptureSession *session, QObject *parent) :
+ QCameraFocusControl(parent),
+ m_session(0),
+ m_service(0),
+ m_advancedSettings(0),
+ m_isFocusLocked(false),
+ m_opticalZoomValue(KDefaultOpticalZoom),
+ m_digitalZoomValue(KDefaultDigitalZoom),
+ m_focusMode(KDefaultFocusMode)
+{
+ m_session = session;
+
+ connect(m_session, SIGNAL(advancedSettingChanged()), this, SLOT(resetAdvancedSetting()));
+ m_advancedSettings = m_session->advancedSettings();
+
+ TRAPD(err, m_session->doSetZoomFactorL(m_opticalZoomValue, m_digitalZoomValue));
+ if (err)
+ m_session->setError(KErrNotSupported, tr("Setting default zoom factors failed."));
+}
+
+S60CameraFocusControl::~S60CameraFocusControl()
+{
+}
+
+QCameraFocus::FocusMode S60CameraFocusControl::focusMode() const
+{
+ return m_focusMode;
+}
+
+void S60CameraFocusControl::setFocusMode(QCameraFocus::FocusMode mode)
+{
+ if (isFocusModeSupported(mode)) {
+ // FocusMode and FocusRange are set. Focusing is triggered by setting
+ // the corresponding FocusType active by calling searchAndLock in LocksControl.
+ m_focusMode = mode;
+ if (m_advancedSettings)
+ m_advancedSettings->setFocusMode(m_focusMode);
+ else
+ m_session->setError(KErrGeneral, tr("Unable to set focus mode before camera is started."));
+ } else {
+ m_session->setError(KErrNotSupported, tr("Requested focus mode is not supported."));
+ }
+}
+
+bool S60CameraFocusControl::isFocusModeSupported(QCameraFocus::FocusMode mode) const
+{
+ if (m_advancedSettings) {
+ return m_advancedSettings->supportedFocusModes() & mode;
+ } else {
+ if (mode == QCameraFocus::AutoFocus)
+ return m_session->isFocusSupported();
+ }
+
+ return false;
+}
+
+qreal S60CameraFocusControl::maximumOpticalZoom() const
+{
+ return m_session->maximumZoom();
+}
+
+qreal S60CameraFocusControl::maximumDigitalZoom() const
+{
+ return m_session->maxDigitalZoom();
+}
+
+qreal S60CameraFocusControl::opticalZoom() const
+{
+ return m_session->opticalZoomFactor();
+}
+
+qreal S60CameraFocusControl::digitalZoom() const
+{
+ return m_session->digitalZoomFactor();
+}
+
+void S60CameraFocusControl::zoomTo(qreal optical, qreal digital)
+{
+ TRAPD(err, m_session->doSetZoomFactorL(optical, digital));
+ if (err)
+ m_session->setError(KErrNotSupported, tr("Requested zoom factor is not supported."));
+
+ // Query new values
+ if (m_opticalZoomValue != m_session->opticalZoomFactor()) {
+ m_opticalZoomValue = m_session->opticalZoomFactor();
+ emit opticalZoomChanged(m_opticalZoomValue);
+ }
+ if (m_digitalZoomValue != m_session->digitalZoomFactor()) {
+ m_digitalZoomValue = m_session->digitalZoomFactor();
+ emit digitalZoomChanged(m_digitalZoomValue);
+ }
+}
+
+void S60CameraFocusControl::resetAdvancedSetting()
+{
+ m_advancedSettings = m_session->advancedSettings();
+}
+
+QCameraFocus::FocusPointMode S60CameraFocusControl::focusPointMode() const
+{
+ // Not supported in Symbian
+ return QCameraFocus::FocusPointAuto;
+}
+
+void S60CameraFocusControl::setFocusPointMode(QCameraFocus::FocusPointMode mode)
+{
+ if (mode != QCameraFocus::FocusPointAuto)
+ m_session->setError(KErrNotSupported, tr("Requested focus point mode is not supported."));
+}
+
+bool S60CameraFocusControl::isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
+{
+ // Not supported in Symbian
+ if (mode == QCameraFocus::FocusPointAuto)
+ return true;
+ else
+ return false;
+}
+
+QPointF S60CameraFocusControl::customFocusPoint() const
+{
+ // Not supported in Symbian, return image center
+ return QPointF(0.5, 0.5);
+}
+
+void S60CameraFocusControl::setCustomFocusPoint(const QPointF &point)
+{
+ // Not supported in Symbian
+ Q_UNUSED(point);
+ m_session->setError(KErrNotSupported, tr("Setting custom focus point is not supported."));
+}
+
+QCameraFocusZoneList S60CameraFocusControl::focusZones() const
+{
+ // Not supported in Symbian
+ return QCameraFocusZoneList(); // Return empty list
+}
+
+// End of file
+
diff --git a/src/plugins/symbian/ecam/s60camerafocuscontrol.h b/src/plugins/symbian/ecam/s60camerafocuscontrol.h
new file mode 100644
index 000000000..28c83ed70
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60camerafocuscontrol.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** 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 S60CAMERAFOCUSCONTROL_H
+#define S60CAMERAFOCUSCONTROL_H
+
+#include <qcamerafocuscontrol.h>
+
+#include "s60camerasettings.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+
+/*
+ * Control for focusing related operations (inc. zooming)
+ */
+class S60CameraFocusControl : public QCameraFocusControl
+{
+ Q_OBJECT
+
+public: // Constructors & Destructor
+
+ S60CameraFocusControl(QObject *parent = 0);
+ S60CameraFocusControl(S60ImageCaptureSession *session, QObject *parent = 0);
+ ~S60CameraFocusControl();
+
+public: // QCameraFocusControl
+
+ // Focus Mode
+ QCameraFocus::FocusMode focusMode() const;
+ void setFocusMode(QCameraFocus::FocusMode mode);
+ bool isFocusModeSupported(QCameraFocus::FocusMode) const;
+
+ // Zoom
+ qreal maximumOpticalZoom() const;
+ qreal maximumDigitalZoom() const;
+ qreal opticalZoom() const;
+ qreal digitalZoom() const;
+
+ void zoomTo(qreal optical, qreal digital);
+
+ // Focus Point
+ QCameraFocus::FocusPointMode focusPointMode() const;
+ void setFocusPointMode(QCameraFocus::FocusPointMode mode);
+ bool isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const;
+ QPointF customFocusPoint() const;
+ void setCustomFocusPoint(const QPointF &point);
+
+ QCameraFocusZoneList focusZones() const;
+
+/*
+Q_SIGNALS: // QCameraFocusControl
+ void opticalZoomChanged(qreal opticalZoom);
+ void digitalZoomChanged(qreal digitalZoom);
+ void focusZonesChanged();
+*/
+
+private slots: // Internal Slots
+
+ void resetAdvancedSetting();
+
+private: // Data
+ S60ImageCaptureSession *m_session;
+ S60CameraService *m_service;
+ S60CameraSettings *m_advancedSettings;
+ bool m_isFocusLocked;
+ qreal m_opticalZoomValue;
+ qreal m_digitalZoomValue;
+ QCameraFocus::FocusMode m_focusMode;
+};
+
+#endif // S60CAMERAFOCUSCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameraimagecapturecontrol.cpp b/src/plugins/symbian/ecam/s60cameraimagecapturecontrol.cpp
new file mode 100644
index 000000000..427a3bd97
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraimagecapturecontrol.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <QtCore/qstring.h>
+
+#include "s60cameraimagecapturecontrol.h"
+#include "s60cameraservice.h"
+#include "s60imagecapturesession.h"
+#include "s60cameracontrol.h"
+
+S60CameraImageCaptureControl::S60CameraImageCaptureControl(QObject *parent) :
+ QCameraImageCaptureControl(parent)
+{
+}
+
+S60CameraImageCaptureControl::S60CameraImageCaptureControl(S60CameraService *service,
+ S60ImageCaptureSession *session,
+ QObject *parent) :
+ QCameraImageCaptureControl(parent),
+ m_driveMode(QCameraImageCapture::SingleImageCapture) // Default DriveMode
+{
+ m_session = session;
+ m_service = service;
+ m_cameraControl = qobject_cast<S60CameraControl *>(m_service->requestControl(QCameraControl_iid));
+
+ if (!m_cameraControl)
+ m_session->setError(KErrGeneral, tr("Unexpected camera error."));
+
+ // Chain these signals from session class
+ connect(m_session, SIGNAL(imageCaptured(const int, QImage)),
+ this, SIGNAL(imageCaptured(const int, QImage)));
+ connect(m_session, SIGNAL(readyForCaptureChanged(bool)),
+ this, SIGNAL(readyForCaptureChanged(bool)), Qt::QueuedConnection);
+ connect(m_session, SIGNAL(imageSaved(const int, const QString&)),
+ this, SIGNAL(imageSaved(const int, const QString&)));
+ connect(m_session, SIGNAL(imageExposed(int)),
+ this, SIGNAL(imageExposed(int)));
+ connect(m_session, SIGNAL(captureError(int, int, const QString&)),
+ this, SIGNAL(error(int, int, const QString&)));
+}
+
+S60CameraImageCaptureControl::~S60CameraImageCaptureControl()
+{
+}
+
+bool S60CameraImageCaptureControl::isReadyForCapture() const
+{
+ if (m_cameraControl && m_cameraControl->captureMode() != QCamera::CaptureStillImage)
+ return false;
+
+ return m_session->isDeviceReady();
+}
+
+QCameraImageCapture::DriveMode S60CameraImageCaptureControl::driveMode() const
+{
+ return m_driveMode;
+}
+
+void S60CameraImageCaptureControl::setDriveMode(QCameraImageCapture::DriveMode mode)
+{
+ if (mode != QCameraImageCapture::SingleImageCapture) {
+ emit error((m_session->currentImageId() + 1), QCamera::NotSupportedFeatureError, tr("DriveMode not supported."));
+ return;
+ }
+
+ m_driveMode = mode;
+}
+
+int S60CameraImageCaptureControl::capture(const QString &fileName)
+{
+ if (m_cameraControl && m_cameraControl->captureMode() != QCamera::CaptureStillImage) {
+ emit error((m_session->currentImageId() + 1), QCameraImageCapture::NotReadyError, tr("Incorrect CaptureMode."));
+ return 0;
+ }
+
+ int imageId = m_session->capture(fileName);
+
+ return imageId;
+}
+
+void S60CameraImageCaptureControl::cancelCapture()
+{
+ m_session->cancelCapture();
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraimagecapturecontrol.h b/src/plugins/symbian/ecam/s60cameraimagecapturecontrol.h
new file mode 100644
index 000000000..4c369e807
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraimagecapturecontrol.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 S60CAMERAIMAGECAPTURECONTROL_H
+#define S60CAMERAIMAGECAPTURECONTROL_H
+
+#include "qcameraimagecapturecontrol.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+class S60CameraControl;
+
+/*
+ * Control for image capture operations.
+ */
+class S60CameraImageCaptureControl : public QCameraImageCaptureControl
+{
+ Q_OBJECT
+
+public: // Contructors & Destrcutor
+
+ S60CameraImageCaptureControl(QObject *parent = 0);
+ S60CameraImageCaptureControl(S60CameraService *service,
+ S60ImageCaptureSession *session,
+ QObject *parent = 0);
+ ~S60CameraImageCaptureControl();
+
+public: // QCameraImageCaptureControl
+
+ bool isReadyForCapture() const;
+
+ // Drive Mode
+ QCameraImageCapture::DriveMode driveMode() const;
+ void setDriveMode(QCameraImageCapture::DriveMode mode);
+
+ // Capture
+ int capture(const QString &fileName);
+ void cancelCapture();
+
+/*
+Q_SIGNALS: // QCameraImageCaptureControl
+ void readyForCaptureChanged(bool);
+
+ void imageExposed(int id);
+ void imageCaptured(int id, const QImage &preview);
+ void imageSaved(int id, const QString &fileName);
+
+ void error(int id, int error, const QString &errorString);
+*/
+
+private: // Data
+
+ S60ImageCaptureSession *m_session;
+ S60CameraService *m_service;
+ S60CameraControl *m_cameraControl;
+ QCameraImageCapture::DriveMode m_driveMode;
+};
+
+#endif // S60CAMERAIMAGECAPTURECONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.cpp b/src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.cpp
new file mode 100644
index 000000000..ae2c4535a
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** 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 <QtCore/qstring.h>
+
+#include "s60cameraimageprocessingcontrol.h"
+#include "s60cameraservice.h"
+#include "s60imagecapturesession.h"
+
+S60CameraImageProcessingControl::S60CameraImageProcessingControl(QObject *parent) :
+ QCameraImageProcessingControl(parent)
+{
+}
+
+S60CameraImageProcessingControl::S60CameraImageProcessingControl(S60ImageCaptureSession *session, QObject *parent) :
+ QCameraImageProcessingControl(parent),
+ m_session(0),
+ m_advancedSettings(0)
+{
+ m_session = session;
+ m_advancedSettings = m_session->advancedSettings();
+}
+
+S60CameraImageProcessingControl::~S60CameraImageProcessingControl()
+{
+ m_advancedSettings = 0;
+}
+
+void S60CameraImageProcessingControl::resetAdvancedSetting()
+{
+ m_advancedSettings = m_session->advancedSettings();
+}
+
+QCameraImageProcessing::WhiteBalanceMode S60CameraImageProcessingControl::whiteBalanceMode() const
+{
+ return m_session->whiteBalanceMode();
+}
+
+void S60CameraImageProcessingControl::setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode)
+{
+ if (isWhiteBalanceModeSupported(mode))
+ m_session->setWhiteBalanceMode(mode);
+ else
+ m_session->setError(KErrNotSupported, tr("Requested white balance mode is not supported."));
+}
+
+bool S60CameraImageProcessingControl::isWhiteBalanceModeSupported(
+ QCameraImageProcessing::WhiteBalanceMode mode) const
+{
+ return m_session->isWhiteBalanceModeSupported(mode);
+}
+
+int S60CameraImageProcessingControl::manualWhiteBalance() const
+{
+ return 0;
+}
+
+void S60CameraImageProcessingControl::setManualWhiteBalance(int colorTemperature)
+{
+ m_session->setError(KErrNotSupported, tr("Setting manual white balance is not supported."));
+ Q_UNUSED(colorTemperature)
+}
+
+bool S60CameraImageProcessingControl::isProcessingParameterSupported(ProcessingParameter parameter) const
+{
+ // First check settings requiring Adv. Settings
+ if (m_advancedSettings) {
+ switch (parameter) {
+ case QCameraImageProcessingControl::Saturation:
+ return true;
+ case QCameraImageProcessingControl::Sharpening:
+ return isSharpeningSupported();
+ case QCameraImageProcessingControl::Denoising:
+ return isDenoisingSupported();
+ case QCameraImageProcessingControl::ColorTemperature:
+ return false;
+ }
+ }
+
+ // Then the rest
+ switch (parameter) {
+ case QCameraImageProcessingControl::Contrast:
+ case QCameraImageProcessingControl::Brightness:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+QVariant S60CameraImageProcessingControl::processingParameter(
+ QCameraImageProcessingControl::ProcessingParameter parameter) const
+{
+ switch (parameter) {
+ case QCameraImageProcessingControl::Contrast:
+ return QVariant(contrast());
+ case QCameraImageProcessingControl::Saturation:
+ return QVariant(saturation());
+ case QCameraImageProcessingControl::Brightness:
+ return QVariant(brightness());
+ case QCameraImageProcessingControl::Sharpening:
+ return QVariant(sharpeningLevel());
+ case QCameraImageProcessingControl::Denoising:
+ return QVariant(denoisingLevel());
+ case QCameraImageProcessingControl::ColorTemperature:
+ return QVariant(manualWhiteBalance());
+
+ default:
+ return QVariant();
+ }
+}
+
+void S60CameraImageProcessingControl::setProcessingParameter(
+ QCameraImageProcessingControl::ProcessingParameter parameter, QVariant value)
+{
+ switch (parameter) {
+ case QCameraImageProcessingControl::Contrast:
+ setContrast(value.toInt());
+ break;
+ case QCameraImageProcessingControl::Saturation:
+ setSaturation(value.toInt());
+ break;
+ case QCameraImageProcessingControl::Brightness:
+ setBrightness(value.toInt());
+ break;
+ case QCameraImageProcessingControl::Sharpening:
+ if (isSharpeningSupported())
+ setSharpeningLevel(value.toInt());
+ break;
+ case QCameraImageProcessingControl::Denoising:
+ if (isDenoisingSupported())
+ setDenoisingLevel(value.toInt());
+ break;
+ case QCameraImageProcessingControl::ColorTemperature:
+ setManualWhiteBalance(value.toInt());
+ break;
+
+ default:
+ break;
+ }
+}
+
+void S60CameraImageProcessingControl::setContrast(int value)
+{
+ m_session->setContrast(value);
+}
+
+int S60CameraImageProcessingControl::contrast() const
+{
+ return m_session->contrast();
+}
+
+void S60CameraImageProcessingControl::setBrightness(int value)
+{
+ m_session->setBrightness(value);
+}
+
+int S60CameraImageProcessingControl::brightness() const
+{
+ return m_session->brightness();
+}
+
+void S60CameraImageProcessingControl::setSaturation(int value)
+{
+ if (m_advancedSettings)
+ m_advancedSettings->setSaturation(value);
+ else
+ m_session->setError(KErrNotSupported, tr("Setting saturation is not supported."));
+}
+
+int S60CameraImageProcessingControl::saturation() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->saturation();
+ return 0;
+}
+
+void S60CameraImageProcessingControl::setDenoisingLevel(int value)
+{
+ m_session->setError(KErrNotSupported, tr("Setting denoising level is not supported."));
+ Q_UNUSED(value); // Not supported for Symbian
+}
+
+bool S60CameraImageProcessingControl::isDenoisingSupported() const
+{
+ return false; // Not supported for Symbian
+}
+
+int S60CameraImageProcessingControl::denoisingLevel() const
+{
+ return 0; // Not supported for Symbian
+}
+
+void S60CameraImageProcessingControl::setSharpeningLevel(int value)
+{
+ if (m_advancedSettings)
+ m_advancedSettings->setSharpeningLevel(value);
+ else
+ m_session->setError(KErrNotSupported, tr("Setting sharpening level is not supported."));
+}
+
+bool S60CameraImageProcessingControl::isSharpeningSupported() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->isSharpeningSupported();
+ return false;
+}
+
+int S60CameraImageProcessingControl::sharpeningLevel() const
+{
+ if (m_advancedSettings)
+ return m_advancedSettings->sharpeningLevel();
+ return 0;
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.h b/src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.h
new file mode 100644
index 000000000..7fc6b8900
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraimageprocessingcontrol.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** 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 S60CAMERAIMAGEPROCESSINGCONTROL_H
+#define S60CAMERAIMAGEPROCESSINGCONTROL_H
+
+#include <qcameraimageprocessing.h>
+#include <qcameraimageprocessingcontrol.h>
+
+#include "s60camerasettings.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+
+/*
+ * Control for image processing related camera operations (inc. white balance).
+ */
+class S60CameraImageProcessingControl : public QCameraImageProcessingControl
+{
+ Q_OBJECT
+
+public: // Constructors & Destructor
+
+ S60CameraImageProcessingControl(QObject *parent = 0);
+ S60CameraImageProcessingControl(S60ImageCaptureSession *session, QObject *parent = 0);
+ ~S60CameraImageProcessingControl();
+
+public: // QCameraImageProcessingControl
+
+ // White Balance
+ QCameraImageProcessing::WhiteBalanceMode whiteBalanceMode() const;
+ void setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode);
+ bool isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const;
+
+ // Processing Parameter
+ bool isProcessingParameterSupported(ProcessingParameter parameter) const;
+ QVariant processingParameter(QCameraImageProcessingControl::ProcessingParameter parameter) const;
+ void setProcessingParameter(QCameraImageProcessingControl::ProcessingParameter parameter, QVariant value);
+
+private slots: // Internal Slots
+
+ void resetAdvancedSetting();
+
+private: // Internal operations - Implementing ProcessingParameter
+
+ // Manual White Balance (Color Temperature)
+ int manualWhiteBalance() const;
+ void setManualWhiteBalance(int colorTemperature);
+
+ // Contrast
+ int contrast() const;
+ void setContrast(int value);
+
+ // Brightness
+ int brightness() const;
+ void setBrightness(int value);
+
+ // Saturation
+ int saturation() const;
+ void setSaturation(int value);
+
+ // Sharpening
+ bool isSharpeningSupported() const;
+ int sharpeningLevel() const;
+ void setSharpeningLevel(int value);
+
+ // Denoising
+ bool isDenoisingSupported() const;
+ int denoisingLevel() const;
+ void setDenoisingLevel(int value);
+
+private: // Data
+
+ S60ImageCaptureSession *m_session;
+ S60CameraSettings *m_advancedSettings;
+};
+
+#endif // S60CAMERAIMAGEPROCESSINGCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameralockscontrol.cpp b/src/plugins/symbian/ecam/s60cameralockscontrol.cpp
new file mode 100644
index 000000000..cce030f22
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameralockscontrol.cpp
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** 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 <QtCore/qstring.h>
+#include <qcamerafocus.h> // FocusMode
+
+#include "s60cameralockscontrol.h"
+#include "s60cameraservice.h"
+#include "s60imagecapturesession.h"
+#include "s60camerasettings.h"
+#include "s60camerafocuscontrol.h"
+
+S60CameraLocksControl::S60CameraLocksControl(QObject *parent) :
+ QCameraLocksControl(parent)
+{
+}
+
+S60CameraLocksControl::S60CameraLocksControl(S60CameraService *service,
+ S60ImageCaptureSession *session,
+ QObject *parent) :
+ QCameraLocksControl(parent),
+ m_session(0),
+ m_service(0),
+ m_advancedSettings(0),
+ m_focusControl(0),
+ m_focusStatus(QCamera::Unlocked),
+ m_exposureStatus(QCamera::Unlocked),
+ m_whiteBalanceStatus(QCamera::Unlocked)
+{
+ m_session = session;
+ m_service = service;
+ m_focusControl = qobject_cast<S60CameraFocusControl *>(m_service->requestControl(QCameraFocusControl_iid));
+
+ connect(m_session, SIGNAL(advancedSettingChanged()), this, SLOT(resetAdvancedSetting()));
+ m_advancedSettings = m_session->advancedSettings();
+
+ // Exposure Lock Signals
+ if (m_advancedSettings)
+ connect(m_advancedSettings, SIGNAL(exposureStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
+ this, SLOT(exposureStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
+
+ // Focus Lock Signal
+ // * S60 3.2 and later (through Adv. Settings)
+ if (m_advancedSettings)
+ connect(m_advancedSettings, SIGNAL(focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
+ this, SLOT(focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
+ // * S60 3.1 (through ImageSession)
+ connect(m_session, SIGNAL(focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
+ this, SLOT(focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
+}
+
+S60CameraLocksControl::~S60CameraLocksControl()
+{
+ m_advancedSettings = 0;
+}
+
+QCamera::LockTypes S60CameraLocksControl::supportedLocks() const
+{
+ QCamera::LockTypes supportedLocks = 0;
+
+#ifdef S60_CAM_AUTOFOCUS_SUPPORT // S60 3.1
+ if (m_session)
+ if (m_session->isFocusSupported())
+ supportedLocks |= QCamera::LockFocus;
+#else // S60 3.2 and later
+ if (m_advancedSettings) {
+ QCameraFocus::FocusModes supportedFocusModes = m_advancedSettings->supportedFocusModes();
+ if (supportedFocusModes & QCameraFocus::AutoFocus)
+ supportedLocks |= QCamera::LockFocus;
+
+ // Exposure/WhiteBalance Locking not implemented in Symbian
+ // supportedLocks |= QCamera::LockExposure;
+ // supportedLocks |= QCamera::LockWhiteBalance;
+ }
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+
+ return supportedLocks;
+}
+
+QCamera::LockStatus S60CameraLocksControl::lockStatus(QCamera::LockType lock) const
+{
+ switch (lock) {
+ case QCamera::LockExposure:
+ return m_exposureStatus;
+ case QCamera::LockWhiteBalance:
+ return m_whiteBalanceStatus;
+ case QCamera::LockFocus:
+ return m_focusStatus;
+
+ default:
+ // Unsupported lock
+ return QCamera::Unlocked;
+ }
+}
+
+void S60CameraLocksControl::searchAndLock(QCamera::LockTypes locks)
+{
+ if (locks & QCamera::LockExposure) {
+ // Not implemented in Symbian
+ //startExposureLocking();
+ }
+ if (locks & QCamera::LockWhiteBalance) {
+ // Not implemented in Symbian
+ }
+ if (locks & QCamera::LockFocus)
+ startFocusing();
+}
+
+void S60CameraLocksControl::unlock(QCamera::LockTypes locks)
+{
+ if (locks & QCamera::LockExposure) {
+ // Not implemented in Symbian
+ //cancelExposureLocking();
+ }
+
+ if (locks & QCamera::LockFocus)
+ cancelFocusing();
+}
+
+void S60CameraLocksControl::resetAdvancedSetting()
+{
+ m_advancedSettings = m_session->advancedSettings();
+
+ // Reconnect Lock Signals
+ if (m_advancedSettings) {
+ connect(m_advancedSettings, SIGNAL(exposureStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
+ this, SLOT(exposureStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
+ connect(m_advancedSettings, SIGNAL(focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
+ this, SLOT(focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
+ }
+}
+
+void S60CameraLocksControl::exposureStatusChanged(QCamera::LockStatus status,
+ QCamera::LockChangeReason reason)
+{
+ if(status != m_exposureStatus) {
+ m_exposureStatus = status;
+ emit lockStatusChanged(QCamera::LockExposure, status, reason);
+ }
+}
+
+void S60CameraLocksControl::focusStatusChanged(QCamera::LockStatus status,
+ QCamera::LockChangeReason reason)
+{
+ if(status != m_focusStatus) {
+ m_focusStatus = status;
+ emit lockStatusChanged(QCamera::LockFocus, status, reason);
+ }
+}
+
+void S60CameraLocksControl::startFocusing()
+{
+#ifndef S60_CAM_AUTOFOCUS_SUPPORT // S60 3.2 or later
+ // Focusing is triggered on Symbian by setting the FocusType corresponding
+ // to the FocusMode set to FocusControl
+ if (m_focusControl) {
+ if (m_advancedSettings) {
+ m_advancedSettings->startFocusing();
+ m_focusStatus = QCamera::Searching;
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Searching, QCamera::UserRequest);
+ }
+ else
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::LockFailed);
+ }
+ else
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::LockFailed);
+
+#else // S60 3.1
+ if (m_focusControl && m_focusControl->focusMode() == QCameraFocus::AutoFocus) {
+ m_session->startFocus();
+ m_focusStatus = QCamera::Searching;
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Searching, QCamera::UserRequest);
+ }
+ else
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::LockFailed);
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+}
+
+void S60CameraLocksControl::cancelFocusing()
+{
+ if (m_focusStatus == QCamera::Unlocked)
+ return;
+
+#ifndef S60_CAM_AUTOFOCUS_SUPPORT // S60 3.2 or later
+ if (m_advancedSettings) {
+ m_advancedSettings->cancelFocusing();
+ m_focusStatus = QCamera::Unlocked;
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::UserRequest);
+ }
+ else
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::LockFailed);
+
+#else // S60 3.1
+ m_session->cancelFocus();
+ m_focusStatus = QCamera::Unlocked;
+ emit lockStatusChanged(QCamera::LockFocus, QCamera::Unlocked, QCamera::UserRequest);
+#endif // S60_CAM_AUTOFOCUS_SUPPORT
+}
+
+void S60CameraLocksControl::startExposureLocking()
+{
+ if (m_advancedSettings) {
+ m_advancedSettings->lockExposure(true);
+ m_exposureStatus = QCamera::Searching;
+ emit lockStatusChanged(QCamera::LockExposure, QCamera::Searching, QCamera::UserRequest);
+ }
+ else
+ emit lockStatusChanged(QCamera::LockExposure, QCamera::Unlocked, QCamera::LockFailed);
+}
+
+void S60CameraLocksControl::cancelExposureLocking()
+{
+ if (m_exposureStatus == QCamera::Unlocked)
+ return;
+
+ if (m_advancedSettings) {
+ m_advancedSettings->lockExposure(false);
+ m_exposureStatus = QCamera::Unlocked;
+ emit lockStatusChanged(QCamera::LockExposure, QCamera::Unlocked, QCamera::UserRequest);
+ }
+ else
+ emit lockStatusChanged(QCamera::LockExposure, QCamera::Unlocked, QCamera::LockFailed);
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameralockscontrol.h b/src/plugins/symbian/ecam/s60cameralockscontrol.h
new file mode 100644
index 000000000..3b49cbaba
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameralockscontrol.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** 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 S60CAMERALOCKSCONTROL_H
+#define S60CAMERALOCKSCONTROL_H
+
+#include <QtCore/qobject.h>
+#include "qcameralockscontrol.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class S60ImageCaptureSession;
+class S60CameraSettings;
+class S60CameraFocusControl;
+
+/*
+ * Control for searching and locking 3A algorithms (AutoFocus, AutoExposure
+ * and AutoWhitebalance).
+ */
+class S60CameraLocksControl : public QCameraLocksControl
+{
+ Q_OBJECT
+
+public: // Contructors & Destrcutor
+
+ S60CameraLocksControl(QObject *parent = 0);
+ S60CameraLocksControl(S60CameraService *service,
+ S60ImageCaptureSession *session,
+ QObject *parent = 0);
+ ~S60CameraLocksControl();
+
+public: // QCameraLocksControl
+
+ QCamera::LockTypes supportedLocks() const;
+
+ QCamera::LockStatus lockStatus(QCamera::LockType lock) const;
+
+ void searchAndLock(QCamera::LockTypes locks);
+ void unlock(QCamera::LockTypes locks);
+
+/*
+Q_SIGNALS: // QCameraLocksControl
+
+ void lockStatusChanged(QCamera::LockType type,
+ QCamera::LockStatus status,
+ QCamera::LockChangeReason reason);
+*/
+
+private slots: // Internal Slots
+
+ void exposureStatusChanged(QCamera::LockStatus status, QCamera::LockChangeReason reason);
+ void focusStatusChanged(QCamera::LockStatus status, QCamera::LockChangeReason reason);
+ void resetAdvancedSetting();
+
+private: // Internal
+
+ // Focus
+ void startFocusing();
+ void cancelFocusing();
+
+ // Exposure
+ void startExposureLocking();
+ void cancelExposureLocking();
+
+private: // Data
+
+ S60ImageCaptureSession *m_session;
+ S60CameraService *m_service;
+ S60CameraSettings *m_advancedSettings;
+ S60CameraFocusControl *m_focusControl;
+ QCamera::LockStatus m_focusStatus;
+ QCamera::LockStatus m_exposureStatus;
+ QCamera::LockStatus m_whiteBalanceStatus;
+};
+
+#endif // S60CAMERALOCKSCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60cameraservice.cpp b/src/plugins/symbian/ecam/s60cameraservice.cpp
new file mode 100644
index 000000000..5cc4485c1
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraservice.cpp
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** 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 <QtCore/qvariant.h>
+#include <QtGui/qwidget.h>
+#include <QtCore/qlist.h>
+
+#include "s60cameraservice.h"
+#include "s60cameracontrol.h"
+#include "s60videodevicecontrol.h"
+#include "s60camerafocuscontrol.h"
+#include "s60cameraexposurecontrol.h"
+#include "s60cameraflashcontrol.h"
+#include "s60cameraimageprocessingcontrol.h"
+#include "s60cameraimagecapturecontrol.h"
+#include "s60mediarecordercontrol.h"
+#include "s60videocapturesession.h"
+#include "s60imagecapturesession.h"
+#include "s60videowidgetcontrol.h"
+#include "s60mediacontainercontrol.h"
+#include "s60videoencodercontrol.h"
+#include "s60audioencodercontrol.h"
+#include "s60imageencodercontrol.h"
+#include "s60cameralockscontrol.h"
+#include "s60videorenderercontrol.h"
+#include "s60videowindowcontrol.h"
+
+#include "s60cameraviewfinderengine.h" // ViewfinderOutputType
+
+S60CameraService::S60CameraService(QObject *parent) :
+ QMediaService(parent)
+{
+ // Session classes for video and image capturing
+ m_imagesession = new S60ImageCaptureSession(this);
+ m_videosession = new S60VideoCaptureSession(this);
+
+ if (m_imagesession && m_videosession) {
+ // Different control classes implementing the Camera API
+ m_control = new S60CameraControl(m_videosession, m_imagesession, this);
+ m_videoDeviceControl = new S60VideoDeviceControl(m_control, this);
+ m_focusControl = new S60CameraFocusControl(m_imagesession, this);
+ m_exposureControl = new S60CameraExposureControl(m_imagesession, this);
+ m_flashControl = new S60CameraFlashControl(m_imagesession, this);
+ m_imageProcessingControl = new S60CameraImageProcessingControl(m_imagesession, this);
+ m_imageCaptureControl = new S60CameraImageCaptureControl(this, m_imagesession, this);
+ m_media = new S60MediaRecorderControl(this, m_videosession, this);
+ m_mediaFormat = new S60MediaContainerControl(m_videosession, this);
+ m_videoEncoder = new S60VideoEncoderControl(m_videosession, this);
+ m_audioEncoder = new S60AudioEncoderControl(m_videosession, this);
+ m_viewFinderWidget = new S60VideoWidgetControl(this);
+ m_imageEncoderControl = new S60ImageEncoderControl(m_imagesession, this);
+ m_locksControl = new S60CameraLocksControl(this, m_imagesession, this);
+ m_rendererControl = new S60VideoRendererControl(this);
+ m_windowControl = new S60VideoWindowControl(this);
+ }
+}
+
+S60CameraService::~S60CameraService()
+{
+ // Delete controls
+ if (m_videoDeviceControl)
+ delete m_videoDeviceControl;
+ if (m_focusControl)
+ delete m_focusControl;
+ if (m_exposureControl)
+ delete m_exposureControl;
+ if (m_flashControl)
+ delete m_flashControl;
+ if (m_imageProcessingControl)
+ delete m_imageProcessingControl;
+ if (m_imageCaptureControl)
+ delete m_imageCaptureControl;
+ if (m_media)
+ delete m_media;
+ if (m_mediaFormat)
+ delete m_mediaFormat;
+ if (m_videoEncoder)
+ delete m_videoEncoder;
+ if (m_audioEncoder)
+ delete m_audioEncoder;
+ if (m_imageEncoderControl)
+ delete m_imageEncoderControl;
+ if (m_locksControl)
+ delete m_locksControl;
+
+ // CameraControl destroys:
+ // * ViewfinderEngine
+ // * CameraEngine
+ if (m_control)
+ delete m_control;
+
+ // Delete viewfinder controls after CameraControl to be sure that
+ // ViewFinder gets stopped before widget (and window) is destroyed
+ if (m_viewFinderWidget)
+ delete m_viewFinderWidget;
+ if (m_rendererControl)
+ delete m_rendererControl;
+ if (m_windowControl)
+ delete m_windowControl;
+
+ // Delete sessions
+ if (m_videosession)
+ delete m_videosession;
+ if (m_imagesession)
+ delete m_imagesession;
+}
+
+QMediaControl *S60CameraService::requestControl(const char *name)
+{
+ if (qstrcmp(name, QMediaRecorderControl_iid) == 0)
+ return m_media;
+
+ if (qstrcmp(name, QCameraControl_iid) == 0)
+ return m_control;
+
+ if (qstrcmp(name, QVideoEncoderControl_iid) == 0)
+ return m_videoEncoder;
+
+ if (qstrcmp(name, QAudioEncoderControl_iid) == 0)
+ return m_audioEncoder;
+
+ if (qstrcmp(name, QMediaContainerControl_iid) == 0)
+ return m_mediaFormat;
+
+ if (qstrcmp(name, QCameraExposureControl_iid) == 0)
+ return m_exposureControl;
+
+ if (qstrcmp(name, QCameraFlashControl_iid) == 0)
+ return m_flashControl;
+
+ if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
+ if (m_viewFinderWidget) {
+ m_control->setVideoOutput(m_viewFinderWidget,
+ S60CameraViewfinderEngine::OutputTypeVideoWidget);
+ return m_viewFinderWidget;
+ }
+ else
+ return 0;
+ }
+
+ if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+ if (m_rendererControl) {
+ m_control->setVideoOutput(m_rendererControl,
+ S60CameraViewfinderEngine::OutputTypeRenderer);
+ return m_rendererControl;
+ }
+ else
+ return 0;
+ }
+
+ if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
+ if (m_windowControl) {
+ m_control->setVideoOutput(m_windowControl,
+ S60CameraViewfinderEngine::OutputTypeVideoWindow);
+ return m_windowControl;
+ }
+ else
+ return 0;
+ }
+
+
+ if (qstrcmp(name, QCameraFocusControl_iid) == 0)
+ return m_focusControl;
+
+ if (qstrcmp(name, QCameraImageProcessingControl_iid) == 0)
+ return m_imageProcessingControl;
+
+ if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
+ return m_imageCaptureControl;
+
+ if (qstrcmp(name, QVideoDeviceControl_iid) == 0)
+ return m_videoDeviceControl;
+
+ if (qstrcmp(name, QImageEncoderControl_iid) == 0)
+ return m_imageEncoderControl;
+
+ if (qstrcmp(name, QCameraLocksControl_iid) == 0)
+ return m_locksControl;
+
+ return 0;
+}
+
+void S60CameraService::releaseControl(QMediaControl *control)
+{
+ if (control == 0)
+ return;
+
+ // Release viewfinder output
+ if (control == m_viewFinderWidget) {
+ if (m_viewFinderWidget)
+ m_control->releaseVideoOutput(S60CameraViewfinderEngine::OutputTypeVideoWidget);
+ }
+
+ if (control == m_rendererControl) {
+ if (m_rendererControl)
+ m_control->releaseVideoOutput(S60CameraViewfinderEngine::OutputTypeRenderer);
+ }
+
+ if (control == m_windowControl) {
+ if (m_windowControl)
+ m_control->releaseVideoOutput(S60CameraViewfinderEngine::OutputTypeVideoWindow);
+ }
+}
+
+int S60CameraService::deviceCount()
+{
+ return S60CameraControl::deviceCount();
+}
+
+QString S60CameraService::deviceDescription(const int index)
+{
+ return S60CameraControl::description(index);
+}
+
+QString S60CameraService::deviceName(const int index)
+{
+ return S60CameraControl::name(index);
+}
+
+// End of file
+
diff --git a/src/plugins/symbian/ecam/s60cameraservice.h b/src/plugins/symbian/ecam/s60cameraservice.h
new file mode 100644
index 000000000..a2744c1fa
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraservice.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** 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 S60CAMERASERVICE_H
+#define S60CAMERASERVICE_H
+
+#include <QtCore/qobject.h>
+#include <qmediaservice.h>
+
+QT_USE_NAMESPACE
+
+class S60MediaContainerControl;
+class S60VideoEncoderControl;
+class S60AudioEncoderControl;
+class S60CameraControl;
+class S60VideoDeviceControl;
+class S60MediaRecorderControl;
+class S60ImageCaptureSession;
+class S60VideoCaptureSession;
+class S60CameraFocusControl;
+class S60CameraExposureControl;
+class S60CameraFlashControl;
+class S60CameraImageProcessingControl;
+class S60CameraImageCaptureControl;
+class S60VideoWidgetControl;
+class S60ImageEncoderControl;
+class S60CameraLocksControl;
+class S60VideoRendererControl;
+class S60VideoWindowControl;
+
+class S60CameraService : public QMediaService
+{
+ Q_OBJECT
+
+public: // Contructor & Destructor
+
+ S60CameraService(QObject *parent = 0);
+ ~S60CameraService();
+
+public: // QMediaService
+
+ QMediaControl *requestControl(const char *name);
+ void releaseControl(QMediaControl *control);
+
+public: // Static Device Info
+
+ static int deviceCount();
+ static QString deviceName(const int index);
+ static QString deviceDescription(const int index);
+
+private: // Data
+
+ S60ImageCaptureSession *m_imagesession;
+ S60VideoCaptureSession *m_videosession;
+ S60MediaContainerControl *m_mediaFormat;
+ S60VideoEncoderControl *m_videoEncoder;
+ S60AudioEncoderControl *m_audioEncoder;
+ S60CameraControl *m_control;
+ S60VideoDeviceControl *m_videoDeviceControl;
+ S60CameraFocusControl *m_focusControl;
+ S60CameraExposureControl *m_exposureControl;
+ S60CameraFlashControl *m_flashControl;
+ S60CameraImageProcessingControl *m_imageProcessingControl;
+ S60CameraImageCaptureControl *m_imageCaptureControl;
+ S60MediaRecorderControl *m_media;
+ S60VideoWidgetControl *m_viewFinderWidget;
+ S60ImageEncoderControl *m_imageEncoderControl;
+ S60CameraLocksControl *m_locksControl;
+ S60VideoRendererControl *m_rendererControl;
+ S60VideoWindowControl *m_windowControl;
+};
+
+#endif // S60CAMERASERVICE_H
diff --git a/src/plugins/symbian/ecam/s60cameraserviceplugin.cpp b/src/plugins/symbian/ecam/s60cameraserviceplugin.cpp
new file mode 100644
index 000000000..8f22fd205
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraserviceplugin.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** 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 <QtCore/qstring.h>
+
+#include "s60cameraserviceplugin.h"
+#ifdef QMEDIA_SYMBIAN_CAMERA
+#include "s60cameraservice.h"
+#endif
+
+QStringList S60CameraServicePlugin::keys() const
+{
+ QStringList list;
+#ifdef QMEDIA_SYMBIAN_CAMERA
+ list << QLatin1String(Q_MEDIASERVICE_CAMERA);
+#endif
+ return list;
+}
+
+QMediaService* S60CameraServicePlugin::create(QString const& key)
+{
+#ifdef QMEDIA_SYMBIAN_CAMERA
+ if (key == QLatin1String(Q_MEDIASERVICE_CAMERA))
+ return new S60CameraService;
+#endif
+ return 0;
+}
+
+void S60CameraServicePlugin::release(QMediaService *service)
+{
+ delete service;
+}
+
+QList<QByteArray> S60CameraServicePlugin::devices(const QByteArray &service) const
+{
+#ifdef QMEDIA_SYMBIAN_CAMERA
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ if (m_cameraDevices.isEmpty())
+ updateDevices();
+
+ return m_cameraDevices;
+ }
+#endif
+ return QList<QByteArray>();
+}
+
+QString S60CameraServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
+{
+#ifdef QMEDIA_SYMBIAN_CAMERA
+ if (service == Q_MEDIASERVICE_CAMERA) {
+ if (m_cameraDevices.isEmpty())
+ updateDevices();
+
+ for (int i=0; i<m_cameraDevices.count(); i++)
+ if (m_cameraDevices[i] == device)
+ return m_cameraDescriptions[i];
+ }
+#endif
+ return QString();
+}
+
+void S60CameraServicePlugin::updateDevices() const
+{
+#ifdef QMEDIA_SYMBIAN_CAMERA
+ m_cameraDevices.clear();
+ m_cameraDescriptions.clear();
+ for (int i=0; i < S60CameraService::deviceCount(); i ++) {
+ m_cameraDevices.append(S60CameraService::deviceName(i).toUtf8());
+ m_cameraDescriptions.append(S60CameraService::deviceDescription(i));
+ }
+#endif
+}
+
+Q_EXPORT_PLUGIN2(qtmultimedia_ecamngine, S60CameraServicePlugin);
+
+// End of file
+
diff --git a/src/plugins/symbian/ecam/s60cameraserviceplugin.h b/src/plugins/symbian/ecam/s60cameraserviceplugin.h
new file mode 100644
index 000000000..c56b054c6
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraserviceplugin.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 S60CAMERASERVICEPLUGIN_H
+#define S60CAMERASERVICEPLUGIN_H
+
+#include <qmediaservice.h>
+#include <qmediaserviceproviderplugin.h>
+
+QT_USE_NAMESPACE
+
+/*
+ * Plugin implementation for the Camera Service
+ */
+class S60CameraServicePlugin : public QMediaServiceProviderPlugin,
+ public QMediaServiceSupportedDevicesInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
+
+public: // QMediaServiceProviderPlugin
+
+ QStringList keys() const;
+ QMediaService* create(QString const& key);
+ void release(QMediaService *service);
+
+public: // QMediaServiceSupportedDevicesInterface
+
+ QList<QByteArray> devices(const QByteArray &service) const;
+ QString deviceDescription(const QByteArray &service, const QByteArray &device);
+
+private: // Internal
+
+ void updateDevices() const;
+
+private: // Data
+
+ mutable QList<QByteArray> m_cameraDevices;
+ mutable QStringList m_cameraDescriptions;
+};
+
+#endif // S60CAMERASERVICEPLUGIN_H
diff --git a/src/plugins/symbian/ecam/s60camerasettings.cpp b/src/plugins/symbian/ecam/s60camerasettings.cpp
new file mode 100644
index 000000000..a5918078f
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60camerasettings.cpp
@@ -0,0 +1,986 @@
+/****************************************************************************
+**
+** 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 "s60camerasettings.h"
+#include "s60cameraconstants.h"
+
+// S60 3.2 Platform
+#ifdef USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER
+#define POST_31_PLATFORM
+#include <ecamadvancedsettings.h> // CCameraAdvancedSettings (inc. TValueInfo)
+#endif // S60 3.2
+
+// S60 5.0 or later
+#ifdef USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER
+#define POST_31_PLATFORM
+#include <ecamadvsettings.h> // CCameraAdvancedSettings
+#include <ecam/ecamconstants.h> // TValueInfo
+#endif // S60 5.0 or later
+
+S60CameraSettings::S60CameraSettings(QObject *parent, CCameraEngine *engine) :
+ QObject(parent),
+#ifndef S60_31_PLATFORM // Post S60 3.1 Platforms
+ m_advancedSettings(0),
+ m_imageProcessingSettings(0),
+#endif // S60_31_PLATFORM
+ m_cameraEngine(engine),
+ m_continuousFocusing(false)
+{
+}
+
+S60CameraSettings::~S60CameraSettings()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ delete m_advancedSettings;
+ m_advancedSettings = 0;
+ }
+
+ if (m_imageProcessingSettings) {
+ delete m_imageProcessingSettings;
+ m_imageProcessingSettings = 0;
+ }
+#endif // POST_31_PLATFORM
+}
+
+/*
+ * This is Symbian NewL kind of consructor, but unlike Symbian version this
+ * constructor will not leave, but instead it will return possible errors in
+ * the error variable. This is to be able to write the class without deriving
+ * it form CBase. Also CleanupStack is cleaned here if the ConstructL leaves.
+ */
+S60CameraSettings* S60CameraSettings::New(int &error, QObject *parent, CCameraEngine *engine)
+{
+ S60CameraSettings* self = new S60CameraSettings(parent, engine);
+ if (!self) {
+ error = KErrNoMemory;
+ return 0;
+ }
+
+ TRAPD(err, self->ConstructL());
+ if (err) {
+ // Clean created object
+ delete self;
+ self = 0;
+ error = err;
+ return 0;
+ }
+
+ error = KErrNone;
+ return self;
+}
+
+void S60CameraSettings::ConstructL()
+{
+#ifdef POST_31_PLATFORM
+ if (!m_cameraEngine)
+ User::Leave(KErrGeneral);
+ // From now on it is safe to assume engine exists
+
+ // If no AdvancedSettings is available, there's no benefit of S60CameraSettings
+ // Leave if creation fails
+ m_advancedSettings = CCamera::CCameraAdvancedSettings::NewL(*m_cameraEngine->Camera());
+ CleanupStack::PushL(m_advancedSettings);
+
+ // ImageProcessing module may not be supported, don't Leave
+ TRAPD(err, m_imageProcessingSettings = CCamera::CCameraImageProcessing::NewL(*m_cameraEngine->Camera()));
+ if (err == KErrNone && m_imageProcessingSettings) {
+ CleanupStack::PushL(m_imageProcessingSettings);
+ } else {
+ if (err == KErrNotSupported)
+ m_imageProcessingSettings = 0;
+ else {
+ // Leave with error
+ if (!m_imageProcessingSettings)
+ User::Leave(KErrNoMemory);
+ else
+ User::Leave(err);
+ }
+ }
+
+ if (m_advancedSettings) {
+ RArray<TInt> digitalZoomFactors;
+ CleanupClosePushL(digitalZoomFactors);
+
+ TValueInfo info = ENotActive;
+ m_advancedSettings->GetDigitalZoomStepsL(digitalZoomFactors, info);
+
+ for (int i = 0; i < digitalZoomFactors.Count(); ++i)
+ m_supportedSymbianDigitalZoomFactors << digitalZoomFactors[i];
+
+ CleanupStack::PopAndDestroy(); // RArray<TInt> digitalZoomFactors
+ }
+
+ // Pop objects from CleanupStack
+ if (m_imageProcessingSettings)
+ CleanupStack::Pop(m_imageProcessingSettings);
+ CleanupStack::Pop(m_advancedSettings);
+
+#else // S60 3.1
+ // AdvancedSettings are not suppoted on S60 3.1 (There's no use for S60CameraSettings)
+ User::Leave(KErrNotSupported);
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setFocusMode(QCameraFocus::FocusMode mode)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ switch (mode) {
+ case QCameraFocus::ManualFocus: // Manual focus mode
+ m_advancedSettings->SetFocusMode(CCamera::CCameraAdvancedSettings::EFocusModeManual);
+ m_continuousFocusing = false;
+ break;
+ case QCameraFocus::AutoFocus: // Single-shot AutoFocus mode
+ m_advancedSettings->SetFocusMode(CCamera::CCameraAdvancedSettings::EFocusModeAuto);
+ m_advancedSettings->SetFocusRange(CCamera::CCameraAdvancedSettings::EFocusRangeAuto);
+ m_continuousFocusing = false;
+ break;
+ case QCameraFocus::HyperfocalFocus:
+ m_advancedSettings->SetFocusMode(CCamera::CCameraAdvancedSettings::EFocusModeAuto);
+ m_advancedSettings->SetFocusRange(CCamera::CCameraAdvancedSettings::EFocusRangeHyperfocal);
+ m_continuousFocusing = false;
+ break;
+ case QCameraFocus::InfinityFocus:
+ m_advancedSettings->SetFocusMode(CCamera::CCameraAdvancedSettings::EFocusModeAuto);
+ m_advancedSettings->SetFocusRange(CCamera::CCameraAdvancedSettings::EFocusRangeInfinite);
+ m_continuousFocusing = false;
+ break;
+ case QCameraFocus::ContinuousFocus:
+ m_advancedSettings->SetFocusMode(CCamera::CCameraAdvancedSettings::EFocusModeAuto);
+ m_advancedSettings->SetFocusRange(CCamera::CCameraAdvancedSettings::EFocusRangeAuto);
+ m_continuousFocusing = true;
+ break;
+ case QCameraFocus::MacroFocus:
+ m_advancedSettings->SetFocusMode(CCamera::CCameraAdvancedSettings::EFocusModeAuto);
+ m_advancedSettings->SetFocusRange(CCamera::CCameraAdvancedSettings::EFocusRangeMacro);
+ m_continuousFocusing = false;
+ break;
+
+ default:
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested focus mode is not supported."));
+ break;
+ }
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#else // S60 3.1
+ Q_UNUSED(mode);
+ emit error(QCamera::NotSupportedFeatureError, tr("Settings focus mode is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::startFocusing()
+{
+#ifdef POST_31_PLATFORM
+ // Setting AutoFocusType triggers the focusing on Symbian
+ if (m_advancedSettings) {
+ if (m_continuousFocusing)
+ m_advancedSettings->SetAutoFocusType(CCamera::CCameraAdvancedSettings::EAutoFocusTypeContinuous);
+ else
+ m_advancedSettings->SetAutoFocusType(CCamera::CCameraAdvancedSettings::EAutoFocusTypeSingle);
+ } else {
+ emit error(QCamera::CameraError, tr("Unable to focus."));
+ }
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::cancelFocusing()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings)
+ m_advancedSettings->SetAutoFocusType(CCamera::CCameraAdvancedSettings::EAutoFocusTypeOff);
+ else
+ emit error(QCamera::CameraError, tr("Unable to cancel focusing."));
+#endif // POST_31_PLATFORM
+}
+
+QCameraFocus::FocusMode S60CameraSettings::focusMode()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ // First request needed info
+ CCamera::CCameraAdvancedSettings::TFocusMode mode = m_advancedSettings->FocusMode();
+ CCamera::CCameraAdvancedSettings::TFocusRange range = m_advancedSettings->FocusRange();
+ CCamera::CCameraAdvancedSettings::TAutoFocusType autoType = m_advancedSettings->AutoFocusType();
+
+ switch (mode) {
+ case CCamera::CCameraAdvancedSettings::EFocusModeManual:
+ case CCamera::CCameraAdvancedSettings::EFocusModeFixed:
+ return QCameraFocus::ManualFocus;
+
+ case CCamera::CCameraAdvancedSettings::EFocusModeAuto:
+ if (autoType == CCamera::CCameraAdvancedSettings::EAutoFocusTypeContinuous) {
+ return QCameraFocus::ContinuousFocus;
+ } else {
+ // Single-shot focusing
+ switch (range) {
+ case CCamera::CCameraAdvancedSettings::EFocusRangeMacro:
+ case CCamera::CCameraAdvancedSettings::EFocusRangeSuperMacro:
+ return QCameraFocus::MacroFocus;
+ case CCamera::CCameraAdvancedSettings::EFocusRangeHyperfocal:
+ return QCameraFocus::HyperfocalFocus;
+ case CCamera::CCameraAdvancedSettings::EFocusRangeInfinite:
+ return QCameraFocus::InfinityFocus;
+ case CCamera::CCameraAdvancedSettings::EFocusRangeAuto:
+ case CCamera::CCameraAdvancedSettings::EFocusRangeNormal:
+ return QCameraFocus::AutoFocus;
+
+ default:
+ return QCameraFocus::AutoFocus;
+ }
+ }
+ default:
+ return QCameraFocus::AutoFocus; // Return automatic focusing
+ }
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#endif // POST_31_PLATFORM
+ return QCameraFocus::AutoFocus; // Return automatic focusing
+}
+
+QCameraFocus::FocusModes S60CameraSettings::supportedFocusModes()
+{
+ QCameraFocus::FocusModes modes = 0;
+
+#ifdef POST_31_PLATFORM
+ TInt supportedModes = 0;
+ TInt autoFocusTypes = 0;
+ TInt supportedRanges = 0;
+
+ if (m_advancedSettings) {
+ supportedModes = m_advancedSettings->SupportedFocusModes();
+ autoFocusTypes = m_advancedSettings->SupportedAutoFocusTypes();
+ supportedRanges = m_advancedSettings->SupportedFocusRanges();
+
+ if (supportedModes == 0 || autoFocusTypes == 0 || supportedRanges == 0)
+ return modes;
+
+ // EFocusModeAuto is the only supported on Symbian
+ if (supportedModes & CCamera::CCameraAdvancedSettings::EFocusModeAuto) {
+ // Check supported types (Single-shot Auto vs. Continuous)
+ if (autoFocusTypes & CCamera::CCameraAdvancedSettings::EAutoFocusTypeSingle)
+ modes |= QCameraFocus::AutoFocus;
+ if (autoFocusTypes & CCamera::CCameraAdvancedSettings::EAutoFocusTypeContinuous)
+ modes |= QCameraFocus::ContinuousFocus;
+
+ // Check supported ranges (Note! Some are actually fixed focuses
+ // even though the mode is Auto on Symbian)
+ if (supportedRanges & CCamera::CCameraAdvancedSettings::EFocusRangeMacro)
+ modes |= QCameraFocus::MacroFocus;
+ if (supportedRanges & CCamera::CCameraAdvancedSettings::EFocusRangeHyperfocal)
+ modes |= QCameraFocus::HyperfocalFocus;
+ if (supportedRanges & CCamera::CCameraAdvancedSettings::EFocusRangeInfinite)
+ modes |= QCameraFocus::InfinityFocus;
+ }
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#endif // POST_31_PLATFORM
+
+ return modes;
+}
+
+qreal S60CameraSettings::opticalZoomFactorL() const
+{
+ // Not supported on Symbian
+ return 1.0;
+}
+
+void S60CameraSettings::setOpticalZoomFactorL(const qreal zoomFactor)
+{
+ // Not supported on Symbian
+ Q_UNUSED(zoomFactor);
+}
+
+QList<qreal> S60CameraSettings::supportedDigitalZoomFactors() const
+{
+ QList<qreal> zoomFactors;
+ foreach (int factor, m_supportedSymbianDigitalZoomFactors)
+ zoomFactors << qreal(factor) / KSymbianFineResolutionFactor;
+
+ return zoomFactors;
+}
+
+qreal S60CameraSettings::digitalZoomFactorL() const
+{
+ qreal factor = 1.0;
+
+#ifdef POST_31_PLATFORM
+ int symbianFactor = 0;
+ if (m_advancedSettings)
+ symbianFactor = m_advancedSettings->DigitalZoom();
+ else
+ User::Leave(KErrNotSupported);
+
+ if (symbianFactor != 0)
+ factor = qreal(symbianFactor) / KSymbianFineResolutionFactor;
+#endif // POST_31_PLATFORM
+
+ return factor;
+}
+
+void S60CameraSettings::setDigitalZoomFactorL(const qreal zoomFactor)
+{
+#ifdef POST_31_PLATFORM
+ int symbianFactor = zoomFactor * KSymbianFineResolutionFactor;
+
+ // Find closest supported Symbian ZoomFactor if needed
+ if (!m_supportedSymbianDigitalZoomFactors.contains(symbianFactor)) {
+ int closestIndex = -1;
+ int closestDiff = 1000000; // Sensible maximum
+ for (int i = 0; i < m_supportedSymbianDigitalZoomFactors.count(); ++i) {
+ int diff = abs(m_supportedSymbianDigitalZoomFactors.at(i) - symbianFactor);
+ if (diff < closestDiff) {
+ closestDiff = diff;
+ closestIndex = i;
+ }
+ }
+ if (closestIndex != -1)
+ symbianFactor = m_supportedSymbianDigitalZoomFactors.at(closestIndex);
+ else
+ User::Leave(KErrGeneral);
+ }
+ if (m_advancedSettings)
+ m_advancedSettings->SetDigitalZoom(symbianFactor);
+ else
+ User::Leave(KErrNotSupported);
+#else // S60 3.1 Platform
+ Q_UNUSED(zoomFactor);
+ emit error(QCamera::NotSupportedFeatureError, tr("Settings digital zoom factor is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+// MCameraObserver2
+void S60CameraSettings::HandleAdvancedEvent(const TECAMEvent& aEvent)
+{
+#ifdef POST_31_PLATFORM
+
+ if (aEvent.iErrorCode != KErrNone) {
+ switch (aEvent.iErrorCode) {
+ case KErrECamCameraDisabled:
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return;
+ case KErrECamSettingDisabled:
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return;
+ case KErrECamParameterNotInRange:
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested value is not in supported range."));
+ return;
+ case KErrECamSettingNotSupported:
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested setting is not supported."));
+ return;
+ case KErrECamNotOptimalFocus:
+ if (m_continuousFocusing)
+ emit focusStatusChanged(QCamera::Searching, QCamera::LockTemporaryLost);
+ else
+ emit focusStatusChanged(QCamera::Unlocked, QCamera::LockFailed);
+ return;
+ }
+
+ if (aEvent.iEventType == KUidECamEventCameraSettingFocusRange ||
+ aEvent.iEventType == KUidECamEventCameraSettingAutoFocusType2) {
+ emit focusStatusChanged(QCamera::Unlocked, QCamera::LockFailed);
+ return;
+ } else if (aEvent.iEventType == KUidECamEventCameraSettingIsoRate) {
+ if (aEvent.iErrorCode == KErrNotSupported)
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested ISO value is not supported."));
+ else
+ emit error(QCamera::CameraError, tr("Setting ISO value failed."));
+ return;
+ } else if (aEvent.iEventType == KUidECamEventCameraSettingAperture) {
+ if (aEvent.iErrorCode == KErrNotSupported)
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested aperture value is not supported."));
+ else
+ emit error(QCamera::CameraError, tr("Setting aperture value failed."));
+ return;
+ } else if (aEvent.iEventType == KUidECamEventCameraSettingExposureCompensation) {
+ if (aEvent.iErrorCode == KErrNotSupported)
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested exposure compensation is not supported."));
+ else
+ emit error(QCamera::CameraError, tr("Setting exposure compensation failed."));
+ return;
+ } else if (aEvent.iEventType == KUidECamEventCameraSettingOpticalZoom ||
+ aEvent.iEventType == KUidECamEventCameraSettingDigitalZoom) {
+ if (aEvent.iErrorCode == KErrNotSupported)
+ return; // Discard
+ else {
+ emit error(QCamera::CameraError, tr("Setting zoom factor failed."));
+ return;
+ }
+ } else if (aEvent.iEventType == KUidECamEventCameraSettingFocusMode) {
+ if (aEvent.iErrorCode == KErrNotSupported)
+ if (m_cameraEngine && m_cameraEngine->CurrentCameraIndex() != 0)
+ emit error(QCamera::NotSupportedFeatureError, tr("Focusing is not supported with this camera."));
+ else
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested focus mode is not supported."));
+ else
+ emit error(QCamera::CameraError, tr("Setting focus mode failed."));
+ return;
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return;
+ }
+ }
+
+ if (aEvent.iEventType == KUidECamEventCameraSettingExposureLock) {
+ if (m_advancedSettings) {
+ if (m_advancedSettings->ExposureLockOn())
+ emit exposureStatusChanged(QCamera::Locked, QCamera::LockAcquired);
+ else
+ emit exposureStatusChanged(QCamera::Unlocked, QCamera::LockLost);
+ }
+ else
+ emit exposureStatusChanged(QCamera::Unlocked, QCamera::LockLost);
+ }
+ else if (aEvent.iEventType == KUidECamEventCameraSettingAperture)
+ emit apertureChanged();
+
+ else if (aEvent.iEventType == KUidECamEventCameraSettingApertureRange)
+ emit apertureRangeChanged();
+
+ else if (aEvent.iEventType == KUidECamEventCameraSettingIsoRateType)
+ emit isoSensitivityChanged();
+
+ else if (aEvent.iEventType == KUidECamEventCameraSettingShutterSpeed)
+ emit shutterSpeedChanged();
+
+ else if (aEvent.iEventType == KUidECamEventCameraSettingExposureCompensationStep)
+ emit evChanged();
+
+ else if (aEvent.iEventType == KUidECamEventFlashReady)
+ emit flashReady(true);
+
+ else if (aEvent.iEventType == KUidECamEventFlashNotReady)
+ emit flashReady(false);
+
+ else if (aEvent.iEventType.iUid == KUidECamEventCameraSettingsOptimalFocusUidValue)
+ emit focusStatusChanged(QCamera::Locked, QCamera::LockAcquired);
+
+#else // S60 3.1 Platform
+ Q_UNUSED(aEvent);
+#endif // POST_31_PLATFORM
+}
+
+bool S60CameraSettings::isFlashReady()
+{
+ TBool isReady = false;
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ int flashErr = m_advancedSettings->IsFlashReady(isReady);
+ if(flashErr != KErrNone) {
+ if (flashErr != KErrNotSupported)
+ emit error(QCamera::CameraError, tr("Unexpected error with flash."));
+ return false;
+ }
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#endif
+ return isReady;
+}
+
+QCameraExposure::MeteringMode S60CameraSettings::meteringMode()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ CCamera::CCameraAdvancedSettings::TMeteringMode mode = m_advancedSettings->MeteringMode();
+ switch (mode) {
+ case CCamera::CCameraAdvancedSettings::EMeteringModeCenterWeighted:
+ return QCameraExposure::MeteringAverage;
+ case CCamera::CCameraAdvancedSettings::EMeteringModeEvaluative:
+ return QCameraExposure::MeteringMatrix;
+ case CCamera::CCameraAdvancedSettings::EMeteringModeSpot:
+ return QCameraExposure::MeteringSpot;
+
+ default:
+ return QCameraExposure::MeteringAverage;
+ }
+ }else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return QCameraExposure::MeteringAverage;
+ }
+#else // S60 3.1 Platform
+ return QCameraExposure::MeteringAverage;
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setMeteringMode(QCameraExposure::MeteringMode mode)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ switch(mode) {
+ case QCameraExposure::MeteringAverage:
+ m_advancedSettings->SetMeteringMode(CCamera::CCameraAdvancedSettings::EMeteringModeCenterWeighted);
+ break;
+ case QCameraExposure::MeteringMatrix:
+ m_advancedSettings->SetMeteringMode(CCamera::CCameraAdvancedSettings::EMeteringModeEvaluative);
+ break;
+ case QCameraExposure::MeteringSpot:
+ m_advancedSettings->SetMeteringMode(CCamera::CCameraAdvancedSettings::EMeteringModeSpot);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#else // S60 3.1
+ Q_UNUSED(mode);
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting metering mode is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+bool S60CameraSettings::isMeteringModeSupported(QCameraExposure::MeteringMode mode)
+{
+#ifdef POST_31_PLATFORM
+ TInt supportedModes = 0;
+
+ if (m_advancedSettings) {
+ supportedModes = m_advancedSettings->SupportedMeteringModes();
+ if (supportedModes == 0)
+ return false;
+
+ switch (mode) {
+ case QCameraExposure::MeteringMatrix:
+ if (supportedModes & CCamera::CCameraAdvancedSettings::EMeteringModeEvaluative)
+ return true;
+ else
+ return false;
+ case QCameraExposure::MeteringAverage:
+ if (supportedModes & CCamera::CCameraAdvancedSettings::EMeteringModeCenterWeighted)
+ return true;
+ else
+ return false;
+ case QCameraExposure::MeteringSpot:
+ if (supportedModes & CCamera::CCameraAdvancedSettings::EMeteringModeSpot)
+ return true;
+ else
+ return false;
+
+ default:
+ return false;
+ }
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#else // S60 3.1
+ Q_UNUSED(mode);
+#endif // POST_31_PLATFORM
+
+ return false;
+}
+
+int S60CameraSettings::isoSensitivity()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ CCamera::CCameraAdvancedSettings::TISORateType isoRateType;
+ TInt param = 0;
+ TInt isoRate = 0;
+ TRAPD(err, m_advancedSettings->GetISORateL(isoRateType, param, isoRate));
+ if (err)
+ return 0;
+ if (isoRate != KErrNotFound)
+ return isoRate;
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#endif // POST_31_PLATFORM
+ return 0;
+}
+
+QList<int> S60CameraSettings::supportedIsoSensitivities()
+{
+ QList<int> isoSentitivities;
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ RArray<TInt> supportedIsoRates;
+ CleanupClosePushL(supportedIsoRates);
+
+ TRAPD(err, m_advancedSettings->GetSupportedIsoRatesL(supportedIsoRates));
+ if (err != KErrNone) {
+ if (err != KErrNotSupported) // Don's emit error if ISO is not supported
+ emit error(QCamera::CameraError, tr("Failure while querying supported iso sensitivities."));
+ } else {
+ for (int i = 0; i < supportedIsoRates.Count(); ++i)
+ isoSentitivities << supportedIsoRates[i];
+ }
+ CleanupStack::PopAndDestroy(); // RArray<TInt> supportedIsoRates
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+
+ return isoSentitivities;
+#else // S60 3.1 Platform
+ return isoSentitivities;
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setManualIsoSensitivity(int iso)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ TRAPD(err, m_advancedSettings->SetISORateL(CCamera::CCameraAdvancedSettings::EISOManual, iso));
+ if (err)
+ emit error(QCamera::CameraError, tr("Setting manual iso sensitivity failed."));
+ return;
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#else // S60 3.1 Platform
+ Q_UNUSED(iso);
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting manual iso sensitivity is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setAutoIsoSensitivity()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ TRAPD(err, m_advancedSettings->SetISORateL(CCamera::CCameraAdvancedSettings::EISOAutoUnPrioritised, 0));
+ if (err)
+ emit error(QCamera::CameraError, tr("Setting auto iso sensitivity failed."));
+ return;
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#else // S60 3.1 Platform
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting auto iso sensitivity is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+qreal S60CameraSettings::aperture()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings)
+ return qreal(m_advancedSettings->Aperture()) / KSymbianFineResolutionFactor;
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return 0;
+#else // S60 3.1 Platform
+ return 0;
+#endif // POST_31_PLATFORM
+}
+
+QList<qreal> S60CameraSettings::supportedApertures()
+{
+ QList<qreal> apertures;
+
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ RArray<TInt> supportedApertures;
+ TValueInfo info = ENotActive;
+
+ TRAPD(err, m_advancedSettings->GetAperturesL(supportedApertures, info));
+ if (err != KErrNone)
+ if (err != KErrNotSupported)
+ emit error(QCamera::CameraError, tr("Failure while querying supported apertures."));
+ else {
+ for (int i = 0; i < supportedApertures.Count(); i++) {
+ qreal q = qreal(supportedApertures[i]) / KSymbianFineResolutionFactor;
+ apertures.append(q);
+ }
+ }
+ supportedApertures.Close();
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return apertures;
+#else // S60 3.1 Platform
+ return apertures;
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setManualAperture(qreal aperture)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ int symbianAperture = (aperture * KSymbianFineResolutionFactor); // KSymbianFineResolutionFactor = 100
+ m_advancedSettings->SetAperture(symbianAperture);
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#else // S60 3.1
+ Q_UNUSED(aperture);
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting manual aperture is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::lockExposure(bool lock)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ m_advancedSettings->SetExposureLockOn(lock);
+ return;
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#else // S60 3.1
+ Q_UNUSED(lock);
+ emit error(QCamera::NotSupportedFeatureError, tr("Locking exposure is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+bool S60CameraSettings::isExposureLocked()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings)
+ return m_advancedSettings->ExposureLockOn();
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+#endif // POST_31_PLATFORM
+ return false;
+}
+
+qreal S60CameraSettings::shutterSpeed()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ qreal shutterSpeed = qreal(m_advancedSettings->ShutterSpeed()) / 1000000.0;
+ return shutterSpeed; // In seconds
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+ return 0;
+#else // S60 3.1 Platform
+ return 0;
+#endif // POST_31_PLATFORM
+}
+
+QList<qreal> S60CameraSettings::supportedShutterSpeeds()
+{
+ QList<qreal> speeds;
+
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ RArray<TInt> supportedSpeeds;
+ TValueInfo info = ENotActive;
+
+ TRAPD(err, m_advancedSettings->GetShutterSpeedsL(supportedSpeeds, info));
+ if (err != KErrNone)
+ if (err != KErrNotSupported)
+ emit error(QCamera::CameraError, tr("Failure while querying supported shutter speeds."));
+ else {
+ for (int i = 0; i < supportedSpeeds.Count(); i++) {
+ qreal q = qreal(supportedSpeeds[i]) / 1000000.0;
+ speeds.append(q); // In seconds
+ }
+ }
+ supportedSpeeds.Close();
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return speeds;
+#else // S60 3.1 Platform
+ return speeds;
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setManualShutterSpeed(qreal speed)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ TInt shutterSpeed = speed * 1000000; // From seconds to microseconds
+ m_advancedSettings->SetShutterSpeed(shutterSpeed);
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#else // S60 3.1
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting manual shutter speed is not supported."));
+ Q_UNUSED(speed);
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setExposureCompensation(qreal ev)
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ TInt evStep = ev * KSymbianFineResolutionFactor;
+ m_advancedSettings->SetExposureCompensationStep(evStep);
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+#else // S60 3.1 Platform
+ Q_UNUSED(ev);
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting exposure compensation is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+qreal S60CameraSettings::exposureCompensation()
+{
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ TInt evStepSymbian = 0;
+ m_advancedSettings->GetExposureCompensationStep(evStepSymbian);
+ qreal evStep = evStepSymbian;
+ evStep /= KSymbianFineResolutionFactor;
+ return evStep;
+ } else {
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ }
+ return 0;
+#else // S60 3.1 Platform
+ return 0;
+#endif // POST_31_PLATFORM
+}
+
+QList<qreal> S60CameraSettings::supportedExposureCompensationValues()
+{
+ QList<qreal> valueList;
+
+#ifdef POST_31_PLATFORM
+ if (m_advancedSettings) {
+ RArray<TInt> evSteps;
+ TValueInfo info;
+ TRAPD(err, m_advancedSettings->GetExposureCompensationStepsL(evSteps, info));
+ if (err) {
+ if (err != KErrNotSupported)
+ emit error(QCamera::CameraError, tr("Failure while querying supported exposure compensation values."));
+ return valueList;
+ }
+
+ if (info == ENotActive || evSteps.Count() == 0) {
+ // EV not supported, return empty list
+ return valueList;
+ }
+
+ for (int i = 0; i < evSteps.Count(); ++i) {
+ qreal appendValue = evSteps[i];
+ appendValue /= KSymbianFineResolutionFactor;
+ valueList.append(appendValue);
+ }
+ }
+ else
+ emit error(QCamera::CameraError, tr("Unexpected camera error."));
+ return valueList;
+#else // S60 3.1 Platform
+ return valueList;
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setSharpeningLevel(int value)
+{
+#ifdef POST_31_PLATFORM
+ if (m_imageProcessingSettings && isSharpeningSupported())
+ m_imageProcessingSettings->SetTransformationValue(KUidECamEventImageProcessingAdjustSharpness, value);
+ else
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting sharpening level is not supported."));
+#else // S60 3.1
+ Q_UNUSED(value);
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting sharpening level is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+bool S60CameraSettings::isSharpeningSupported() const
+{
+#ifdef POST_31_PLATFORM
+ if (m_imageProcessingSettings) {
+ RArray<TUid> suppTransforms;
+ TRAPD(err, m_imageProcessingSettings->GetSupportedTransformationsL(suppTransforms));
+ if (err)
+ return false;
+
+ if (suppTransforms.Find(KUidECamEventImageProcessingAdjustSharpness))
+ return true;
+ }
+ return false;
+#else // S60 3.1 Platform
+ return false;
+#endif // POST_31_PLATFORM
+}
+
+int S60CameraSettings::sharpeningLevel() const
+{
+#ifdef POST_31_PLATFORM
+ if (m_imageProcessingSettings && isSharpeningSupported())
+ return m_imageProcessingSettings->TransformationValue(KUidECamEventImageProcessingAdjustSharpness);
+ else
+ return 0;
+#else // S60 3.1 Platform
+ return 0;
+#endif // POST_31_PLATFORM
+}
+
+void S60CameraSettings::setSaturation(int value)
+{
+#ifdef POST_31_PLATFORM
+ if (m_imageProcessingSettings) {
+ RArray<TUid> suppTransforms;
+ TRAPD(err, m_imageProcessingSettings->GetSupportedTransformationsL(suppTransforms));
+ if (err)
+ if (err != KErrNotSupported)
+ emit error(QCamera::CameraError, tr("Failure while querying supported transformations."));
+
+ if (suppTransforms.Find(KUidECamEventtImageProcessingAdjustSaturation))
+ m_imageProcessingSettings->SetTransformationValue(KUidECamEventtImageProcessingAdjustSaturation, value == -1 ? 0 : value*2-100);
+ else
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting saturation is not supported."));
+ }
+ else
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting saturation is not supported."));
+#else // S60 3.1
+ Q_UNUSED(value);
+ emit error(QCamera::NotSupportedFeatureError, tr("Setting saturation is not supported."));
+#endif // POST_31_PLATFORM
+}
+
+int S60CameraSettings::saturation()
+{
+#ifdef POST_31_PLATFORM
+ if (m_imageProcessingSettings) {
+ RArray<TUid> suppTransforms;
+ TRAPD(err, m_imageProcessingSettings->GetSupportedTransformationsL(suppTransforms));
+ if (err)
+ if (err != KErrNotSupported)
+ emit error(QCamera::CameraError, tr("Failure while querying supported transformations."));
+
+ if (suppTransforms.Find(KUidECamEventtImageProcessingAdjustSaturation))
+ return m_imageProcessingSettings->TransformationValue(KUidECamEventtImageProcessingAdjustSaturation);
+ }
+ return 0;
+#else // S60 3.1 Platform
+ return 0;
+#endif // POST_31_PLATFORM
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60camerasettings.h b/src/plugins/symbian/ecam/s60camerasettings.h
new file mode 100644
index 000000000..4ecb131b2
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60camerasettings.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** 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 S60CAMERASETTINGS_H
+#define S60CAMERASETTINGS_H
+
+#include "qcamera.h"
+
+#include "s60cameraengine.h"
+#include "s60cameraengineobserver.h"
+
+#include <e32base.h>
+
+QT_USE_NAMESPACE
+
+/*
+ * Class handling CCamera AdvancedSettings and ImageProcessing operations.
+ */
+class S60CameraSettings : public QObject,
+ public MAdvancedSettingsObserver
+{
+ Q_OBJECT
+
+public: // Static Contructor & Destructor
+
+ static S60CameraSettings* New(int &error, QObject *parent = 0, CCameraEngine *engine = 0);
+ ~S60CameraSettings();
+
+public: // Methods
+
+ // Focus
+ QCameraFocus::FocusMode focusMode();
+ void setFocusMode(QCameraFocus::FocusMode mode);
+ QCameraFocus::FocusModes supportedFocusModes();
+ void startFocusing();
+ void cancelFocusing();
+
+ // Zoom
+ qreal opticalZoomFactorL() const;
+ void setOpticalZoomFactorL(const qreal zoomFactor);
+ QList<qreal> supportedDigitalZoomFactors() const;
+ qreal digitalZoomFactorL() const;
+ void setDigitalZoomFactorL(const qreal zoomFactor);
+
+ // Flash
+ bool isFlashReady();
+
+ // Exposure
+ void setExposureMode(QCameraExposure::ExposureMode mode);
+ void lockExposure(bool lock);
+ bool isExposureLocked();
+
+ // Metering Mode
+ QCameraExposure::MeteringMode meteringMode();
+ void setMeteringMode(QCameraExposure::MeteringMode mode);
+ bool isMeteringModeSupported(QCameraExposure::MeteringMode mode);
+
+ // ISO Sensitivity
+ int isoSensitivity();
+ void setManualIsoSensitivity(int iso);
+ void setAutoIsoSensitivity();
+ QList<int> supportedIsoSensitivities();
+
+ // Aperture
+ qreal aperture();
+ void setManualAperture(qreal aperture);
+ QList<qreal> supportedApertures();
+
+ // Shutter Speed
+ qreal shutterSpeed();
+ void setManualShutterSpeed(qreal speed);
+ QList<qreal> supportedShutterSpeeds();
+
+ // ExposureCompensation
+ qreal exposureCompensation();
+ void setExposureCompensation(qreal ev);
+ QList<qreal> supportedExposureCompensationValues();
+
+ // Sharpening Level
+ int sharpeningLevel() const;
+ void setSharpeningLevel(int value);
+ bool isSharpeningSupported() const;
+
+ // Saturation
+ int saturation();
+ void setSaturation(int value);
+
+signals: // Notifications
+
+ // For QCameraExposureControl
+ void flashReady(bool ready);
+ void apertureChanged();
+ void apertureRangeChanged();
+ void shutterSpeedChanged();
+ void isoSensitivityChanged();
+ void evChanged();
+
+ // For QCameraLocksControl
+ void exposureStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason);
+ void focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason);
+
+ // Errors
+ void error(int, const QString&);
+
+protected: // Protected constructors
+
+ S60CameraSettings(QObject *parent, CCameraEngine *engine);
+ void ConstructL();
+
+protected: // MAdvancedSettingsObserver
+
+ void HandleAdvancedEvent(const TECAMEvent& aEvent);
+
+private: // Internal
+
+ bool queryAdvancedSettingsInfo();
+
+private: // Enums
+
+ enum EcamErrors {
+ KErrECamCameraDisabled = -12100, // The camera has been disabled, hence calls do not succeed
+ KErrECamSettingDisabled = -12101, // This parameter or operation is supported, but presently is disabled.
+ KErrECamParameterNotInRange = -12102, // This value is out of range.
+ KErrECamSettingNotSupported = -12103, // This parameter or operation is not supported.
+ KErrECamNotOptimalFocus = -12104 // The optimum focus is lost
+ };
+
+private: // Data
+
+#ifndef S60_31_PLATFORM // Post S60 3.1 Platforms
+ CCamera::CCameraAdvancedSettings *m_advancedSettings;
+ CCamera::CCameraImageProcessing *m_imageProcessingSettings;
+#endif // S60_31_PLATFORM
+ CCameraEngine *m_cameraEngine;
+ QList<int> m_supportedSymbianDigitalZoomFactors;
+ bool m_continuousFocusing;
+};
+
+#endif // S60CAMERASETTINGS_H
diff --git a/src/plugins/symbian/ecam/s60cameraviewfinderengine.cpp b/src/plugins/symbian/ecam/s60cameraviewfinderengine.cpp
new file mode 100644
index 000000000..55d7cbc67
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraviewfinderengine.cpp
@@ -0,0 +1,789 @@
+/****************************************************************************
+**
+** 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 <QApplication>
+#include <QDesktopWidget>
+#include <qcamera.h>
+#include <qabstractvideosurface.h>
+#include <qvideoframe.h>
+
+#include "s60cameraviewfinderengine.h"
+#include "s60cameraengine.h"
+#include "s60cameracontrol.h"
+#include "s60videowidgetcontrol.h"
+#include "s60videowidgetdisplay.h"
+#include "s60videorenderercontrol.h"
+#include "s60videowindowcontrol.h"
+#include "s60videowindowdisplay.h"
+#include "s60cameraconstants.h"
+
+#include <coemain.h> // CCoeEnv
+#include <coecntrl.h> // CCoeControl
+#include <w32std.h>
+
+// Helper function
+TRect qRect2TRect(const QRect &qr)
+{
+ return TRect(TPoint(qr.left(), qr.top()), TSize(qr.width(), qr.height()));
+}
+
+
+S60CameraViewfinderEngine::S60CameraViewfinderEngine(S60CameraControl *control,
+ CCameraEngine *engine,
+ QObject *parent):
+ QObject(parent),
+ m_cameraEngine(engine),
+ m_cameraControl(0),
+ m_viewfinderOutput(0),
+ m_viewfinderDisplay(0),
+ m_viewfinderSurface(0),
+ m_wsSession(CCoeEnv::Static()->WsSession()),
+ m_screenDevice(*CCoeEnv::Static()->ScreenDevice()),
+ m_window(0),
+ m_desktopWidget(0),
+ m_vfState(EVFNotConnectedNotStarted),
+ m_viewfinderSize(KDefaultViewfinderSize),
+ m_actualViewFinderSize(KDefaultViewfinderSize),
+ m_viewfinderAspectRatio(0.0),
+ m_viewfinderType(OutputTypeNotSet),
+ m_viewfinderNativeType(EBitmapViewFinder), // Default type
+ m_isViewFinderVisible(true), // True by default (only QVideoWidgetControl supports being hidden)
+ m_uiLandscape(true),
+ m_vfErrorsSignalled(0)
+{
+ m_cameraControl = control;
+
+ // Check whether platform supports DirectScreen ViewFinder
+ if (m_cameraEngine) {
+ if (m_cameraEngine->IsDirectViewFinderSupported())
+ m_viewfinderNativeType = EDirectScreenViewFinder;
+ else
+ m_viewfinderNativeType = EBitmapViewFinder;
+
+ MCameraViewfinderObserver *vfObserver = this;
+ m_cameraEngine->SetViewfinderObserver(vfObserver);
+ }
+ else
+ m_cameraControl->setError(KErrGeneral, tr("Unexpected camera error."));
+ // From now on it is safe to assume engine exists
+
+ // Check the UI orientation
+ QDesktopWidget* desktopWidget = QApplication::desktop();
+ QRect screenRect = desktopWidget->screenGeometry();
+ if (screenRect.width() > screenRect.height())
+ m_uiLandscape = true;
+ else
+ m_uiLandscape = false;
+
+ // Detect UI Rotations
+ m_desktopWidget = QApplication::desktop();
+ if (m_desktopWidget)
+ connect(m_desktopWidget, SIGNAL(resized(int)), this, SLOT(handleDesktopResize(int)));
+}
+
+S60CameraViewfinderEngine::~S60CameraViewfinderEngine()
+{
+ // No need to stop viewfinder:
+ // Engine has stopped it already
+ // Surface will be stopped by VideoRendererControl
+
+ m_viewfinderOutput = 0;
+ m_viewfinderSurface = 0;
+}
+
+void S60CameraViewfinderEngine::setNewCameraEngine(CCameraEngine *engine)
+{
+ m_cameraEngine = engine;
+
+ if (m_cameraEngine) {
+ // And set observer to the new CameraEngine
+ MCameraViewfinderObserver *vfObserver = this;
+ m_cameraEngine->SetViewfinderObserver(vfObserver);
+ }
+}
+
+void S60CameraViewfinderEngine::handleDesktopResize(int screen)
+{
+ Q_UNUSED(screen);
+ // UI Rotation is handled by the QVideoWidgetControl, thus this is needed
+ // only for the QVideoRendererControl
+ if (m_viewfinderType == OutputTypeRenderer) {
+ QSize newResolution(-1,-1);
+ if (m_viewfinderSurface)
+ newResolution = m_viewfinderSurface->nativeResolution();
+
+ if (newResolution.width() == -1 || newResolution.height() == -1) {
+ QDesktopWidget* desktopWidget = QApplication::desktop();
+ QRect screenRect = desktopWidget->screenGeometry();
+ newResolution = QSize(screenRect.width(), screenRect.height());
+ }
+
+ resetViewfinderSize(newResolution);
+ }
+
+ // Rotate Camera if UI has rotated
+ checkAndRotateCamera();
+}
+
+void S60CameraViewfinderEngine::setVideoWidgetControl(QObject *viewfinderOutput)
+{
+ // Release old control if it has not already been done
+ if (m_viewfinderOutput)
+ releaseControl(m_viewfinderType);
+
+ // Rotate Camera if UI has rotated
+ checkAndRotateCamera();
+
+ S60VideoWidgetControl* viewFinderWidgetControl =
+ qobject_cast<S60VideoWidgetControl*>(viewfinderOutput);
+
+ if (viewFinderWidgetControl) {
+ // Check whether platform supports DirectScreen ViewFinder
+ if (m_cameraEngine) {
+ if (m_cameraEngine->IsDirectViewFinderSupported())
+ m_viewfinderNativeType = EDirectScreenViewFinder;
+ else
+ m_viewfinderNativeType = EBitmapViewFinder;
+ }
+ else
+ return;
+
+ m_viewfinderDisplay = viewFinderWidgetControl->display();
+
+ if (m_viewfinderNativeType == EDirectScreenViewFinder) {
+ m_viewfinderDisplay->setPaintingEnabled(false); // No Qt Painter painting - Direct rendering
+ connect(m_viewfinderDisplay, SIGNAL(windowHandleChanged(RWindow *)), this, SLOT(resetViewfinderDisplay()));
+ } else {
+ m_viewfinderDisplay->setPaintingEnabled(true); // Qt Painter painting - Bitmap rendering
+ connect(this, SIGNAL(viewFinderFrameReady(const CFbsBitmap &)), m_viewfinderDisplay, SLOT(setFrame(const CFbsBitmap &)));
+ }
+
+ connect(m_viewfinderDisplay, SIGNAL(visibilityChanged(bool)), this, SLOT(handleVisibilityChange(bool)));
+ connect(m_viewfinderDisplay, SIGNAL(displayRectChanged(QRect, QRect)), this, SLOT(resetVideoWindowSize()));
+ connect(m_viewfinderDisplay, SIGNAL(windowHandleChanged(RWindow*)), this, SLOT(handleWindowChange(RWindow*)));
+
+ m_viewfinderSize = m_viewfinderDisplay->extentRect().size();
+ m_viewfinderOutput = viewfinderOutput;
+ m_viewfinderType = OutputTypeVideoWidget;
+ m_isViewFinderVisible = m_viewfinderDisplay->isVisible();
+
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ m_vfState = EVFIsConnectedNotStarted;
+ break;
+ case EVFNotConnectedIsStarted:
+ if (m_isViewFinderVisible)
+ m_vfState = EVFIsConnectedIsStartedIsVisible;
+ else
+ m_vfState = EVFIsConnectedIsStartedNotVisible;
+ break;
+ case EVFIsConnectedNotStarted:
+ case EVFIsConnectedIsStartedNotVisible:
+ case EVFIsConnectedIsStartedIsVisible:
+ // Already connected, state does not change
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+
+ if (m_vfState == EVFIsConnectedIsStartedIsVisible)
+ startViewfinder(true); // Internal start (i.e. start if started externally)
+ }
+}
+
+void S60CameraViewfinderEngine::setVideoRendererControl(QObject *viewfinderOutput)
+{
+ // Release old control if it has not already been done
+ if (m_viewfinderOutput)
+ releaseControl(m_viewfinderType);
+
+ // Rotate Camera if UI has rotated
+ checkAndRotateCamera();
+
+ S60VideoRendererControl* viewFinderRenderControl =
+ qobject_cast<S60VideoRendererControl*>(viewfinderOutput);
+
+ if (viewFinderRenderControl) {
+ m_viewfinderNativeType = EBitmapViewFinder; // Always Bitmap
+
+ connect(viewFinderRenderControl, SIGNAL(viewFinderSurfaceSet()),
+ this, SLOT(rendererSurfaceSet()));
+
+ Q_ASSERT(!viewFinderRenderControl->surface());
+ m_viewfinderOutput = viewfinderOutput;
+ m_viewfinderType = OutputTypeRenderer;
+ // RendererControl viewfinder is "visible" when surface is set
+ m_isViewFinderVisible = false;
+ if (EVFIsConnectedIsStartedIsVisible)
+ m_vfState = EVFIsConnectedIsStartedNotVisible;
+
+ // Use display resolution as default viewfinder resolution
+ m_viewfinderSize = QApplication::desktop()->screenGeometry().size();
+
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ m_vfState = EVFIsConnectedNotStarted;
+ break;
+ case EVFNotConnectedIsStarted:
+ m_vfState = EVFIsConnectedIsStartedIsVisible; // GraphicsItem "always visible" (FrameWork decides to draw/not draw)
+ break;
+ case EVFIsConnectedNotStarted:
+ case EVFIsConnectedIsStartedNotVisible:
+ case EVFIsConnectedIsStartedIsVisible:
+ // Already connected, state does not change
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+
+ if (m_vfState == EVFIsConnectedIsStartedIsVisible)
+ startViewfinder(true);
+ }
+}
+
+void S60CameraViewfinderEngine::setVideoWindowControl(QObject *viewfinderOutput)
+{
+ // Release old control if it has not already been done
+ if (m_viewfinderOutput)
+ releaseControl(m_viewfinderType);
+
+ // Rotate Camera if UI has rotated
+ checkAndRotateCamera();
+
+ S60VideoWindowControl* viewFinderWindowControl =
+ qobject_cast<S60VideoWindowControl*>(viewfinderOutput);
+
+ if (viewFinderWindowControl) {
+ // Check whether platform supports DirectScreen ViewFinder
+ if (m_cameraEngine) {
+ if (m_cameraEngine->IsDirectViewFinderSupported())
+ m_viewfinderNativeType = EDirectScreenViewFinder;
+ else
+ m_viewfinderNativeType = EBitmapViewFinder;
+ } else {
+ return;
+ }
+
+ m_viewfinderDisplay = viewFinderWindowControl->display();
+
+ if (m_viewfinderNativeType == EDirectScreenViewFinder) {
+ m_viewfinderDisplay->setPaintingEnabled(false); // No Qt Painter painting - Direct rendering
+ connect(m_viewfinderDisplay, SIGNAL(windowHandleChanged(RWindow *)), this, SLOT(resetViewfinderDisplay()));
+ } else {
+ m_viewfinderDisplay->setPaintingEnabled(true); // Qt Painter painting - Bitmap rendering
+ connect(this, SIGNAL(viewFinderFrameReady(const CFbsBitmap &)), m_viewfinderDisplay, SLOT(setFrame(const CFbsBitmap &)));
+ }
+
+ connect(m_viewfinderDisplay, SIGNAL(displayRectChanged(QRect, QRect)), this, SLOT(resetVideoWindowSize()));
+ connect(m_viewfinderDisplay, SIGNAL(visibilityChanged(bool)), this, SLOT(handleVisibilityChange(bool)));
+ connect(m_viewfinderDisplay, SIGNAL(windowHandleChanged(RWindow*)), this, SLOT(handleWindowChange(RWindow*)));
+
+ m_viewfinderSize = m_viewfinderDisplay->extentRect().size();
+ m_viewfinderOutput = viewfinderOutput;
+ m_viewfinderType = OutputTypeVideoWindow;
+ m_isViewFinderVisible = m_viewfinderDisplay->isVisible();
+
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ m_vfState = EVFIsConnectedNotStarted;
+ break;
+ case EVFNotConnectedIsStarted:
+ if (m_isViewFinderVisible)
+ m_vfState = EVFIsConnectedIsStartedIsVisible;
+ else
+ m_vfState = EVFIsConnectedIsStartedNotVisible;
+ break;
+ case EVFIsConnectedNotStarted:
+ case EVFIsConnectedIsStartedNotVisible:
+ case EVFIsConnectedIsStartedIsVisible:
+ // Already connected, state does not change
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+
+ if (m_vfState == EVFIsConnectedIsStartedIsVisible)
+ startViewfinder(true); // Internal start (i.e. start if started externally)
+ }
+}
+
+void S60CameraViewfinderEngine::releaseControl(ViewfinderOutputType type)
+{
+ if (m_vfState == EVFIsConnectedIsStartedIsVisible)
+ stopViewfinder(true);
+
+ if (m_viewfinderOutput) {
+ switch (type) {
+ case OutputTypeNotSet:
+ return;
+ case OutputTypeVideoWidget:
+ if (m_viewfinderType != OutputTypeVideoWidget)
+ return;
+ disconnect(m_viewfinderOutput);
+ m_viewfinderOutput->disconnect(this);
+ Q_ASSERT(m_viewfinderDisplay);
+ disconnect(m_viewfinderDisplay);
+ m_viewfinderDisplay->disconnect(this);
+ m_viewfinderDisplay = 0;
+ // Invalidate the extent rect
+ qobject_cast<S60VideoWidgetControl*>(m_viewfinderOutput)->setExtentRect(QRect());
+ break;
+ case OutputTypeVideoWindow:
+ if (m_viewfinderType != OutputTypeVideoWindow)
+ return;
+ disconnect(m_viewfinderOutput);
+ m_viewfinderOutput->disconnect(this);
+ Q_ASSERT(m_viewfinderDisplay);
+ disconnect(m_viewfinderDisplay);
+ m_viewfinderDisplay->disconnect(this);
+ m_viewfinderDisplay = 0;
+ break;
+ case OutputTypeRenderer:
+ if (m_viewfinderType != OutputTypeRenderer)
+ return;
+ disconnect(m_viewfinderOutput);
+ m_viewfinderOutput->disconnect(this);
+ if (m_viewfinderSurface)
+ m_viewfinderSurface->disconnect(this);
+ disconnect(this, SIGNAL(viewFinderFrameReady(const CFbsBitmap &)),
+ this, SLOT(viewFinderBitmapReady(const CFbsBitmap &)));
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("Unexpected viewfinder error."));
+ return;
+ }
+ }
+
+ Q_ASSERT(!m_viewfinderDisplay);
+ m_viewfinderOutput = 0;
+ m_viewfinderType = OutputTypeNotSet;
+
+ // Update state
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ case EVFNotConnectedIsStarted:
+ // Do nothing
+ break;
+ case EVFIsConnectedNotStarted:
+ m_vfState = EVFNotConnectedNotStarted;
+ break;
+ case EVFIsConnectedIsStartedNotVisible:
+ case EVFIsConnectedIsStartedIsVisible:
+ m_vfState = EVFNotConnectedIsStarted;
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+}
+
+void S60CameraViewfinderEngine::startViewfinder(const bool internalStart)
+{
+ if (!internalStart) {
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ m_vfState = EVFNotConnectedIsStarted;
+ break;
+ case EVFIsConnectedNotStarted:
+ if (m_isViewFinderVisible)
+ m_vfState = EVFIsConnectedIsStartedIsVisible;
+ else
+ m_vfState = EVFIsConnectedIsStartedNotVisible;
+ break;
+ case EVFNotConnectedIsStarted:
+ case EVFIsConnectedIsStartedNotVisible:
+ case EVFIsConnectedIsStartedIsVisible:
+ // Already started, state does not change
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+ }
+
+ // Start viewfinder
+ if (m_vfState == EVFIsConnectedIsStartedIsVisible) {
+
+ if (!m_cameraEngine)
+ return;
+
+ if (m_viewfinderNativeType == EDirectScreenViewFinder) {
+
+ if (RWindow *window = m_viewfinderDisplay ? m_viewfinderDisplay->windowHandle() : 0) {
+ m_window = window;
+ } else {
+ emit error(QCamera::CameraError, tr("Requesting window for viewfinder failed."));
+ return;
+ }
+
+ const QRect extentRect = m_viewfinderDisplay ? m_viewfinderDisplay->extentRect() : QRect();
+ const QRect clipRect = m_viewfinderDisplay ? m_viewfinderDisplay->clipRect() : QRect();
+
+ TRect extentRectSymbian = qRect2TRect(extentRect);
+ TRect clipRectSymbian = qRect2TRect(clipRect);
+ TRAPD(err, m_cameraEngine->StartDirectViewFinderL(m_wsSession, m_screenDevice, *m_window, extentRectSymbian, clipRectSymbian));
+ if (err) {
+ if (err == KErrNotSupported) {
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested viewfinder size is not supported."));
+ } else {
+ emit error(QCamera::CameraError, tr("Starting viewfinder failed."));
+ }
+ return;
+ }
+
+ m_actualViewFinderSize = QSize(extentRectSymbian.Size().iWidth, extentRectSymbian.Size().iHeight);
+ m_viewfinderAspectRatio = qreal(m_actualViewFinderSize.width()) / qreal(m_actualViewFinderSize.height());
+
+ } else { // Bitmap ViewFinder
+ TSize size = TSize(m_viewfinderSize.width(), m_viewfinderSize.height());
+
+ if( m_viewfinderType == OutputTypeRenderer && m_viewfinderSurface) {
+ if (!m_surfaceFormat.isValid()) {
+ emit error(QCamera::NotSupportedFeatureError, tr("Invalid surface format."));
+ return;
+ }
+
+ // Start rendering to surface with correct size and format
+ if (!m_viewfinderSurface->isFormatSupported(m_surfaceFormat) ||
+ !m_viewfinderSurface->start(m_surfaceFormat)) {
+ emit error(QCamera::NotSupportedFeatureError, tr("Failed to start surface."));
+ return;
+ }
+
+ if (!m_viewfinderSurface->isActive())
+ return;
+ }
+
+ TRAPD(vfErr, m_cameraEngine->StartViewFinderL(size));
+ if (vfErr) {
+ if (vfErr == KErrNotSupported) {
+ emit error(QCamera::NotSupportedFeatureError, tr("Requested viewfinder size is not supported."));
+ } else {
+ emit error(QCamera::CameraError, tr("Starting viewfinder failed."));
+ }
+ return;
+ }
+
+ m_actualViewFinderSize = QSize(size.iWidth, size.iHeight);
+ m_viewfinderAspectRatio = qreal(m_actualViewFinderSize.width()) / qreal(m_actualViewFinderSize.height());
+
+ // Notify control about the frame size (triggers frame position calculation)
+ if (m_viewfinderDisplay) {
+ m_viewfinderDisplay->setNativeSize(m_actualViewFinderSize);
+ } else {
+ if (m_viewfinderType == OutputTypeRenderer && m_viewfinderSurface) {
+ m_viewfinderSurface->stop();
+ QVideoSurfaceFormat format = m_viewfinderSurface->surfaceFormat();
+ format.setFrameSize(QSize(m_actualViewFinderSize));
+ format.setViewport(QRect(0, 0, m_actualViewFinderSize.width(), m_actualViewFinderSize.height()));
+ m_viewfinderSurface->start(format);
+ }
+ }
+ }
+ }
+}
+
+void S60CameraViewfinderEngine::stopViewfinder(const bool internalStop)
+{
+ // Stop if viewfinder is started
+ if (m_vfState == EVFIsConnectedIsStartedIsVisible) {
+ if (m_viewfinderOutput && m_viewfinderType == OutputTypeRenderer && m_viewfinderSurface) {
+ // Stop surface if one still exists
+ m_viewfinderSurface->stop();
+ }
+
+ if (m_cameraEngine)
+ m_cameraEngine->StopViewFinder();
+ }
+
+ // Update state
+ if (!internalStop) {
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ case EVFIsConnectedNotStarted:
+ // Discard
+ break;
+ case EVFNotConnectedIsStarted:
+ m_vfState = EVFNotConnectedNotStarted;
+ break;
+ case EVFIsConnectedIsStartedNotVisible:
+ case EVFIsConnectedIsStartedIsVisible:
+ m_vfState = EVFIsConnectedNotStarted;
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+ }
+}
+
+void S60CameraViewfinderEngine::MceoViewFinderFrameReady(CFbsBitmap& aFrame)
+{
+ emit viewFinderFrameReady(aFrame);
+ if (m_cameraEngine)
+ m_cameraEngine->ReleaseViewFinderBuffer();
+}
+
+void S60CameraViewfinderEngine::resetViewfinderSize(const QSize size)
+{
+ m_viewfinderSize = size;
+
+ if(m_vfState != EVFIsConnectedIsStartedIsVisible) {
+ // Set native size to Window/Renderer Control
+ if (m_viewfinderDisplay)
+ m_viewfinderDisplay->setNativeSize(m_actualViewFinderSize);
+ return;
+ }
+
+ stopViewfinder(true);
+
+ startViewfinder(true);
+}
+
+void S60CameraViewfinderEngine::resetVideoWindowSize()
+{
+ if (m_viewfinderDisplay)
+ resetViewfinderSize(m_viewfinderDisplay->extentRect().size());
+}
+
+void S60CameraViewfinderEngine::resetViewfinderDisplay()
+{
+ if (m_viewfinderNativeType == EDirectScreenViewFinder) {
+
+ switch (m_viewfinderType) {
+ case OutputTypeVideoWidget: {
+ if (!m_viewfinderOutput)
+ return;
+
+ // First stop viewfinder
+ stopViewfinder(true);
+
+ RWindow *window = m_viewfinderDisplay->windowHandle();
+ if (!window) {
+ return;
+ }
+
+ // Then start it with the new WindowID
+ startViewfinder(true);
+ break;
+ }
+ case OutputTypeRenderer:
+ case OutputTypeVideoWindow:
+ // Do nothing
+ break;
+
+ default:
+ // Not ViewFinder Output has been set, Discard
+ break;
+ }
+ }
+}
+
+void S60CameraViewfinderEngine::rendererSurfaceSet()
+{
+ S60VideoRendererControl* viewFinderRenderControl =
+ qobject_cast<S60VideoRendererControl*>(m_viewfinderOutput);
+
+ // Reset old surface if needed
+ if (m_viewfinderSurface) {
+ handleVisibilityChange(false);
+ disconnect(m_viewfinderSurface);
+ if (viewFinderRenderControl->surface())
+ stopViewfinder(true); // Temporary stop
+ else
+ stopViewfinder(); // Stop for good
+ m_viewfinderSize = QApplication::desktop()->screenGeometry().size();
+ m_viewfinderSurface = 0;
+ }
+
+ // Set new surface
+ m_viewfinderSurface = viewFinderRenderControl->surface();
+ if (!m_viewfinderSurface)
+ return;
+ if (!m_viewfinderSurface->nativeResolution().isEmpty()) {
+ if (m_viewfinderSurface->nativeResolution() != m_viewfinderSize)
+ resetViewfinderSize(m_viewfinderSurface->nativeResolution());
+ }
+
+ connect(m_viewfinderSurface, SIGNAL(nativeResolutionChanged(const QSize&)),
+ this, SLOT(resetViewfinderSize(QSize)));
+
+ // Set Surface Properties
+ if (m_viewfinderSurface->supportedPixelFormats().contains(QVideoFrame::Format_RGB32))
+ m_surfaceFormat = QVideoSurfaceFormat(m_actualViewFinderSize, QVideoFrame::Format_RGB32);
+ else if (m_viewfinderSurface->supportedPixelFormats().contains(QVideoFrame::Format_ARGB32))
+ m_surfaceFormat = QVideoSurfaceFormat(m_actualViewFinderSize, QVideoFrame::Format_ARGB32);
+ else {
+ return;
+ }
+ m_surfaceFormat.setFrameRate(KViewfinderFrameRate);
+ m_surfaceFormat.setYCbCrColorSpace(QVideoSurfaceFormat::YCbCr_Undefined); // EColor16MU (compatible with EColor16MA)
+ m_surfaceFormat.setPixelAspectRatio(1,1); // PAR 1:1
+
+
+ connect(this, SIGNAL(viewFinderFrameReady(const CFbsBitmap &)),
+ this, SLOT(viewFinderBitmapReady(const CFbsBitmap &)));
+
+ // Surface set, viewfinder is "visible"
+ handleVisibilityChange(true);
+}
+
+void S60CameraViewfinderEngine::viewFinderBitmapReady(const CFbsBitmap &bitmap)
+{
+ CFbsBitmap *bitmapPtr = const_cast<CFbsBitmap*>(&bitmap);
+ QPixmap pixmap = QPixmap::fromSymbianCFbsBitmap(bitmapPtr);
+
+ QImage newImage = pixmap.toImage();
+ if (newImage.format() != QImage::Format_ARGB32 &&
+ newImage.format() != QImage::Format_RGB32) {
+ newImage = newImage.convertToFormat(QImage::Format_RGB32);
+ }
+
+ if (!newImage.isNull()) {
+ QVideoFrame newFrame(newImage);
+ if (newFrame.isValid()) {
+ if (!m_viewfinderSurface->present(newFrame)) {
+ // Presenting may fail even if there are no errors (e.g. busy)
+ if (m_viewfinderSurface->error()) {
+ if (m_vfErrorsSignalled < KMaxVFErrorsSignalled) {
+ emit error(QCamera::CameraError, tr("Presenting viewfinder frame failed."));
+ ++m_vfErrorsSignalled;
+ }
+ }
+ }
+ } else {
+ if (m_vfErrorsSignalled < KMaxVFErrorsSignalled) {
+ emit error(QCamera::CameraError, tr("Invalid viewfinder frame was received."));
+ ++m_vfErrorsSignalled;
+ }
+ }
+
+ } else {
+ if (m_vfErrorsSignalled < KMaxVFErrorsSignalled) {
+ emit error(QCamera::CameraError, tr("Failed to convert viewfinder frame to presentable image."));
+ ++m_vfErrorsSignalled;
+ }
+ }
+}
+
+void S60CameraViewfinderEngine::handleVisibilityChange(const bool isVisible)
+{
+ if (m_isViewFinderVisible == isVisible)
+ return;
+
+ m_isViewFinderVisible = isVisible;
+
+ if (m_isViewFinderVisible) {
+ switch (m_vfState) {
+ case EVFNotConnectedNotStarted:
+ case EVFIsConnectedNotStarted:
+ case EVFNotConnectedIsStarted:
+ case EVFIsConnectedIsStartedIsVisible:
+ // Discard
+ break;
+ case EVFIsConnectedIsStartedNotVisible:
+ m_vfState = EVFIsConnectedIsStartedIsVisible;
+ break;
+ default:
+ emit error(QCamera::CameraError, tr("General viewfinder error."));
+ break;
+ }
+ startViewfinder(true);
+ } else {
+ // Stopping takes care of the state change
+ stopViewfinder(true);
+ }
+}
+
+void S60CameraViewfinderEngine::handleWindowChange(RWindow *handle)
+{
+ stopViewfinder(true);
+
+ if (handle) // New handle available, start viewfinder
+ startViewfinder(true);
+}
+
+void S60CameraViewfinderEngine::checkAndRotateCamera()
+{
+ bool isUiNowLandscape = false;
+ QDesktopWidget* desktopWidget = QApplication::desktop();
+ QRect screenRect = desktopWidget->screenGeometry();
+
+ if (screenRect.width() > screenRect.height())
+ isUiNowLandscape = true;
+ else
+ isUiNowLandscape = false;
+
+ // Rotate camera if possible
+ if (isUiNowLandscape != m_uiLandscape) {
+ stopViewfinder(true);
+
+ // Request orientation reset
+ m_cameraControl->resetCameraOrientation();
+ }
+ m_uiLandscape = isUiNowLandscape;
+}
+
+void S60CameraViewfinderEngine::handleContentAspectRatioChange(const QSize& newSize)
+{
+ qreal newAspectRatio = qreal(newSize.width()) / qreal(newSize.height());
+ // Check if aspect ratio changed
+ if (qFuzzyCompare(newAspectRatio, m_viewfinderAspectRatio))
+ return;
+
+ // Resize viewfinder by reducing either width or height to comply with the new aspect ratio
+ QSize newNativeResolution;
+ if (newAspectRatio > m_viewfinderAspectRatio) { // New AspectRatio is wider => Reduce height
+ newNativeResolution = QSize(m_actualViewFinderSize.width(), (m_actualViewFinderSize.width() / newAspectRatio));
+ } else { // New AspectRatio is higher => Reduce width
+ newNativeResolution = QSize((m_actualViewFinderSize.height() * newAspectRatio), m_actualViewFinderSize.height());
+ }
+
+ // Notify aspect ratio change (use actual content size to notify that)
+ // This triggers item size/position re-calculation
+ if (m_viewfinderDisplay)
+ m_viewfinderDisplay->setNativeSize(newNativeResolution);
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60cameraviewfinderengine.h b/src/plugins/symbian/ecam/s60cameraviewfinderengine.h
new file mode 100644
index 000000000..c5df760d9
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60cameraviewfinderengine.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** 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 S60CAMERAVIEWFINDERENGINE_H
+#define S60CAMERAVIEWFINDERENGINE_H
+
+#include <QtCore/qsize.h>
+#include <QtGui/qpixmap.h>
+
+#include <qvideosurfaceformat.h>
+
+#include "s60cameraengineobserver.h"
+
+class CCameraEngine;
+class S60CameraControl;
+class QAbstractVideoSurface;
+
+// For DirectScreen ViewFinder
+class RWsSession;
+class CWsScreenDevice;
+class RWindowBase;
+class RWindow;
+class QDesktopWidget;
+
+class S60VideoDisplay;
+
+/*
+ * Class implementing video output selection for the viewfinder and the handler of
+ * all common viewfinder operations.
+ */
+class S60CameraViewfinderEngine : public QObject, public MCameraViewfinderObserver
+{
+ Q_OBJECT
+
+public: // Enums
+
+ /*
+ * Defines whether viewfinder output backend control is of type
+ * QVideoWidgetControl, QVideoRendererControl or QVideoWindowControl
+ */
+ enum ViewfinderOutputType {
+ OutputTypeNotSet = 0, // No viewfinder output connected
+ OutputTypeVideoWidget, // Using QVideoWidget
+ OutputTypeRenderer, // (Using QGraphicsVideoItem with) QVideoRendererControl
+ OutputTypeVideoWindow // Using QGraphicsVideoItem with QVideoWindow
+ };
+
+public: // Constructor & Destructor
+
+ S60CameraViewfinderEngine(S60CameraControl *control,
+ CCameraEngine *engine,
+ QObject *parent = 0);
+ ~S60CameraViewfinderEngine();
+
+public: // Methods
+
+ // Setting Viewfinder Output
+ void setVideoWidgetControl(QObject *viewfinderOutput);
+ void setVideoRendererControl(QObject *viewfinderOutput);
+ void setVideoWindowControl(QObject *viewfinderOutput);
+ void releaseControl(ViewfinderOutputType type);
+
+ // Controls
+ void startViewfinder(const bool internalStart = false);
+ void stopViewfinder(const bool internalStop = false);
+
+ // Start using new CameraEngine
+ void setNewCameraEngine(CCameraEngine *engine);
+
+protected: // MCameraViewfinderObserver
+
+ void MceoViewFinderFrameReady(CFbsBitmap& aFrame);
+
+private: // Internal operation
+
+ void checkAndRotateCamera();
+
+signals:
+
+ void error(int error, const QString &errorString);
+ void viewFinderFrameReady(const CFbsBitmap &bitmap);
+
+private slots:
+
+ void resetViewfinderSize(const QSize size);
+ void resetVideoWindowSize();
+ void resetViewfinderDisplay();
+ void viewFinderBitmapReady(const CFbsBitmap &bitmap);
+ void handleVisibilityChange(const bool isVisible);
+ void handleWindowChange(RWindow *handle);
+ void handleDesktopResize(int screen);
+ void handleContentAspectRatioChange(const QSize& newSize);
+ void rendererSurfaceSet();
+
+private: // Enums
+
+ /*
+ * Defines the internal state of the viewfinder. ViewFinder will only be
+ * started if output is connected to Camera and Camera is started (and
+ * ViewFinder widget is visible in case of QVideoWidget).
+ */
+ enum ViewFinderState {
+ EVFNotConnectedNotStarted = 0, // 0 - No output connected, viewfinder is not started
+ EVFNotConnectedIsStarted, // 1 - No output connected, viewfinder is started
+ EVFIsConnectedNotStarted, // 2 - Output is connected, viewfinder is not started
+ EVFIsConnectedIsStartedNotVisible, // 3 - Output is connected, viewfinder is started but is not visible
+ EVFIsConnectedIsStartedIsVisible // 4 - Output is connected, viewfinder is started and is visible
+ };
+
+ /*
+ * The native type of ViewFinder. DirectScreen ViewFinder is used with
+ * QVideoWidget if support for it is available in the platform. For
+ * QGraphicsVideoItem Bitmap ViewFinder is always used.
+ */
+ enum NativeViewFinderType {
+ EBitmapViewFinder = 0,
+ EDirectScreenViewFinder
+ };
+
+private: // Data
+
+ CCameraEngine *m_cameraEngine;
+ S60CameraControl *m_cameraControl;
+ QObject *m_viewfinderOutput;
+ S60VideoDisplay *m_viewfinderDisplay;
+ QAbstractVideoSurface *m_viewfinderSurface; // Used only by QVideoRendererControl
+ RWsSession &m_wsSession;
+ CWsScreenDevice &m_screenDevice;
+ RWindowBase *m_window;
+ QDesktopWidget *m_desktopWidget;
+ ViewFinderState m_vfState;
+ QSize m_viewfinderSize;
+ // Actual viewfinder size, which may differ from requested
+ // (m_viewfinderSize), if the size/aspect ratio was not supported.
+ QSize m_actualViewFinderSize;
+ qreal m_viewfinderAspectRatio;
+ ViewfinderOutputType m_viewfinderType;
+ NativeViewFinderType m_viewfinderNativeType;
+ QVideoSurfaceFormat m_surfaceFormat; // Used only by QVideoRendererControl
+ bool m_isViewFinderVisible;
+ bool m_uiLandscape; // For detecting UI rotation
+ int m_vfErrorsSignalled;
+};
+
+#endif // S60CAMERAVIEWFINDERENGINE_H
diff --git a/src/plugins/symbian/ecam/s60imagecapturesession.cpp b/src/plugins/symbian/ecam/s60imagecapturesession.cpp
new file mode 100644
index 000000000..16d240c7b
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60imagecapturesession.cpp
@@ -0,0 +1,1884 @@
+/****************************************************************************
+**
+** 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 <QtCore/qstring.h>
+#include <QtCore/qdir.h>
+
+#include "s60imagecapturesession.h"
+#include "s60videowidgetcontrol.h"
+#include "s60cameraservice.h"
+#include "s60cameraconstants.h"
+
+#include <fbs.h> // CFbsBitmap
+#include <pathinfo.h>
+#include <imageconversion.h> // ICL Decoder (for SnapShot) & Encoder (for Bitmap Images)
+
+S60ImageCaptureDecoder::S60ImageCaptureDecoder(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC8 *data,
+ const TDesC16 *fileName) :
+ CActive(CActive::EPriorityStandard),
+ m_imageSession(imageSession),
+ m_fs(fileSystemAccess),
+ m_jpegImageData(data),
+ m_jpegImageFile(fileName),
+ m_fileInput(false)
+{
+ CActiveScheduler::Add(this);
+}
+
+S60ImageCaptureDecoder::~S60ImageCaptureDecoder()
+{
+ if (m_imageDecoder) {
+ delete m_imageDecoder;
+ m_imageDecoder = 0;
+ }
+}
+
+S60ImageCaptureDecoder *S60ImageCaptureDecoder::FileNewL(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC16 *fileName)
+{
+ S60ImageCaptureDecoder* self = new (ELeave) S60ImageCaptureDecoder(imageSession,
+ fileSystemAccess,
+ 0,
+ fileName);
+ CleanupStack::PushL(self);
+ self->ConstructL(true);
+ CleanupStack::Pop(self);
+ return self;
+}
+
+S60ImageCaptureDecoder *S60ImageCaptureDecoder::DataNewL(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC8 *data)
+{
+ S60ImageCaptureDecoder* self = new (ELeave) S60ImageCaptureDecoder(imageSession,
+ fileSystemAccess,
+ data,
+ 0);
+ CleanupStack::PushL(self);
+ self->ConstructL(false);
+ CleanupStack::Pop(self);
+ return self;
+}
+
+void S60ImageCaptureDecoder::ConstructL(const bool fileInput)
+{
+ if (fileInput) {
+ if (!m_imageSession || !m_fs || !m_jpegImageFile)
+ User::Leave(KErrGeneral);
+ m_imageDecoder = CImageDecoder::FileNewL(*m_fs, *m_jpegImageFile);
+ } else {
+ if (!m_imageSession || !m_fs || !m_jpegImageData)
+ User::Leave(KErrGeneral);
+ m_imageDecoder = CImageDecoder::DataNewL(*m_fs, *m_jpegImageData);
+ }
+}
+
+void S60ImageCaptureDecoder::decode(CFbsBitmap *destBitmap)
+{
+ if (m_imageDecoder) {
+ m_imageDecoder->Convert(&iStatus, *destBitmap, 0);
+ SetActive();
+ }
+ else
+ m_imageSession->setError(KErrGeneral, QLatin1String("Preview image creation failed."));
+}
+
+TFrameInfo *S60ImageCaptureDecoder::frameInfo()
+{
+ if (m_imageDecoder) {
+ m_frameInfo = m_imageDecoder->FrameInfo();
+ return &m_frameInfo;
+ }
+ else
+ return 0;
+}
+
+void S60ImageCaptureDecoder::RunL()
+{
+ m_imageSession->handleImageDecoded(iStatus.Int());
+}
+
+void S60ImageCaptureDecoder::DoCancel()
+{
+ if (m_imageDecoder)
+ m_imageDecoder->Cancel();
+}
+
+TInt S60ImageCaptureDecoder::RunError(TInt aError)
+{
+ m_imageSession->setError(aError, QLatin1String("Preview image creation failed."));
+ return KErrNone;
+}
+
+//=============================================================================
+
+S60ImageCaptureEncoder::S60ImageCaptureEncoder(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC16 *fileName,
+ TInt jpegQuality) :
+ CActive(CActive::EPriorityStandard),
+ m_imageSession(imageSession),
+ m_fileSystemAccess(fileSystemAccess),
+ m_fileName(fileName),
+ m_jpegQuality(jpegQuality)
+{
+ CActiveScheduler::Add(this);
+}
+
+S60ImageCaptureEncoder::~S60ImageCaptureEncoder()
+{
+ if (m_frameImageData) {
+ delete m_frameImageData;
+ m_frameImageData = 0;
+ }
+ if (m_imageEncoder) {
+ delete m_imageEncoder;
+ m_imageEncoder = 0;
+ }
+}
+
+S60ImageCaptureEncoder *S60ImageCaptureEncoder::NewL(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC16 *fileName,
+ TInt jpegQuality)
+{
+ S60ImageCaptureEncoder* self = new (ELeave) S60ImageCaptureEncoder(imageSession,
+ fileSystemAccess,
+ fileName,
+ jpegQuality);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+void S60ImageCaptureEncoder::ConstructL()
+{
+ if (!m_imageSession || !m_fileSystemAccess || !m_fileName)
+ User::Leave(KErrGeneral);
+
+ m_imageEncoder = CImageEncoder::FileNewL(*m_fileSystemAccess,
+ *m_fileName,
+ CImageEncoder::EOptionNone,
+ KImageTypeJPGUid);
+ CleanupStack::PushL(m_imageEncoder);
+
+ // Set Jpeg Quality
+ m_frameImageData = CFrameImageData::NewL();
+ CleanupStack::PushL(m_frameImageData);
+
+ TJpegImageData* jpegFormat = new( ELeave ) TJpegImageData;
+ CleanupStack::PushL(jpegFormat);
+
+ jpegFormat->iQualityFactor = m_jpegQuality;
+
+ // jpegFormat (TJpegImageData) ownership transferred to m_frameImageData (CFrameImageData)
+ User::LeaveIfError( m_frameImageData->AppendImageData(jpegFormat));
+
+ CleanupStack::Pop(jpegFormat);
+ CleanupStack::Pop(m_frameImageData);
+ CleanupStack::Pop(m_imageEncoder);
+}
+
+void S60ImageCaptureEncoder::encode(CFbsBitmap *sourceBitmap)
+{
+ if (m_imageEncoder) {
+ m_imageEncoder->Convert(&iStatus, *sourceBitmap, m_frameImageData);
+ SetActive();
+ }
+ else
+ m_imageSession->setError(KErrGeneral, QLatin1String("Saving image to file failed."));
+}
+
+void S60ImageCaptureEncoder::RunL()
+{
+ m_imageSession->handleImageEncoded(iStatus.Int());
+}
+
+void S60ImageCaptureEncoder::DoCancel()
+{
+ if (m_imageEncoder)
+ m_imageEncoder->Cancel();
+}
+
+TInt S60ImageCaptureEncoder::RunError(TInt aError)
+{
+ m_imageSession->setError(aError, QLatin1String("Saving image to file failed."));
+ return KErrNone;
+}
+
+//=============================================================================
+
+S60ImageCaptureSession::S60ImageCaptureSession(QObject *parent) :
+ QObject(parent),
+ m_cameraEngine(0),
+ m_advancedSettings(0),
+ m_cameraInfo(0),
+ m_previewBitmap(0),
+ m_activeScheduler(0),
+ m_fileSystemAccess(0),
+ m_imageDecoder(0),
+ m_imageEncoder(0),
+ m_error(KErrNone),
+ m_activeDeviceIndex(KDefaultCameraDevice),
+ m_cameraStarted(false),
+ m_icState(EImageCaptureNotPrepared),
+ m_currentCodec(QString()),
+ m_captureSize(QSize()),
+ m_symbianImageQuality(QtMultimediaKit::HighQuality * KSymbianImageQualityCoefficient),
+ m_captureSettingsSet(false),
+ m_stillCaptureFileName(QString()),
+ m_requestedStillCaptureFileName(QString()),
+ m_currentImageId(0),
+ m_captureWhenReady(false),
+ m_previewDecodingOngoing(false),
+ m_previewInWaitLoop(false)
+{
+ // Define supported image codecs
+ m_supportedImageCodecs << "image/jpeg";
+
+ initializeImageCaptureSettings();
+
+ // Install ActiveScheduler if needed
+ if (!CActiveScheduler::Current()) {
+ m_activeScheduler = new CActiveScheduler;
+ CActiveScheduler::Install(m_activeScheduler);
+ }
+}
+
+S60ImageCaptureSession::~S60ImageCaptureSession()
+{
+ // Delete AdvancedSettings (Should already be destroyed by CameraControl)
+ deleteAdvancedSettings();
+
+ m_formats.clear();
+ m_supportedImageCodecs.clear();
+
+ if (m_imageDecoder) {
+ m_imageDecoder->Cancel();
+ delete m_imageDecoder;
+ m_imageDecoder = 0;
+ }
+ if (m_imageEncoder) {
+ m_imageEncoder->Cancel();
+ delete m_imageEncoder;
+ m_imageEncoder = 0;
+ }
+
+ if (m_previewBitmap) {
+ delete m_previewBitmap;
+ m_previewBitmap = 0;
+ }
+
+ // Uninstall ActiveScheduler if needed
+ if (m_activeScheduler) {
+ CActiveScheduler::Install(0);
+ delete m_activeScheduler;
+ m_activeScheduler = 0;
+ }
+}
+
+CCamera::TFormat S60ImageCaptureSession::defaultImageFormat()
+{
+ // Primary Camera
+ if (m_activeDeviceIndex == 0)
+ return KDefaultImageFormatPrimaryCam;
+
+ // Secondary Camera or other
+ else
+ return KDefaultImageFormatSecondaryCam;
+}
+
+bool S60ImageCaptureSession::isDeviceReady()
+{
+#ifdef Q_CC_NOKIAX86 // Emulator
+ return true;
+#endif
+
+ if (m_cameraEngine)
+ return m_cameraEngine->IsCameraReady();
+
+ return false;
+}
+
+void S60ImageCaptureSession::deleteAdvancedSettings()
+{
+ if (m_advancedSettings) {
+ delete m_advancedSettings;
+ m_advancedSettings = 0;
+ emit advancedSettingChanged();
+ }
+}
+
+void S60ImageCaptureSession::setCameraHandle(CCameraEngine* camerahandle)
+{
+ if (camerahandle) {
+ m_cameraEngine = camerahandle;
+ resetSession();
+
+ // Set default settings
+ initializeImageCaptureSettings();
+ }
+}
+
+void S60ImageCaptureSession::setCurrentDevice(TInt deviceindex)
+{
+ m_activeDeviceIndex = deviceindex;
+}
+
+void S60ImageCaptureSession::notifySettingsSet()
+{
+ m_captureSettingsSet = true;
+}
+
+void S60ImageCaptureSession::resetSession(bool errorHandling)
+{
+ // Delete old AdvancedSettings
+ deleteAdvancedSettings();
+
+ m_captureWhenReady = false;
+ m_previewDecodingOngoing = false;
+ m_previewInWaitLoop = false;
+ m_stillCaptureFileName = QString();
+ m_requestedStillCaptureFileName = QString();
+ m_icState = EImageCaptureNotPrepared;
+
+ m_error = KErrNone;
+ m_currentFormat = defaultImageFormat();
+
+ int err = KErrNone;
+ m_advancedSettings = S60CameraSettings::New(err, this, m_cameraEngine);
+ if (err == KErrNotSupported) {
+ m_advancedSettings = 0;
+#ifndef S60_31_PLATFORM // Post S60 3.1 Platform
+ // Adv. settings may not be supported for other than the Primary Camera
+ if (m_cameraEngine->CurrentCameraIndex() == 0)
+ setError(err, tr("Unexpected camera error."));
+#endif // !S60_31_PLATFORM
+ } else if (err != KErrNone) { // Other errors
+ m_advancedSettings = 0;
+ qWarning("Failed to create camera settings handler.");
+ if (errorHandling)
+ emit cameraError(QCamera::ServiceMissingError, tr("Failed to recover from error."));
+ else
+ setError(err, tr("Unexpected camera error."));
+ return;
+ }
+
+ if (m_advancedSettings) {
+ if (m_cameraEngine)
+ m_cameraEngine->SetAdvancedObserver(m_advancedSettings);
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+
+ updateImageCaptureFormats();
+
+ emit advancedSettingChanged();
+}
+
+S60CameraSettings* S60ImageCaptureSession::advancedSettings()
+{
+ return m_advancedSettings;
+}
+
+/*
+ * This function can be used both internally and from Control classes using
+ * this session. The error notification will go to the client application
+ * either through QCameraImageCapture (if captureError is true) or QCamera (if
+ * captureError is false, default) error signal.
+ */
+void S60ImageCaptureSession::setError(const TInt error,
+ const QString &description,
+ const bool captureError)
+{
+ if (error == KErrNone)
+ return;
+
+ m_error = error;
+ QCameraImageCapture::Error cameraError = fromSymbianErrorToQtMultimediaError(error);
+
+ if (captureError) {
+ emit this->captureError(m_currentImageId, cameraError, description);
+ if (cameraError != QCameraImageCapture::NotSupportedFeatureError)
+ resetSession(true);
+ } else {
+ emit this->cameraError(cameraError, description);
+ if (cameraError != QCamera::NotSupportedFeatureError)
+ resetSession(true);
+ }
+}
+
+QCameraImageCapture::Error S60ImageCaptureSession::fromSymbianErrorToQtMultimediaError(int aError)
+{
+ switch(aError) {
+ case KErrNone:
+ return QCameraImageCapture::NoError; // No errors have occurred
+ case KErrNotReady:
+ return QCameraImageCapture::NotReadyError; // Not ready for operation
+ case KErrNotSupported:
+ return QCameraImageCapture::NotSupportedFeatureError; // The feature is not supported
+ case KErrNoMemory:
+ return QCameraImageCapture::OutOfSpaceError; // Out of disk space
+ case KErrNotFound:
+ case KErrBadHandle:
+ return QCameraImageCapture::ResourceError; // No resources available
+
+ default:
+ return QCameraImageCapture::ResourceError; // Other error has occurred
+ }
+}
+
+int S60ImageCaptureSession::currentImageId() const
+{
+ return m_currentImageId;
+}
+
+void S60ImageCaptureSession::initializeImageCaptureSettings()
+{
+ if (m_captureSettingsSet)
+ return;
+
+ m_currentCodec = KDefaultImageCodec;
+ m_captureSize = QSize(-1, -1);
+ m_currentFormat = defaultImageFormat();
+
+ // Resolution
+ if (m_cameraEngine) {
+ QList<QSize> resolutions = supportedCaptureSizesForCodec(imageCaptureCodec());
+ foreach (QSize reso, resolutions) {
+ if ((reso.width() * reso.height()) > (m_captureSize.width() * m_captureSize.height()))
+ m_captureSize = reso;
+ }
+ } else {
+ m_captureSize = KDefaultImageResolution;
+ }
+
+ m_symbianImageQuality = KDefaultImageQuality;
+}
+
+/*
+ * This function selects proper format to be used for the captured image based
+ * on the requested image codec.
+ */
+CCamera::TFormat S60ImageCaptureSession::selectFormatForCodec(const QString &codec)
+{
+ CCamera::TFormat format = CCamera::EFormatMonochrome;
+
+ if (codec == "image/jpg" || codec == "image/jpeg") {
+ // Primary Camera
+ if (m_activeDeviceIndex == 0)
+ format = KDefaultImageFormatPrimaryCam;
+
+ // Secondary Camera or other
+ else
+ format = KDefaultImageFormatSecondaryCam;
+
+ return format;
+ }
+
+ setError(KErrNotSupported, tr("Failed to select color format to be used with image codec."));
+ return format;
+}
+
+int S60ImageCaptureSession::prepareImageCapture()
+{
+ if (m_cameraEngine) {
+ if (!m_cameraEngine->IsCameraReady()) {
+ // Reset state to make sure camera is prepared before capturing image
+ m_icState = EImageCaptureNotPrepared;
+ return KErrNotReady;
+ }
+
+ // First set the quality
+ CCamera *camera = m_cameraEngine->Camera();
+ if (camera)
+ camera->SetJpegQuality(m_symbianImageQuality);
+ else
+ setError(KErrNotReady, tr("Setting image quality failed."), true);
+
+ // Then prepare with correct resolution and format
+ TSize captureSize = TSize(m_captureSize.width(), m_captureSize.height());
+ TRAPD(symbianError, m_cameraEngine->PrepareL(captureSize, m_currentFormat));
+ if (!symbianError)
+ m_icState = EImageCapturePrepared;
+
+ // Check if CaptureSize was modified
+ if (captureSize.iWidth != m_captureSize.width() || captureSize.iHeight != m_captureSize.height())
+ m_captureSize = QSize(captureSize.iWidth, captureSize.iHeight);
+ emit captureSizeChanged(m_captureSize);
+
+#ifdef ECAM_PREVIEW_API
+ // Subscribe previews
+ MCameraPreviewObserver *observer = this;
+ m_cameraEngine->EnablePreviewProvider(observer);
+#endif // ECAM_PREVIEW_API
+
+ return symbianError;
+ }
+
+ return KErrGeneral;
+}
+
+void S60ImageCaptureSession::releaseImageCapture()
+{
+ // Make sure ImageCapture is prepared the next time it is being activated
+ m_icState = EImageCaptureNotPrepared;
+
+#ifdef ECAM_PREVIEW_API
+ // Cancel preview subscription
+ m_cameraEngine->DisablePreviewProvider();
+#endif // ECAM_PREVIEW_API
+}
+
+int S60ImageCaptureSession::capture(const QString &fileName)
+{
+ if (!m_cameraStarted) {
+ m_captureWhenReady = true;
+ m_requestedStillCaptureFileName = fileName; // Save name, it will be processed during actual capture
+ return 0;
+ }
+
+ if (m_icState < EImageCapturePrepared) {
+ int prepareSuccess = prepareImageCapture();
+ if (prepareSuccess) {
+ setError(prepareSuccess, tr("Failure during image capture preparation."), true);
+ return 0;
+ }
+ } else if (m_icState > EImageCapturePrepared) {
+ setError(KErrNotReady, tr("Previous operation is still ongoing."), true);
+ return 0;
+ }
+
+ m_icState = EImageCaptureCapturing;
+
+ // Give new ID for the new image
+ m_currentImageId += 1;
+
+ emit readyForCaptureChanged(false);
+
+ processFileName(fileName);
+
+ if (m_cameraEngine) {
+ TRAPD(err, m_cameraEngine->CaptureL());
+ setError(err, tr("Image capture failed."), true);
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."), true);
+ }
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ QImage *snapImage = new QImage(QLatin1String("C:/Data/testimage.jpg"));
+ emit imageExposed(m_currentImageId);
+ emit imageCaptured(m_currentImageId, *snapImage);
+ emit imageSaved(m_currentImageId, m_stillCaptureFileName);
+#endif // Q_CC_NOKIAX86
+
+ return m_currentImageId;
+}
+
+void S60ImageCaptureSession::cancelCapture()
+{
+ if (m_icState != EImageCaptureCapturing)
+ return;
+
+ if (m_cameraEngine)
+ m_cameraEngine->CancelCapture();
+
+ m_icState = EImageCapturePrepared;
+}
+
+void S60ImageCaptureSession::processFileName(const QString &fileName)
+{
+ // Empty FileName - Use default file name and path (C:\Data\Images\image.jpg)
+ if (fileName.isEmpty()) {
+ // Make sure default directory exists
+ QDir videoDir(QDir::rootPath());
+ if (!videoDir.exists(KDefaultImagePath))
+ videoDir.mkpath(KDefaultImagePath);
+ QString defaultFile = KDefaultImagePath;
+ defaultFile.append("\\");
+ defaultFile.append(KDefaultImageFileName);
+ m_stillCaptureFileName = defaultFile;
+
+ } else { // Not empty
+
+ QString fullFileName;
+
+ // Relative FileName
+ if (!fileName.contains(":")) {
+ // Extract file name and path from the URL
+ fullFileName = KDefaultImagePath;
+ if (fileName.at(0) != '\\')
+ fullFileName.append("\\");
+ fullFileName.append(QDir::toNativeSeparators(QDir::cleanPath(fileName)));
+
+ // Absolute FileName
+ } else {
+ // Extract file name and path from the given location
+ fullFileName = QDir::toNativeSeparators(QDir::cleanPath(fileName));
+ }
+
+ QString fileNameOnly = fullFileName.right(fullFileName.length() - fullFileName.lastIndexOf("\\") - 1);
+ QString directory = fullFileName.left(fullFileName.lastIndexOf("\\"));
+ if (directory.lastIndexOf("\\") == (directory.length() - 1))
+ directory = directory.left(directory.length() - 1);
+
+ // URL is Absolute path, not including file name
+ if (!fileNameOnly.contains(".")) {
+ if (fileNameOnly != "") {
+ directory.append("\\");
+ directory.append(fileNameOnly);
+ }
+ fileNameOnly = KDefaultImageFileName;
+ }
+
+ // Make sure absolute directory exists
+ QDir imageDir(QDir::rootPath());
+ if (!imageDir.exists(directory))
+ imageDir.mkpath(directory);
+
+ QString resolvedFileName = directory;
+ resolvedFileName.append("\\");
+ resolvedFileName.append(fileNameOnly);
+ m_stillCaptureFileName = resolvedFileName;
+ }
+}
+
+void S60ImageCaptureSession::MceoFocusComplete()
+{
+ emit focusStatusChanged(QCamera::Locked, QCamera::LockAcquired);
+}
+
+void S60ImageCaptureSession::MceoCapturedDataReady(TDesC8* aData)
+{
+ emit imageExposed(m_currentImageId);
+
+ m_icState = EImageCaptureWritingImage;
+
+ TFileName path = convertImagePath();
+
+ // Try to save image and inform if it was succcesful
+ TRAPD(err, saveImageL(aData, path));
+ if (err) {
+ if (m_previewDecodingOngoing)
+ m_previewDecodingOngoing = false; // Reset
+
+ setError(err, tr("Writing captured image to a file failed."), true);
+ m_icState = EImageCapturePrepared;
+ return;
+ }
+
+ m_icState = EImageCapturePrepared;
+
+}
+
+void S60ImageCaptureSession::MceoCapturedBitmapReady(CFbsBitmap* aBitmap)
+{
+ emit imageExposed(m_currentImageId);
+
+ m_icState = EImageCaptureWritingImage;
+
+ if(aBitmap)
+ {
+#ifndef ECAM_PREVIEW_API
+ if (m_previewDecodingOngoing) {
+ m_previewInWaitLoop = true;
+ CActiveScheduler::Start(); // Wait for the completion of the previous Preview generation
+ }
+
+ // Delete old instances if needed
+ if (m_imageDecoder) {
+ delete m_imageDecoder;
+ m_imageDecoder = 0;
+ }
+ if (m_previewBitmap) {
+ delete m_previewBitmap;
+ m_previewBitmap = 0;
+ }
+#endif // ECAM_CAMERA_API
+ if (m_imageEncoder) {
+ delete m_imageEncoder;
+ m_imageEncoder = 0;
+ }
+ if (m_fileSystemAccess) {
+ m_fileSystemAccess->Close();
+ delete m_fileSystemAccess;
+ m_fileSystemAccess = 0;
+ }
+
+ TInt saveError = KErrNone;
+ TFileName path = convertImagePath();
+
+ // Create FileSystem access
+ m_fileSystemAccess = new RFs;
+ if (!m_fileSystemAccess) {
+ setError(KErrNoMemory, tr("Failed to write captured image to a file."));
+ return;
+ }
+ saveError = m_fileSystemAccess->Connect();
+ if (saveError) {
+ setError(saveError, tr("Failed to write captured image to a file."));
+ return;
+ }
+
+ TRAP(saveError, m_imageEncoder = S60ImageCaptureEncoder::NewL(this,
+ m_fileSystemAccess,
+ &path,
+ m_symbianImageQuality));
+ if (saveError)
+ setError(saveError, tr("Saving captured image failed."), true);
+ m_previewDecodingOngoing = true;
+ m_imageEncoder->encode(aBitmap);
+
+ } else {
+ setError(KErrBadHandle, tr("Unexpected camera error."), true);
+ }
+
+ m_icState = EImageCapturePrepared;
+}
+
+void S60ImageCaptureSession::MceoHandleError(TCameraEngineError aErrorType, TInt aError)
+{
+ Q_UNUSED(aErrorType);
+ setError(aError, tr("General camera error."));
+}
+
+TFileName S60ImageCaptureSession::convertImagePath()
+{
+ TFileName path = KNullDesC();
+
+ // Convert to Symbian path
+ TPtrC16 attachmentPath(KNullDesC);
+
+ // Path is already included in filename
+ attachmentPath.Set(reinterpret_cast<const TUint16*>(QDir::toNativeSeparators(m_stillCaptureFileName).utf16()));
+ path.Append(attachmentPath);
+
+ return path;
+}
+
+/*
+ * Creates (asynchronously) Preview Image from Jpeg ImageBuffer and also
+ * writes Jpeg (synchronously) to a file.
+ */
+void S60ImageCaptureSession::saveImageL(TDesC8 *aData, TFileName &aPath)
+{
+ if (aData == 0)
+ setError(KErrGeneral, tr("Captured image data is not available."), true);
+
+ if (aPath.Size() > 0) {
+#ifndef ECAM_PREVIEW_API
+ if (m_previewDecodingOngoing) {
+ m_previewInWaitLoop = true;
+ CActiveScheduler::Start(); // Wait for the completion of the previous Preview generation
+ }
+
+ // Delete old instances if needed
+ if (m_imageDecoder) {
+ delete m_imageDecoder;
+ m_imageDecoder = 0;
+ }
+ if (m_previewBitmap) {
+ delete m_previewBitmap;
+ m_previewBitmap = 0;
+ }
+#endif // ECAM_PREVIEW_API
+ if (m_fileSystemAccess) {
+ m_fileSystemAccess->Close();
+ delete m_fileSystemAccess;
+ m_fileSystemAccess = 0;
+ }
+
+ RFs *fileSystemAccess = new (ELeave) RFs;
+ User::LeaveIfError(fileSystemAccess->Connect());
+ CleanupClosePushL(*fileSystemAccess);
+
+#ifndef ECAM_PREVIEW_API
+ // Generate Thumbnail to be used as Preview
+ S60ImageCaptureDecoder *imageDecoder = S60ImageCaptureDecoder::DataNewL(this, fileSystemAccess, aData);
+ CleanupStack::PushL(imageDecoder);
+
+ // Set proper Preview Size
+ TSize scaledSize((m_captureSize.width() / KSnapshotDownScaleFactor), (m_captureSize.height() / KSnapshotDownScaleFactor));
+ if (scaledSize.iWidth < KSnapshotMinWidth || scaledSize.iHeight < KSnapshotMinHeight)
+ scaledSize.SetSize((m_captureSize.width() / (KSnapshotDownScaleFactor/2)), (m_captureSize.height() / (KSnapshotDownScaleFactor/2)));
+ if (scaledSize.iWidth < KSnapshotMinWidth || scaledSize.iHeight < KSnapshotMinHeight)
+ scaledSize.SetSize((m_captureSize.width() / (KSnapshotDownScaleFactor/4)), (m_captureSize.height() / (KSnapshotDownScaleFactor/4)));
+ if (scaledSize.iWidth < KSnapshotMinWidth || scaledSize.iHeight < KSnapshotMinHeight)
+ scaledSize.SetSize(m_captureSize.width(), m_captureSize.height());
+
+ TFrameInfo *info = imageDecoder->frameInfo();
+ if (!info) {
+ setError(KErrGeneral, tr("Preview image creation failed."));
+ return;
+ }
+
+ CFbsBitmap *previewBitmap = new (ELeave) CFbsBitmap;
+ CleanupStack::PushL(previewBitmap);
+ TInt bitmapCreationErr = previewBitmap->Create(scaledSize, info->iFrameDisplayMode);
+ if (bitmapCreationErr) {
+ setError(bitmapCreationErr, tr("Preview creation failed."));
+ return;
+ }
+
+ // Jpeg conversion completes in RunL
+ m_previewDecodingOngoing = true;
+ imageDecoder->decode(previewBitmap);
+#endif // ECAM_PREVIEW_API
+
+ RFile file;
+ TInt fileWriteErr = KErrNone;
+ fileWriteErr = file.Replace(*fileSystemAccess, aPath, EFileWrite);
+ if (fileWriteErr)
+ User::Leave(fileWriteErr);
+ CleanupClosePushL(file); // Close if Leaves
+
+ fileWriteErr = file.Write(*aData);
+ if (fileWriteErr)
+ User::Leave(fileWriteErr);
+
+ CleanupStack::PopAndDestroy(&file);
+#ifdef ECAM_PREVIEW_API
+ CleanupStack::PopAndDestroy(fileSystemAccess);
+#else // !ECAM_PREVIEW_API
+ // Delete when Image is decoded
+ CleanupStack::Pop(previewBitmap);
+ CleanupStack::Pop(imageDecoder);
+ CleanupStack::Pop(fileSystemAccess);
+
+ // Set member variables (Cannot leave any more)
+ m_previewBitmap = previewBitmap;
+ m_imageDecoder = imageDecoder;
+ m_fileSystemAccess = fileSystemAccess;
+#endif // ECAM_PREVIEW_API
+
+ emit imageSaved(m_currentImageId, m_stillCaptureFileName);
+
+ // Inform that we can continue taking more pictures
+ emit readyForCaptureChanged(true);
+
+ // For custom preview generation, image buffer gets released in RunL()
+#ifdef ECAM_PREVIEW_API
+ releaseImageBuffer();
+#endif // ECAM_PREVIEW_API
+
+ } else {
+ setError(KErrPathNotFound, tr("Invalid path given."), true);
+ }
+}
+
+void S60ImageCaptureSession::releaseImageBuffer()
+{
+ if (m_cameraEngine)
+ m_cameraEngine->ReleaseImageBuffer();
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."), true);
+}
+
+/*
+ * Queries camera properties
+ * Results are returned to member variable m_info
+ *
+ * @return boolean indicating if querying the info was a success
+ */
+bool S60ImageCaptureSession::queryCurrentCameraInfo()
+{
+ if (m_cameraEngine) {
+ m_cameraInfo = m_cameraEngine->CameraInfo();
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * This function handles different camera status changes
+ */
+void S60ImageCaptureSession::cameraStatusChanged(QCamera::Status status)
+{
+ if (status == QCamera::ActiveStatus) {
+ m_cameraStarted = true;
+ if (m_captureWhenReady)
+ capture(m_requestedStillCaptureFileName);
+ }else if (status == QCamera::UnloadedStatus) {
+ m_cameraStarted = false;
+ m_icState = EImageCaptureNotPrepared;
+ }
+ else
+ m_cameraStarted = false;
+}
+
+QSize S60ImageCaptureSession::captureSize() const
+{
+ return m_captureSize;
+}
+
+QSize S60ImageCaptureSession::minimumCaptureSize()
+{
+ return supportedCaptureSizesForCodec(formatMap().key(m_currentFormat)).first();
+}
+QSize S60ImageCaptureSession::maximumCaptureSize()
+{
+ return supportedCaptureSizesForCodec(formatMap().key(m_currentFormat)).last();
+}
+
+void S60ImageCaptureSession::setCaptureSize(const QSize &size)
+{
+ if (size.isNull() ||
+ size.isEmpty() ||
+ size == QSize(-1,-1)) {
+ // An empty QSize indicates the encoder should make an optimal choice based on what is
+ // available from the image source and the limitations of the codec.
+ m_captureSize = supportedCaptureSizesForCodec(formatMap().key(m_currentFormat)).last();
+ }
+ else
+ m_captureSize = size;
+}
+
+QList<QSize> S60ImageCaptureSession::supportedCaptureSizesForCodec(const QString &codecName)
+{
+ QList<QSize> list;
+
+ // If we have CameraEngine loaded and we can update CameraInfo
+ if (m_cameraEngine && queryCurrentCameraInfo()) {
+ CCamera::TFormat format;
+ if (codecName == "")
+ format = defaultImageFormat();
+ else
+ format = selectFormatForCodec(codecName);
+
+ CCamera *camera = m_cameraEngine->Camera();
+ TSize imageSize;
+ if (camera) {
+ for (int i = 0; i < m_cameraInfo->iNumImageSizesSupported; i++) {
+ camera->EnumerateCaptureSizes(imageSize, i, format);
+ list << QSize(imageSize.iWidth, imageSize.iHeight); // Add resolution to the list
+ }
+ }
+ }
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ // Add some for testing purposes
+ list << QSize(50, 50);
+ list << QSize(100, 100);
+ list << QSize(800,600);
+#endif
+
+ return list;
+}
+
+QMap<QString, int> S60ImageCaptureSession::formatMap()
+{
+ QMap<QString, int> formats;
+
+ // Format list copied from CCamera::TFormat (in ecam.h)
+ formats.insert("Monochrome", 0x0001);
+ formats.insert("16bitRGB444", 0x0002);
+ formats.insert("16BitRGB565", 0x0004);
+ formats.insert("32BitRGB888", 0x0008);
+ formats.insert("Jpeg", 0x0010);
+ formats.insert("Exif", 0x0020);
+ formats.insert("FbsBitmapColor4K", 0x0040);
+ formats.insert("FbsBitmapColor64K", 0x0080);
+ formats.insert("FbsBitmapColor16M", 0x0100);
+ formats.insert("UserDefined", 0x0200);
+ formats.insert("YUV420Interleaved", 0x0400);
+ formats.insert("YUV420Planar", 0x0800);
+ formats.insert("YUV422", 0x1000);
+ formats.insert("YUV422Reversed", 0x2000);
+ formats.insert("YUV444", 0x4000);
+ formats.insert("YUV420SemiPlanar", 0x8000);
+ formats.insert("FbsBitmapColor16MU", 0x00010000);
+ formats.insert("MJPEG", 0x00020000);
+ formats.insert("EncodedH264", 0x00040000);
+
+ return formats;
+}
+
+QMap<QString, QString> S60ImageCaptureSession::codecDescriptionMap()
+{
+ QMap<QString, QString> formats;
+
+ formats.insert("image/jpg", "JPEG image codec");
+
+ return formats;
+}
+
+QStringList S60ImageCaptureSession::supportedImageCaptureCodecs()
+{
+#ifdef Q_CC_NOKIAX86 // Emulator
+ return formatMap().keys();
+#endif
+
+ return m_supportedImageCodecs;
+}
+
+void S60ImageCaptureSession::updateImageCaptureFormats()
+{
+ m_formats.clear();
+ if (m_cameraEngine && queryCurrentCameraInfo()) {
+ TUint32 supportedFormats = m_cameraInfo->iImageFormatsSupported;
+
+#ifdef S60_3X_PLATFORM // S60 3.1 & 3.2
+ int maskEnd = CCamera::EFormatFbsBitmapColor16MU;
+#else // S60 5.0 or later
+ int maskEnd = CCamera::EFormatEncodedH264;
+#endif // S60_3X_PLATFORM
+
+ for (int mask = CCamera::EFormatMonochrome; mask <= maskEnd; mask <<= 1) {
+ if (supportedFormats & mask)
+ m_formats << mask; // Store mask of supported format
+ }
+ }
+}
+
+QString S60ImageCaptureSession::imageCaptureCodec()
+{
+ return m_currentCodec;
+}
+void S60ImageCaptureSession::setImageCaptureCodec(const QString &codecName)
+{
+ if (!codecName.isEmpty()) {
+ if (supportedImageCaptureCodecs().contains(codecName, Qt::CaseInsensitive) ||
+ codecName == "image/jpg") {
+ m_currentCodec = codecName;
+ m_currentFormat = selectFormatForCodec(m_currentCodec);
+ } else {
+ setError(KErrNotSupported, tr("Requested image codec is not supported"));
+ }
+ } else {
+ m_currentCodec = KDefaultImageCodec;
+ m_currentFormat = selectFormatForCodec(m_currentCodec);
+ }
+}
+
+QString S60ImageCaptureSession::imageCaptureCodecDescription(const QString &codecName)
+{
+ QString description = codecDescriptionMap().value(codecName);
+ return description;
+}
+
+QtMultimediaKit::EncodingQuality S60ImageCaptureSession::captureQuality() const
+{
+ switch (m_symbianImageQuality) {
+ case KJpegQualityVeryLow:
+ return QtMultimediaKit::VeryLowQuality;
+ case KJpegQualityLow:
+ return QtMultimediaKit::LowQuality;
+ case KJpegQualityNormal:
+ return QtMultimediaKit::NormalQuality;
+ case KJpegQualityHigh:
+ return QtMultimediaKit::HighQuality;
+ case KJpegQualityVeryHigh:
+ return QtMultimediaKit::VeryHighQuality;
+
+ default:
+ // Return normal as default
+ return QtMultimediaKit::NormalQuality;
+ }
+}
+
+void S60ImageCaptureSession::setCaptureQuality(const QtMultimediaKit::EncodingQuality &quality)
+{
+ // Use sensible presets
+ switch (quality) {
+ case QtMultimediaKit::VeryLowQuality:
+ m_symbianImageQuality = KJpegQualityVeryLow;
+ break;
+ case QtMultimediaKit::LowQuality:
+ m_symbianImageQuality = KJpegQualityLow;
+ break;
+ case QtMultimediaKit::NormalQuality:
+ m_symbianImageQuality = KJpegQualityNormal;
+ break;
+ case QtMultimediaKit::HighQuality:
+ m_symbianImageQuality = KJpegQualityHigh;
+ break;
+ case QtMultimediaKit::VeryHighQuality:
+ m_symbianImageQuality = KJpegQualityVeryHigh;
+ break;
+
+ default:
+ m_symbianImageQuality = quality * KSymbianImageQualityCoefficient;
+ break;
+ }
+}
+
+qreal S60ImageCaptureSession::maximumZoom()
+{
+ qreal maxZoomFactor = 1.0;
+
+ if (queryCurrentCameraInfo()) {
+ maxZoomFactor = m_cameraInfo->iMaxZoomFactor;
+
+ if (maxZoomFactor == 0.0 || maxZoomFactor == 1.0) {
+ return 1.0; // Not supported
+ } else {
+ return maxZoomFactor;
+ }
+ } else {
+ return 1.0;
+ }
+}
+
+qreal S60ImageCaptureSession::minZoom()
+{
+ qreal minZoomValue = 1.0;
+
+ if (queryCurrentCameraInfo()) {
+ minZoomValue = m_cameraInfo->iMinZoomFactor;
+ if (minZoomValue == 0.0 || minZoomValue == 1.0)
+ return 1.0; // Macro Zoom is not supported
+ else {
+ return minZoomValue;
+ }
+
+ } else {
+ return 1.0;
+ }
+}
+
+qreal S60ImageCaptureSession::maxDigitalZoom()
+{
+ qreal maxDigitalZoomFactor = 1.0;
+
+ if (queryCurrentCameraInfo()) {
+ maxDigitalZoomFactor = m_cameraInfo->iMaxDigitalZoomFactor;
+ return maxDigitalZoomFactor;
+ } else {
+ return 1.0;
+ }
+}
+
+void S60ImageCaptureSession::doSetZoomFactorL(qreal optical, qreal digital)
+{
+#if !defined(USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER) & !defined(USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER)
+ // Convert Zoom Factor to Zoom Value if AdvSettings are not available
+ int digitalSymbian = (digital * m_cameraInfo->iMaxDigitalZoom) / maxDigitalZoom();
+ if (m_cameraInfo->iMaxDigitalZoom != 0 && digital == 1.0)
+ digitalSymbian = 1; // Make sure zooming out to initial value if requested
+#endif // !USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER & !USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER
+
+ if (m_cameraEngine && !m_cameraEngine->IsCameraReady())
+ return;
+
+ if (m_cameraEngine && queryCurrentCameraInfo()) {
+ CCamera *camera = m_cameraEngine->Camera();
+ if (camera) {
+
+ // Optical Zoom
+ if (!qFuzzyCompare(optical, qreal(1.0)) && !qFuzzyCompare(optical, qreal(0.0))) {
+ setError(KErrNotSupported, tr("Requested optical zoom factor is not supported."));
+ return;
+ }
+
+ // Digital Zoom (Smooth Zoom - Zoom value set in steps)
+ if (digital != digitalZoomFactor()) {
+ if ((digital > 1.0 || qFuzzyCompare(digital, qreal(1.0))) &&
+ digital <= m_cameraInfo->iMaxDigitalZoomFactor) {
+#if defined(USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER) | defined(USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER)
+ if (m_advancedSettings) {
+ qreal currentZoomFactor = m_advancedSettings->digitalZoomFactorL();
+
+ QList<qreal> smoothZoomSetValues;
+ QList<qreal> factors = m_advancedSettings->supportedDigitalZoomFactors();
+ if (currentZoomFactor < digital) {
+ for (int i = 0; i < factors.count(); ++i) {
+ if (factors.at(i) > currentZoomFactor && factors.at(i) < digital)
+ smoothZoomSetValues << factors.at(i);
+ }
+
+ for (int i = 0; i < smoothZoomSetValues.count(); i = i + KSmoothZoomStep) {
+ m_advancedSettings->setDigitalZoomFactorL(smoothZoomSetValues[i]); // Using Zoom Factor
+ }
+
+ } else {
+ for (int i = 0; i < factors.count(); ++i) {
+ if (factors.at(i) < currentZoomFactor && factors.at(i) > digital)
+ smoothZoomSetValues << factors.at(i);
+ }
+
+ for (int i = (smoothZoomSetValues.count() - 1); i >= 0; i = i - KSmoothZoomStep) {
+ m_advancedSettings->setDigitalZoomFactorL(smoothZoomSetValues[i]); // Using Zoom Factor
+ }
+ }
+
+ // Set final value
+ m_advancedSettings->setDigitalZoomFactorL(digital);
+ }
+ else
+ setError(KErrNotReady, tr("Zooming failed."));
+#else // No advanced settigns
+ // Define zoom steps
+ int currentZoomFactor = camera->DigitalZoomFactor();
+ int difference = abs(currentZoomFactor - digitalSymbian);
+ int midZoomValue = currentZoomFactor;
+
+ if (currentZoomFactor < digitalSymbian) {
+ while (midZoomValue < (digitalSymbian - KSmoothZoomStep)) {
+ midZoomValue = midZoomValue + KSmoothZoomStep;
+ camera->SetDigitalZoomFactorL(midZoomValue);
+ }
+ } else {
+ while (midZoomValue > (digitalSymbian + KSmoothZoomStep)) {
+ midZoomValue = midZoomValue - KSmoothZoomStep;
+ camera->SetDigitalZoomFactorL(midZoomValue);
+ }
+ }
+
+ // Set final and emit signal
+ camera->SetDigitalZoomFactorL(digitalSymbian);
+#endif // USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER | USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER
+ } else {
+ setError(KErrNotSupported, tr("Requested digital zoom factor is not supported."));
+ return;
+ }
+ }
+ }
+ } else {
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ }
+}
+
+qreal S60ImageCaptureSession::opticalZoomFactor()
+{
+ qreal factor = 1.0;
+
+#if defined(USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER) | defined(USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER)
+ if (m_advancedSettings) {
+ TRAPD(err, factor = m_advancedSettings->opticalZoomFactorL());
+ if (err)
+ return 1.0;
+ }
+#else // No advanced settigns
+ if (m_cameraEngine && m_cameraInfo) {
+ if (m_cameraEngine->Camera()) {
+ if (m_cameraInfo->iMaxZoom != 0)
+ factor = (m_cameraEngine->Camera()->ZoomFactor()* maximumZoom()) / m_cameraInfo->iMaxZoom;
+ else
+ factor = 1.0;
+ }
+ }
+#endif // USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER | USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER
+
+ if (factor == 0.0) // If not supported
+ factor = 1.0;
+
+ return factor;
+}
+
+qreal S60ImageCaptureSession::digitalZoomFactor()
+{
+ qreal factor = 1.0;
+
+#if defined(USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER) | defined(USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER)
+ if (m_advancedSettings) {
+ TRAPD(err, factor = m_advancedSettings->digitalZoomFactorL());
+ if (err)
+ return 1.0;
+ }
+#else // No advanced settigns
+ if (m_cameraEngine && m_cameraInfo) {
+ if (m_cameraEngine->Camera()) {
+ if (m_cameraInfo->iMaxDigitalZoom != 0)
+ factor = (m_cameraEngine->Camera()->DigitalZoomFactor()* maxDigitalZoom()) / m_cameraInfo->iMaxDigitalZoom;
+ else
+ factor = 1.0;
+ }
+ }
+#endif // USE_S60_32_ECAM_ADVANCED_SETTINGS_HEADER | USE_S60_50_ECAM_ADVANCED_SETTINGS_HEADER
+
+ if (factor == 0.0)
+ factor = 1.0;
+
+ return factor;
+}
+
+void S60ImageCaptureSession::setFlashMode(QCameraExposure::FlashModes mode)
+{
+ TRAPD(err, doSetFlashModeL(mode));
+ setError(err, tr("Failed to set flash mode."));
+}
+
+void S60ImageCaptureSession::doSetFlashModeL(QCameraExposure::FlashModes mode)
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ CCamera *camera = m_cameraEngine->Camera();
+ switch(mode) {
+ case QCameraExposure::FlashOff:
+ camera->SetFlashL(CCamera::EFlashNone);
+ break;
+ case QCameraExposure::FlashAuto:
+ camera->SetFlashL(CCamera::EFlashAuto);
+ break;
+ case QCameraExposure::FlashOn:
+ camera->SetFlashL(CCamera::EFlashForced);
+ break;
+ case QCameraExposure::FlashRedEyeReduction:
+ camera->SetFlashL(CCamera::EFlashRedEyeReduce);
+ break;
+ case QCameraExposure::FlashFill:
+ camera->SetFlashL(CCamera::EFlashFillIn);
+ break;
+
+ default:
+ setError(KErrNotSupported, tr("Requested flash mode is not suported"));
+ break;
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+QCameraExposure::FlashMode S60ImageCaptureSession::flashMode()
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ CCamera *camera = m_cameraEngine->Camera();
+ switch(camera->Flash()) {
+ case CCamera::EFlashAuto:
+ return QCameraExposure::FlashAuto;
+ case CCamera::EFlashForced:
+ return QCameraExposure::FlashOn;
+ case CCamera::EFlashRedEyeReduce:
+ return QCameraExposure::FlashRedEyeReduction;
+ case CCamera::EFlashFillIn:
+ return QCameraExposure::FlashFill;
+ case CCamera::EFlashNone:
+ return QCameraExposure::FlashOff;
+
+ default:
+ return QCameraExposure::FlashAuto; // Most probable default
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+
+ return QCameraExposure::FlashOff;
+}
+
+QCameraExposure::FlashModes S60ImageCaptureSession::supportedFlashModes()
+{
+ QCameraExposure::FlashModes modes = QCameraExposure::FlashOff;
+
+ if (queryCurrentCameraInfo()) {
+ TInt supportedModes = m_cameraInfo->iFlashModesSupported;
+
+ if (supportedModes == 0)
+ return modes;
+
+ if (supportedModes & CCamera::EFlashManual)
+ modes |= QCameraExposure::FlashOff;
+ if (supportedModes & CCamera::EFlashForced)
+ modes |= QCameraExposure::FlashOn;
+ if (supportedModes & CCamera::EFlashAuto)
+ modes |= QCameraExposure::FlashAuto;
+ if (supportedModes & CCamera::EFlashFillIn)
+ modes |= QCameraExposure::FlashFill;
+ if (supportedModes & CCamera::EFlashRedEyeReduce)
+ modes |= QCameraExposure::FlashRedEyeReduction;
+ }
+
+ return modes;
+}
+
+QCameraExposure::ExposureMode S60ImageCaptureSession::exposureMode()
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ CCamera* camera = m_cameraEngine->Camera();
+ switch(camera->Exposure()) {
+ case CCamera::EExposureManual:
+ return QCameraExposure::ExposureManual;
+ case CCamera::EExposureAuto:
+ return QCameraExposure::ExposureAuto;
+ case CCamera::EExposureNight:
+ return QCameraExposure::ExposureNight;
+ case CCamera::EExposureBacklight:
+ return QCameraExposure::ExposureBacklight;
+ case CCamera::EExposureSport:
+ return QCameraExposure::ExposureSports;
+ case CCamera::EExposureSnow:
+ return QCameraExposure::ExposureSnow;
+ case CCamera::EExposureBeach:
+ return QCameraExposure::ExposureBeach;
+
+ default:
+ return QCameraExposure::ExposureAuto;
+ }
+ }
+
+ return QCameraExposure::ExposureAuto;
+}
+
+bool S60ImageCaptureSession::isExposureModeSupported(QCameraExposure::ExposureMode mode) const
+{
+ TInt supportedModes = m_cameraInfo->iExposureModesSupported;
+
+ if (supportedModes == 0)
+ return false;
+
+ switch (mode) {
+ case QCameraExposure::ExposureManual:
+ if(supportedModes & CCamera::EExposureManual)
+ return true;
+ else
+ return false;
+ case QCameraExposure::ExposureAuto:
+ return true; // Always supported
+ case QCameraExposure::ExposureNight:
+ if(supportedModes & CCamera::EExposureNight)
+ return true;
+ else
+ return false;
+ case QCameraExposure::ExposureBacklight:
+ if(supportedModes & CCamera::EExposureBacklight)
+ return true;
+ else
+ return false;
+ case QCameraExposure::ExposureSports:
+ if(supportedModes & CCamera::EExposureSport)
+ return true;
+ else
+ return false;
+ case QCameraExposure::ExposureSnow:
+ if(supportedModes & CCamera::EExposureSnow)
+ return true;
+ else
+ return false;
+ case QCameraExposure::ExposureBeach:
+ if(supportedModes & CCamera::EExposureBeach)
+ return true;
+ else
+ return false;
+
+ default:
+ return false;
+ }
+}
+
+void S60ImageCaptureSession::setExposureMode(QCameraExposure::ExposureMode mode)
+{
+ TRAPD(err, doSetExposureModeL(mode));
+ setError(err, tr("Failed to set exposure mode."));
+}
+
+void S60ImageCaptureSession::doSetExposureModeL( QCameraExposure::ExposureMode mode)
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ CCamera *camera = m_cameraEngine->Camera();
+ switch(mode) {
+ case QCameraExposure::ExposureManual:
+ camera->SetExposureL(CCamera::EExposureManual);
+ break;
+ case QCameraExposure::ExposureAuto:
+ camera->SetExposureL(CCamera::EExposureAuto);
+ break;
+ case QCameraExposure::ExposureNight:
+ camera->SetExposureL(CCamera::EExposureNight);
+ break;
+ case QCameraExposure::ExposureBacklight:
+ camera->SetExposureL(CCamera::EExposureBacklight);
+ break;
+ case QCameraExposure::ExposureSports:
+ camera->SetExposureL(CCamera::EExposureSport);
+ break;
+ case QCameraExposure::ExposureSnow:
+ camera->SetExposureL(CCamera::EExposureSnow);
+ break;
+ case QCameraExposure::ExposureBeach:
+ camera->SetExposureL(CCamera::EExposureBeach);
+ break;
+ case QCameraExposure::ExposureLargeAperture:
+ case QCameraExposure::ExposureSmallAperture:
+ break;
+ case QCameraExposure::ExposurePortrait:
+ case QCameraExposure::ExposureSpotlight:
+ default:
+ setError(KErrNotSupported, tr("Requested exposure mode is not suported"));
+ break;
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+int S60ImageCaptureSession::contrast() const
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ return m_cameraEngine->Camera()->Contrast();
+ } else {
+ return 0;
+ }
+}
+
+void S60ImageCaptureSession::setContrast(int value)
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ TRAPD(err, m_cameraEngine->Camera()->SetContrastL(value));
+ setError(err, tr("Failed to set contrast."));
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+int S60ImageCaptureSession::brightness() const
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ return m_cameraEngine->Camera()->Brightness();
+ } else {
+ return 0;
+ }
+}
+
+void S60ImageCaptureSession::setBrightness(int value)
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ TRAPD(err, m_cameraEngine->Camera()->SetBrightnessL(value));
+ setError(err, tr("Failed to set brightness."));
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+ QCameraImageProcessing::WhiteBalanceMode S60ImageCaptureSession::whiteBalanceMode()
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ CCamera::TWhiteBalance mode = m_cameraEngine->Camera()->WhiteBalance();
+ switch(mode) {
+ case CCamera::EWBAuto:
+ return QCameraImageProcessing::WhiteBalanceAuto;
+ case CCamera::EWBDaylight:
+ return QCameraImageProcessing::WhiteBalanceSunlight;
+ case CCamera::EWBCloudy:
+ return QCameraImageProcessing::WhiteBalanceCloudy;
+ case CCamera::EWBTungsten:
+ return QCameraImageProcessing::WhiteBalanceTungsten;
+ case CCamera::EWBFluorescent:
+ return QCameraImageProcessing::WhiteBalanceFluorescent;
+ case CCamera::EWBFlash:
+ return QCameraImageProcessing::WhiteBalanceFlash;
+ case CCamera::EWBBeach:
+ return QCameraImageProcessing::WhiteBalanceSunset;
+ case CCamera::EWBManual:
+ return QCameraImageProcessing::WhiteBalanceManual;
+ case CCamera::EWBShade:
+ return QCameraImageProcessing::WhiteBalanceShade;
+
+ default:
+ return QCameraImageProcessing::WhiteBalanceAuto;
+ }
+ }
+
+ return QCameraImageProcessing::WhiteBalanceAuto;
+}
+
+void S60ImageCaptureSession::setWhiteBalanceMode( QCameraImageProcessing::WhiteBalanceMode mode)
+{
+ TRAPD(err, doSetWhiteBalanceModeL(mode));
+ setError(err, tr("Failed to set white balance mode."));
+}
+
+void S60ImageCaptureSession::doSetWhiteBalanceModeL( QCameraImageProcessing::WhiteBalanceMode mode)
+{
+ if (m_cameraEngine && m_cameraEngine->Camera()) {
+ CCamera* camera = m_cameraEngine->Camera();
+ switch(mode) {
+ case QCameraImageProcessing::WhiteBalanceAuto:
+ camera->SetWhiteBalanceL(CCamera::EWBAuto);
+ break;
+ case QCameraImageProcessing::WhiteBalanceSunlight:
+ camera->SetWhiteBalanceL(CCamera::EWBDaylight);
+ break;
+ case QCameraImageProcessing::WhiteBalanceCloudy:
+ camera->SetWhiteBalanceL(CCamera::EWBCloudy);
+ break;
+ case QCameraImageProcessing::WhiteBalanceTungsten:
+ camera->SetWhiteBalanceL(CCamera::EWBTungsten);
+ break;
+ case QCameraImageProcessing::WhiteBalanceFluorescent:
+ camera->SetWhiteBalanceL(CCamera::EWBFluorescent);
+ break;
+ case QCameraImageProcessing::WhiteBalanceFlash:
+ camera->SetWhiteBalanceL(CCamera::EWBFlash);
+ break;
+ case QCameraImageProcessing::WhiteBalanceSunset:
+ camera->SetWhiteBalanceL(CCamera::EWBBeach);
+ break;
+ case QCameraImageProcessing::WhiteBalanceManual:
+ camera->SetWhiteBalanceL(CCamera::EWBManual);
+ break;
+ case QCameraImageProcessing::WhiteBalanceShade:
+ camera->SetWhiteBalanceL(CCamera::EWBShade);
+ break;
+
+ default:
+ setError(KErrNotSupported, tr("Requested white balance mode is not suported"));
+ break;
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+bool S60ImageCaptureSession::isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const
+{
+ if (m_cameraEngine) {
+ TInt supportedModes = m_cameraInfo->iWhiteBalanceModesSupported;
+ switch (mode) {
+ case QCameraImageProcessing::WhiteBalanceManual:
+ if (supportedModes & CCamera::EWBManual)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceAuto:
+ if (supportedModes & CCamera::EWBAuto)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceSunlight:
+ if (supportedModes & CCamera::EWBDaylight)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceCloudy:
+ if (supportedModes & CCamera::EWBCloudy)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceShade:
+ if (supportedModes & CCamera::EWBShade)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceTungsten:
+ if (supportedModes & CCamera::EWBTungsten)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceFluorescent:
+ if (supportedModes & CCamera::EWBFluorescent)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceIncandescent: // Not available in Symbian
+ return false;
+ case QCameraImageProcessing::WhiteBalanceFlash:
+ if (supportedModes & CCamera::EWBFlash)
+ return true;
+ else
+ return false;
+ case QCameraImageProcessing::WhiteBalanceSunset:
+ if (supportedModes & CCamera::EWBBeach)
+ return true;
+ else
+ return false;
+
+ default:
+ return false;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * ====================
+ * S60 3.1 AutoFocosing
+ * ====================
+ */
+bool S60ImageCaptureSession::isFocusSupported() const
+{
+ return m_cameraEngine->IsAutoFocusSupported();
+}
+
+void S60ImageCaptureSession::startFocus()
+{
+ if (m_cameraEngine) {
+ TRAPD(err, m_cameraEngine->StartFocusL());
+ setError(err, tr("Failed to start focusing."));
+ }
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+}
+
+void S60ImageCaptureSession::cancelFocus()
+{
+ if (m_cameraEngine) {
+ TRAPD(err, m_cameraEngine->FocusCancel());
+ setError(err, tr("Failed to cancel focusing."));
+ }
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+}
+
+void S60ImageCaptureSession::handleImageDecoded(int error)
+{
+ // Delete unneeded objects
+ if (m_imageDecoder) {
+ delete m_imageDecoder;
+ m_imageDecoder = 0;
+ }
+ if (m_fileSystemAccess) {
+ m_fileSystemAccess->Close();
+ delete m_fileSystemAccess;
+ m_fileSystemAccess = 0;
+ }
+
+ // Check status of decoding
+ if (error != KErrNone) {
+ if (m_previewBitmap) {
+ m_previewBitmap->Reset();
+ delete m_previewBitmap;
+ m_previewBitmap = 0;
+ }
+ releaseImageBuffer();
+ if (m_previewInWaitLoop) {
+ CActiveScheduler::Stop(); // Notify to continue execution of next Preview Image generation
+ m_previewInWaitLoop = false; // Reset
+ }
+ setError(error, tr("Preview creation failed."));
+ return;
+ }
+
+ m_previewDecodingOngoing = false;
+
+ QPixmap prevPixmap = QPixmap::fromSymbianCFbsBitmap(m_previewBitmap);
+ QImage preview = prevPixmap.toImage();
+
+ if (m_previewBitmap) {
+ m_previewBitmap->Reset();
+ delete m_previewBitmap;
+ m_previewBitmap = 0;
+ }
+
+ QT_TRYCATCH_LEAVING( emit imageCaptured(m_currentImageId, preview) );
+
+ // Release image resources (if not already done)
+ releaseImageBuffer();
+
+ if (m_previewInWaitLoop) {
+ CActiveScheduler::Stop(); // Notify to continue execution of next Preview Image generation
+ m_previewInWaitLoop = false; // Reset
+ }
+}
+
+void S60ImageCaptureSession::handleImageEncoded(int error)
+{
+ // Check status of encoding
+ if (error != KErrNone) {
+ releaseImageBuffer();
+ if (m_previewInWaitLoop) {
+ CActiveScheduler::Stop(); // Notify to continue execution of next Preview Image generation
+ m_previewInWaitLoop = false; // Reset
+ }
+ setError(error, tr("Saving captured image to file failed."));
+ return;
+ } else {
+ QT_TRYCATCH_LEAVING( emit imageSaved(m_currentImageId, m_stillCaptureFileName) );
+ }
+
+ if (m_imageEncoder) {
+ delete m_imageEncoder;
+ m_imageEncoder = 0;
+ }
+
+#ifndef ECAM_PREVIEW_API
+ // Start preview generation
+ TInt previewError = KErrNone;
+ TFileName fileName = convertImagePath();
+ TRAP(previewError, m_imageDecoder = S60ImageCaptureDecoder::FileNewL(this, m_fileSystemAccess, &fileName));
+ if (previewError) {
+ setError(previewError, tr("Failed to create preview image."));
+ return;
+ }
+
+ // Set proper Preview Size
+ TSize scaledSize((m_captureSize.width() / KSnapshotDownScaleFactor), (m_captureSize.height() / KSnapshotDownScaleFactor));
+ if (scaledSize.iWidth < KSnapshotMinWidth || scaledSize.iHeight < KSnapshotMinHeight)
+ scaledSize.SetSize((m_captureSize.width() / (KSnapshotDownScaleFactor/2)), (m_captureSize.height() / (KSnapshotDownScaleFactor/2)));
+ if (scaledSize.iWidth < KSnapshotMinWidth || scaledSize.iHeight < KSnapshotMinHeight)
+ scaledSize.SetSize((m_captureSize.width() / (KSnapshotDownScaleFactor/4)), (m_captureSize.height() / (KSnapshotDownScaleFactor/4)));
+ if (scaledSize.iWidth < KSnapshotMinWidth || scaledSize.iHeight < KSnapshotMinHeight)
+ scaledSize.SetSize(m_captureSize.width(), m_captureSize.height());
+
+ TFrameInfo *info = m_imageDecoder->frameInfo();
+ if (!info) {
+ setError(KErrGeneral, tr("Preview image creation failed."));
+ return;
+ }
+
+ m_previewBitmap = new CFbsBitmap;
+ if (!m_previewBitmap) {
+ setError(KErrNoMemory, tr("Failed to create preview image."));
+ return;
+ }
+ previewError = m_previewBitmap->Create(scaledSize, info->iFrameDisplayMode);
+ if (previewError) {
+ setError(previewError, tr("Preview creation failed."));
+ return;
+ }
+
+ // Jpeg decoding completes in handleImageDecoded()
+ m_imageDecoder->decode(m_previewBitmap);
+#endif // ECAM_PREVIEW_API
+
+ // Buffer can be released since Preview is created from file
+ releaseImageBuffer();
+
+ // Inform that we can continue taking more pictures
+ QT_TRYCATCH_LEAVING( emit readyForCaptureChanged(true) );
+}
+
+#ifdef ECAM_PREVIEW_API
+void S60ImageCaptureSession::MceoPreviewReady(CFbsBitmap& aPreview)
+{
+ QPixmap previewPixmap = QPixmap::fromSymbianCFbsBitmap(&aPreview);
+ QImage preview = previewPixmap.toImage();
+
+ // Notify preview availability
+ emit imageCaptured(m_currentImageId, preview);
+}
+#endif // ECAM_PREVIEW_API
+
+// End of file
+
diff --git a/src/plugins/symbian/ecam/s60imagecapturesession.h b/src/plugins/symbian/ecam/s60imagecapturesession.h
new file mode 100644
index 000000000..9cae05fc9
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60imagecapturesession.h
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** 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 S60IMAGECAPTURESESSION_H
+#define S60IMAGECAPTURESESSION_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qmap.h>
+#include <QtGui/qicon.h>
+
+#include <qcamera.h>
+#include <qcamerafocus.h>
+#include <qcameraimagecapture.h>
+#include <qvideoframe.h>
+
+#include "s60camerasettings.h"
+#include "s60cameraengine.h"
+#include "s60cameraengineobserver.h"
+#include "s60cameraconstants.h" // Default Jpeg Quality
+
+#include <icl/imagedata.h> // TFrameInfo
+
+QT_USE_NAMESPACE
+
+class S60CameraService;
+class CImageDecoder;
+class CImageEncoder;
+class CFrameImageData;
+class RFs;
+class S60ImageCaptureSession;
+
+/*
+ * This class implements asynchronous image decoding service for the
+ * S60ImageCaptureSession.
+ */
+class S60ImageCaptureDecoder : public CActive
+{
+public: // Static Contructor & Destructor
+
+ static S60ImageCaptureDecoder* FileNewL(S60ImageCaptureSession *imageSession = 0,
+ RFs *fileSystemAccess = 0,
+ const TDesC16 *fileName = 0);
+ static S60ImageCaptureDecoder* DataNewL(S60ImageCaptureSession *imageSession = 0,
+ RFs *fileSystemAccess = 0,
+ const TDesC8 *data = 0);
+ ~S60ImageCaptureDecoder();
+
+public: // Operations
+
+ void decode(CFbsBitmap *destBitmap);
+ TFrameInfo *frameInfo();
+
+protected: // CActive
+
+ void RunL();
+ void DoCancel();
+ TInt RunError(TInt aError);
+
+protected: // Protected constructors
+
+ S60ImageCaptureDecoder(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC8 *data,
+ const TDesC16 *fileName);
+ void ConstructL(const bool fileInput = false);
+
+private: // Data
+
+ S60ImageCaptureSession *m_imageSession;
+ CImageDecoder *m_imageDecoder;
+ RFs *m_fs;
+ const TDesC8 *m_jpegImageData;
+ const TDesC16 *m_jpegImageFile;
+ bool m_fileInput;
+ TFrameInfo m_frameInfo;
+
+};
+
+//=============================================================================
+
+/*
+ * This class implements asynchronous image encoding service for the
+ * S60ImageCaptureSession.
+ */
+class S60ImageCaptureEncoder : public CActive
+{
+public: // Static Contructor & Destructor
+
+ static S60ImageCaptureEncoder* NewL(S60ImageCaptureSession *imageSession = 0,
+ RFs *fileSystemAccess = 0,
+ const TDesC16 *fileName = 0,
+ TInt jpegQuality = KDefaultImageQuality);
+ ~S60ImageCaptureEncoder();
+
+public: // Operations
+
+ void encode(CFbsBitmap *sourceBitmap);
+
+protected: // CActive
+
+ void RunL();
+ void DoCancel();
+ TInt RunError(TInt aError);
+
+protected: // Protected constructors
+
+ S60ImageCaptureEncoder(S60ImageCaptureSession *imageSession,
+ RFs *fileSystemAccess,
+ const TDesC16 *fileName,
+ TInt jpegQuality);
+ void ConstructL();
+
+private: // Data
+
+ S60ImageCaptureSession *m_imageSession;
+ CImageEncoder *m_imageEncoder;
+ RFs *m_fileSystemAccess;
+ const TDesC16 *m_fileName;
+ CFrameImageData *m_frameImageData;
+ TInt m_jpegQuality;
+
+};
+
+//=============================================================================
+
+/*
+ * Session handling all image capture activities.
+ */
+class S60ImageCaptureSession : public QObject,
+#ifdef ECAM_PREVIEW_API
+ public MCameraPreviewObserver,
+#endif // ECAM_PREVIEW_API
+ public MCameraEngineImageCaptureObserver
+{
+ Q_OBJECT
+
+public: // Enums
+
+ enum ImageCaptureState {
+ EImageCaptureNotPrepared = 0, // 0 - ImageCapture has not been prepared
+ EImageCapturePrepared, // 1 - ImageCapture has been prepared
+ EImageCaptureCapturing, // 2 - Image capture ongoing
+ EImageCaptureWritingImage // 3 - Image captured and image writing to file ongoing
+ };
+
+public: // Constructor & Destructor
+
+ S60ImageCaptureSession(QObject *parent = 0);
+ ~S60ImageCaptureSession();
+
+public: // Methods
+
+ void setError(const TInt error, const QString &description, const bool captureError = false);
+ int currentImageId() const;
+
+ bool isDeviceReady();
+ void setCameraHandle(CCameraEngine* camerahandle);
+ void setCurrentDevice(TInt deviceindex);
+ void notifySettingsSet();
+
+ // Ecam Advanced Settings
+ S60CameraSettings* advancedSettings();
+ void deleteAdvancedSettings();
+
+ // Controls
+ int prepareImageCapture();
+ void releaseImageCapture();
+ int capture(const QString &fileName);
+ void cancelCapture();
+ void releaseImageBuffer();
+
+ // Image Resolution
+ QSize captureSize() const;
+ QSize minimumCaptureSize();
+ QSize maximumCaptureSize();
+ QList<QSize> supportedCaptureSizesForCodec(const QString &codecName);
+ void setCaptureSize(const QSize &size);
+
+ // Image Codec
+ QStringList supportedImageCaptureCodecs();
+ QString imageCaptureCodec();
+ void setImageCaptureCodec(const QString &codecName);
+ QString imageCaptureCodecDescription(const QString &codecName);
+
+ // Image Quality
+ QtMultimediaKit::EncodingQuality captureQuality() const;
+ void setCaptureQuality(const QtMultimediaKit::EncodingQuality &quality);
+
+ // S60 3.1 Focus Control (S60 3.2 and later via S60CameraSettings class)
+ bool isFocusSupported() const;
+ void startFocus();
+ void cancelFocus();
+
+ // Zoom Control
+ qreal maximumZoom();
+ qreal minZoom();
+ qreal maxDigitalZoom();
+ void doSetZoomFactorL(qreal optical, qreal digital);
+ qreal opticalZoomFactor();
+ qreal digitalZoomFactor();
+
+ // Exposure Mode Control
+ QCameraExposure::ExposureMode exposureMode();
+ void setExposureMode(QCameraExposure::ExposureMode mode);
+ bool isExposureModeSupported(QCameraExposure::ExposureMode mode) const;
+
+ // Flash Mode Control
+ QCameraExposure::FlashMode flashMode();
+ void setFlashMode(QCameraExposure::FlashModes mode);
+ QCameraExposure::FlashModes supportedFlashModes();
+
+ // Contrast Control
+ int contrast() const;
+ void setContrast(int value);
+
+ // Brightness Control
+ int brightness() const;
+ void setBrightness(int value);
+
+ // White Balance Mode Control
+ QCameraImageProcessing::WhiteBalanceMode whiteBalanceMode();
+ void setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode);
+ bool isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const;
+
+public: // Image Decoding & Encoding Notifications
+
+ void handleImageDecoded(int error);
+ void handleImageEncoded(int error);
+
+protected: // MCameraEngineObserver
+
+ void MceoFocusComplete();
+ void MceoCapturedDataReady(TDesC8* aData);
+ void MceoCapturedBitmapReady(CFbsBitmap* aBitmap);
+ void MceoHandleError(TCameraEngineError aErrorType, TInt aError);
+
+#ifdef ECAM_PREVIEW_API
+protected: // MCameraPreviewObserver
+
+ void MceoPreviewReady(CFbsBitmap& aPreview);
+#endif // ECAM_PREVIEW_API
+
+private: // Internal
+
+ QCameraImageCapture::Error fromSymbianErrorToQtMultimediaError(int aError);
+
+ void initializeImageCaptureSettings();
+ void resetSession(bool errorHandling = false);
+
+ CCamera::TFormat selectFormatForCodec(const QString &codec);
+ CCamera::TFormat defaultImageFormat();
+ bool queryCurrentCameraInfo();
+ QMap<QString, int> formatMap();
+ QMap<QString, QString> codecDescriptionMap();
+ void updateImageCaptureFormats();
+
+ void doSetWhiteBalanceModeL(QCameraImageProcessing::WhiteBalanceMode mode);
+
+ void doSetFlashModeL(QCameraExposure::FlashModes mode);
+ void doSetExposureModeL(QCameraExposure::ExposureMode mode);
+
+ void saveImageL(TDesC8 *aData, TFileName &aPath);
+ void processFileName(const QString &fileName);
+ TFileName convertImagePath();
+
+signals: // Notifications
+
+ void stateChanged(QCamera::State);
+ void advancedSettingChanged();
+ void captureSizeChanged(const QSize&);
+
+ // Error signals
+ void cameraError(int, const QString&); // For QCamera::error
+ void captureError(int, int, const QString&); // For QCameraImageCapture::error
+
+ // Capture notifications
+ void readyForCaptureChanged(bool);
+ void imageExposed(int);
+ void imageCaptured(const int, const QImage&);
+ void imageSaved(const int, const QString&);
+
+ // Focus notifications
+ void focusStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason);
+
+private slots: // Internal Slots
+
+ void cameraStatusChanged(QCamera::Status);
+
+private: // Data
+
+ CCameraEngine *m_cameraEngine;
+ S60CameraSettings *m_advancedSettings;
+ mutable TCameraInfo *m_cameraInfo;
+ CFbsBitmap *m_previewBitmap;
+ CActiveScheduler *m_activeScheduler;
+ RFs *m_fileSystemAccess;
+ S60ImageCaptureDecoder *m_imageDecoder;
+ S60ImageCaptureEncoder *m_imageEncoder;
+ mutable int m_error; // Symbian ErrorCode
+ TInt m_activeDeviceIndex;
+ bool m_cameraStarted;
+ ImageCaptureState m_icState;
+ QStringList m_supportedImageCodecs;
+ QString m_currentCodec;
+ CCamera::TFormat m_currentFormat;
+ QSize m_captureSize;
+ int m_symbianImageQuality;
+ bool m_captureSettingsSet;
+ QString m_stillCaptureFileName;
+ QString m_requestedStillCaptureFileName;
+ mutable int m_currentImageId;
+ QList<uint> m_formats;
+ // This indicates that image capture should be triggered right after
+ // camera and image setting initialization has completed
+ bool m_captureWhenReady;
+ bool m_previewDecodingOngoing;
+ bool m_previewInWaitLoop;
+};
+
+#endif // S60IMAGECAPTURESESSION_H
diff --git a/src/plugins/symbian/ecam/s60imageencodercontrol.cpp b/src/plugins/symbian/ecam/s60imageencodercontrol.cpp
new file mode 100644
index 000000000..bfbf8d36b
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60imageencodercontrol.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** 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 <QtCore/qstring.h>
+
+#include "s60imageencodercontrol.h"
+#include "s60imagecapturesession.h"
+
+S60ImageEncoderControl::S60ImageEncoderControl(QObject *parent) :
+ QImageEncoderControl(parent)
+{
+}
+
+S60ImageEncoderControl::S60ImageEncoderControl(S60ImageCaptureSession *session, QObject *parent) :
+ QImageEncoderControl(parent)
+{
+ m_session = session;
+}
+
+S60ImageEncoderControl::~S60ImageEncoderControl()
+{
+}
+
+QList<QSize> S60ImageEncoderControl::supportedResolutions(
+ const QImageEncoderSettings &settings, bool *continuous) const
+{
+ QList<QSize> resolutions = m_session->supportedCaptureSizesForCodec(settings.codec());
+
+ // Discrete resolutions are returned
+ if (continuous)
+ *continuous = false;
+
+ return resolutions;
+}
+QStringList S60ImageEncoderControl::supportedImageCodecs() const
+{
+ return m_session->supportedImageCaptureCodecs();
+}
+
+QString S60ImageEncoderControl::imageCodecDescription(const QString &codec) const
+{
+ return m_session->imageCaptureCodecDescription(codec);
+}
+
+QImageEncoderSettings S60ImageEncoderControl::imageSettings() const
+{
+ // Update setting values from session
+ QImageEncoderSettings settings;
+ settings.setCodec(m_session->imageCaptureCodec());
+ settings.setResolution(m_session->captureSize());
+ settings.setQuality(m_session->captureQuality());
+
+ return settings;
+}
+void S60ImageEncoderControl::setImageSettings(const QImageEncoderSettings &settings)
+{
+ // Notify that settings have been implicitly set and there's no need to
+ // initialize them in case camera is changed
+ m_session->notifySettingsSet();
+
+ if (!settings.isNull()) {
+ if (!settings.codec().isEmpty()) {
+ if (settings.resolution() != QSize(-1,-1)) { // Codec, Resolution & Quality
+ m_session->setImageCaptureCodec(settings.codec());
+ m_session->setCaptureSize(settings.resolution());
+ m_session->setCaptureQuality(settings.quality());
+ } else { // Codec and Quality
+ m_session->setImageCaptureCodec(settings.codec());
+ m_session->setCaptureQuality(settings.quality());
+ }
+ } else {
+ if (settings.resolution() != QSize(-1,-1)) { // Resolution & Quality
+ m_session->setCaptureSize(settings.resolution());
+ m_session->setCaptureQuality(settings.quality());
+ }
+ else // Only Quality
+ m_session->setCaptureQuality(settings.quality());
+ }
+
+ // Prepare ImageCapture with the settings and set error if needed
+ int prepareSuccess = m_session->prepareImageCapture();
+
+ // Preparation fails with KErrNotReady if camera has not been started.
+ // That can be ignored since settings are set internally in that case.
+ if (prepareSuccess != KErrNotReady && prepareSuccess != KErrNone)
+ m_session->setError(prepareSuccess, tr("Failure in preparation of image capture."));
+ }
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60imageencodercontrol.h b/src/plugins/symbian/ecam/s60imageencodercontrol.h
new file mode 100644
index 000000000..99a308286
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60imageencodercontrol.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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 S60IMAGEENCODERCONTROL_H
+#define S60IMAGEENCODERCONTROL_H
+
+#include <QtCore/qobject.h>
+#include "qimageencodercontrol.h"
+
+QT_USE_NAMESPACE
+
+class S60ImageCaptureSession;
+
+/*
+ * Control for setting encoding settings for the captured image.
+ */
+class S60ImageEncoderControl : public QImageEncoderControl
+{
+ Q_OBJECT
+
+public: // Contructors & Destructor
+
+ S60ImageEncoderControl(QObject *parent = 0);
+ S60ImageEncoderControl(S60ImageCaptureSession *session, QObject *parent = 0);
+ ~S60ImageEncoderControl();
+
+public: // QImageEncoderControl
+
+ // Codec
+ QStringList supportedImageCodecs() const;
+ QString imageCodecDescription(const QString &codec) const;
+
+ // Resolution
+ QList<QSize> supportedResolutions(const QImageEncoderSettings &settings,
+ bool *continuous = 0) const;
+
+ // Settings
+ QImageEncoderSettings imageSettings() const;
+ void setImageSettings(const QImageEncoderSettings &settings);
+
+private: // Data
+
+ S60ImageCaptureSession *m_session;
+};
+
+#endif // S60IMAGEENCODERCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60mediacontainercontrol.cpp b/src/plugins/symbian/ecam/s60mediacontainercontrol.cpp
new file mode 100644
index 000000000..f0d20f4e3
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60mediacontainercontrol.cpp
@@ -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 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 "s60mediacontainercontrol.h"
+#include "s60videocapturesession.h"
+#include "s60cameraconstants.h"
+
+S60MediaContainerControl::S60MediaContainerControl(QObject *parent):
+ QMediaContainerControl(parent)
+{
+}
+
+S60MediaContainerControl::S60MediaContainerControl(S60VideoCaptureSession *session, QObject *parent):
+ QMediaContainerControl(parent)
+{
+ m_session = session;
+
+ // Set default video container
+ m_supportedContainers = m_session->supportedVideoContainers();
+
+ if (!m_supportedContainers.isEmpty()) {
+ // Check if default container is supported
+ if (m_supportedContainers.indexOf(KMimeTypeDefaultContainer) != -1)
+ setContainerMimeType(KMimeTypeDefaultContainer);
+ // Otherwise use first in the list
+ else
+ setContainerMimeType(m_supportedContainers[0]); // First as default
+ } else {
+ m_session->setError(KErrGeneral, tr("No supported video containers found."));
+ }
+}
+
+S60MediaContainerControl::~S60MediaContainerControl()
+{
+ m_supportedContainers.clear();
+ m_containerDescriptions.clear();
+}
+
+QStringList S60MediaContainerControl::supportedContainers() const
+{
+ return m_session->supportedVideoContainers();
+}
+
+QString S60MediaContainerControl::containerMimeType() const
+{
+ return m_session->videoContainer();
+}
+
+void S60MediaContainerControl::setContainerMimeType(const QString &containerMimeType)
+{
+ m_session->setVideoContainer(containerMimeType);
+}
+
+QString S60MediaContainerControl::containerDescription(const QString &containerMimeType) const
+{
+ return m_session->videoContainerDescription(containerMimeType);
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60mediacontainercontrol.h b/src/plugins/symbian/ecam/s60mediacontainercontrol.h
new file mode 100644
index 000000000..057b4bc43
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60mediacontainercontrol.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** 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 S60MEDIACONTAINERCONTROL_H
+#define S60MEDIACONTAINERCONTROL_H
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+#include <qmediacontainercontrol.h>
+
+QT_USE_NAMESPACE
+
+class S60VideoCaptureSession;
+
+/*
+ * Control for setting container (file format) for video recorded using
+ * QMediaRecorder.
+ */
+class S60MediaContainerControl : public QMediaContainerControl
+{
+ Q_OBJECT
+
+public: // Contructors & Destructor
+
+ S60MediaContainerControl(QObject *parent = 0);
+ S60MediaContainerControl(S60VideoCaptureSession *session, QObject *parent = 0);
+ virtual ~S60MediaContainerControl();
+
+public: // QMediaContainerControl
+
+ QStringList supportedContainers() const;
+ QString containerMimeType() const;
+ void setContainerMimeType(const QString &containerMimeType);
+
+ QString containerDescription(const QString &containerMimeType) const;
+
+private: // Data
+
+ S60VideoCaptureSession *m_session;
+ QStringList m_supportedContainers;
+ QMap<QString, QString> m_containerDescriptions;
+};
+
+#endif // S60MEDIACONTAINERCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60mediarecordercontrol.cpp b/src/plugins/symbian/ecam/s60mediarecordercontrol.cpp
new file mode 100644
index 000000000..2a1394fa5
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60mediarecordercontrol.cpp
@@ -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$
+**
+****************************************************************************/
+
+#include "s60cameraservice.h"
+#include "s60mediarecordercontrol.h"
+#include "s60cameracontrol.h"
+#include "s60videocapturesession.h"
+
+S60MediaRecorderControl::S60MediaRecorderControl(QObject *parent) :
+ QMediaRecorderControl(parent)
+{
+}
+
+S60MediaRecorderControl::S60MediaRecorderControl(S60CameraService *service,
+ S60VideoCaptureSession *session,
+ QObject *parent):
+ QMediaRecorderControl(parent),
+ m_state(QMediaRecorder::StoppedState) // Default RecorderState
+{
+ m_session = session;
+ m_service = service;
+ m_cameraControl = qobject_cast<S60CameraControl *>(m_service->requestControl(QCameraControl_iid));
+
+ // Connect signals
+ connect(m_session, SIGNAL(stateChanged(S60VideoCaptureSession::TVideoCaptureState)),
+ this, SLOT(updateState(S60VideoCaptureSession::TVideoCaptureState)));
+ connect(m_session, SIGNAL(positionChanged(qint64)), this, SIGNAL(durationChanged(qint64)));
+ connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool)));
+ connect(m_session, SIGNAL(error(int,const QString &)), this, SIGNAL(error(int,const QString &)));
+}
+
+S60MediaRecorderControl::~S60MediaRecorderControl()
+{
+ // Release requested control
+ if (m_cameraControl)
+ m_service->releaseControl(m_cameraControl);
+}
+
+QUrl S60MediaRecorderControl::outputLocation() const
+{
+ return m_session->outputLocation();
+}
+
+bool S60MediaRecorderControl::setOutputLocation(const QUrl& sink)
+{
+ // Output location can only be set in StoppedState
+ if (m_state == QMediaRecorder::StoppedState)
+ return m_session->setOutputLocation(sink);
+
+ // Do not signal error, but notify that setting was not effective
+ return false;
+}
+
+QMediaRecorder::State S60MediaRecorderControl::convertInternalStateToQtState(S60VideoCaptureSession::TVideoCaptureState aState) const
+{
+ QMediaRecorder::State state;
+
+ switch (aState) {
+ case S60VideoCaptureSession::ERecording:
+ state = QMediaRecorder::RecordingState;
+ break;
+ case S60VideoCaptureSession::EPaused:
+ state = QMediaRecorder::PausedState;
+ break;
+
+ default:
+ // All others
+ state = QMediaRecorder::StoppedState;
+ break;
+ }
+
+ return state;
+}
+
+void S60MediaRecorderControl::updateState(S60VideoCaptureSession::TVideoCaptureState state)
+{
+ QMediaRecorder::State newState = convertInternalStateToQtState(state);
+
+ if (m_state != newState) {
+ m_state = newState;
+ emit stateChanged(m_state);
+ }
+}
+
+QMediaRecorder::State S60MediaRecorderControl::state() const
+{
+ return m_state;
+}
+
+qint64 S60MediaRecorderControl::duration() const
+{
+ return m_session->position();
+}
+
+/*
+This method is called after encoder configuration is done.
+Encoder can load necessary resources at this point,
+to reduce delay before recording is started. Calling this method reduces the
+latency when calling record() to start video recording.
+*/
+void S60MediaRecorderControl::applySettings()
+{
+ m_session->applyAllSettings();
+}
+
+void S60MediaRecorderControl::record()
+{
+ if (m_state == QMediaRecorder::RecordingState)
+ return;
+
+ if (m_cameraControl && m_cameraControl->captureMode() != QCamera::CaptureVideo) {
+ emit error(QCamera::CameraError, tr("Video capture mode is not selected."));
+ return;
+ }
+
+ m_session->startRecording();
+}
+
+void S60MediaRecorderControl::pause()
+{
+ if (m_state != QMediaRecorder::RecordingState) {
+ // Discard
+ return;
+ }
+
+ m_session->pauseRecording();
+}
+
+void S60MediaRecorderControl::stop()
+{
+ if (m_state == QMediaRecorder::StoppedState) {
+ // Ignore
+ return;
+ }
+
+ m_session->stopRecording();
+}
+
+bool S60MediaRecorderControl::isMuted() const
+{
+ return m_session->isMuted();
+}
+
+void S60MediaRecorderControl::setMuted(bool muted)
+{
+ m_session->setMuted(muted);
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60mediarecordercontrol.h b/src/plugins/symbian/ecam/s60mediarecordercontrol.h
new file mode 100644
index 000000000..5db7477bd
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60mediarecordercontrol.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** 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 S60MEDIARECORDERCONTROL_H
+#define S60MEDIARECORDERCONTROL_H
+
+#include <QtCore/qurl.h>
+#include <qmediarecorder.h>
+#include <qmediarecordercontrol.h>
+
+#include "s60videocapturesession.h"
+
+QT_USE_NAMESPACE
+
+class S60VideoCaptureSession;
+class S60CameraService;
+class S60CameraControl;
+
+/*
+ * Control for video recording operations.
+ */
+class S60MediaRecorderControl : public QMediaRecorderControl
+{
+ Q_OBJECT
+
+public: // Contructors & Destructor
+
+ S60MediaRecorderControl(QObject *parent = 0);
+ S60MediaRecorderControl(S60CameraService *service,
+ S60VideoCaptureSession *session,
+ QObject *parent = 0);
+ ~S60MediaRecorderControl();
+
+public: // QMediaRecorderControl
+
+ QUrl outputLocation() const;
+ bool setOutputLocation(const QUrl &sink);
+
+ QMediaRecorder::State state() const;
+
+ qint64 duration() const;
+
+ bool isMuted() const;
+
+ void applySettings();
+
+/*
+Q_SIGNALS: // QMediaRecorderControl
+ void stateChanged(QMediaRecorder::State state);
+ void durationChanged(qint64 position);
+ void mutedChanged(bool muted);
+ void error(int error, const QString &errorString);
+*/
+
+public slots: // QMediaRecorderControl
+
+ void record();
+ void pause();
+ void stop();
+ void setMuted(bool);
+
+private:
+
+ QMediaRecorder::State convertInternalStateToQtState(
+ S60VideoCaptureSession::TVideoCaptureState aState) const;
+
+private slots:
+
+ void updateState(S60VideoCaptureSession::TVideoCaptureState state);
+
+private: // Data
+
+ S60VideoCaptureSession *m_session;
+ S60CameraService *m_service;
+ S60CameraControl *m_cameraControl;
+ QMediaRecorder::State m_state;
+
+};
+
+#endif // S60MEDIARECORDERCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60videocapturesession.cpp b/src/plugins/symbian/ecam/s60videocapturesession.cpp
new file mode 100644
index 000000000..7158f8696
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videocapturesession.cpp
@@ -0,0 +1,2995 @@
+/****************************************************************************
+**
+** 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 <QtCore/qstring.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qtimer.h>
+
+#include "s60videocapturesession.h"
+#include "s60cameraconstants.h"
+
+#include <utf.h>
+#include <bautils.h>
+
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+#include <mmf/devvideo/devvideorecord.h>
+#endif
+
+S60VideoCaptureSession::S60VideoCaptureSession(QObject *parent) :
+ QObject(parent),
+ m_cameraEngine(0),
+ m_videoRecorder(0),
+ m_position(0),
+ m_error(KErrNone),
+ m_cameraStarted(false),
+ m_captureState(ENotInitialized), // Default state
+ m_sink(QUrl()),
+ m_requestedSink(QUrl()),
+ m_captureSettingsSet(false),
+ m_container(QString()),
+ m_requestedContainer(QString()),
+ m_muted(false),
+ m_maxClipSize(-1),
+ m_videoControllerMap(QHash<int, QHash<int,VideoFormatData> >()),
+ m_videoParametersForEncoder(QList<MaxResolutionRatesAndTypes>()),
+ m_openWhenReady(false),
+ m_prepareAfterOpenComplete(false),
+ m_startAfterPrepareComplete(false),
+ m_uncommittedSettings(false),
+ m_commitSettingsWhenReady(false)
+{
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+ // Populate info of supported codecs, and their resolution, etc.
+ TRAPD(err, doPopulateVideoCodecsDataL());
+ setError(err, tr("Failed to gather video codec information."));
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+
+ initializeVideoCaptureSettings();
+
+ m_durationTimer = new QTimer;
+ m_durationTimer->setInterval(KDurationChangedInterval);
+ connect(m_durationTimer, SIGNAL(timeout()), this, SLOT(durationTimerTriggered()));
+}
+
+S60VideoCaptureSession::~S60VideoCaptureSession()
+{
+ if (m_captureState >= ERecording)
+ m_videoRecorder->Stop();
+
+ if (m_captureState >= EInitialized)
+ m_videoRecorder->Close();
+
+ if (m_videoRecorder) {
+ delete m_videoRecorder;
+ m_videoRecorder = 0;
+ }
+
+ if (m_durationTimer) {
+ delete m_durationTimer;
+ m_durationTimer = 0;
+ }
+
+ // Clear all data structures
+ foreach (MaxResolutionRatesAndTypes structure, m_videoParametersForEncoder) {
+ structure.frameRatePictureSizePair.clear();
+ structure.mimeTypes.clear();
+ }
+ m_videoParametersForEncoder.clear();
+
+ m_videoCodecList.clear();
+ m_audioCodecList.clear();
+
+ QList<TInt> controllers = m_videoControllerMap.keys();
+ for (int i = 0; i < controllers.size(); ++i) {
+ foreach(VideoFormatData data, m_videoControllerMap[controllers[i]]){
+ data.supportedMimeTypes.clear();
+ }
+ m_videoControllerMap[controllers[i]].clear();
+ }
+ m_videoControllerMap.clear();
+}
+
+/*
+ * This function can be used both internally and from Control classes using this session.
+ * The error notification will go to client application through QMediaRecorder error signal.
+ */
+void S60VideoCaptureSession::setError(const TInt error, const QString &description)
+{
+ if (error == KErrNone)
+ return;
+
+ m_error = error;
+ QMediaRecorder::Error recError = fromSymbianErrorToQtMultimediaError(m_error);
+
+ // Stop/Close/Reset only of other than "not supported" error
+ if (m_error != KErrNotSupported) {
+ if (m_captureState >= ERecording)
+ m_videoRecorder->Stop();
+
+ if (m_captureState >= EInitialized)
+ m_videoRecorder->Close();
+
+ // Reset state
+ if (m_captureState != ENotInitialized) {
+ if (m_durationTimer->isActive())
+ m_durationTimer->stop();
+ m_captureState = ENotInitialized;
+ emit stateChanged(m_captureState);
+ }
+ }
+
+ emit this->error(recError, description);
+
+ // Reset only of other than "not supported" error
+ if (m_error != KErrNotSupported)
+ resetSession(true);
+ else
+ m_error = KErrNone; // Reset error
+}
+
+QMediaRecorder::Error S60VideoCaptureSession::fromSymbianErrorToQtMultimediaError(int aError)
+{
+ switch(aError) {
+ case KErrNone:
+ return QMediaRecorder::NoError; // No errors have occurred
+ case KErrArgument:
+ case KErrNotSupported:
+ return QMediaRecorder::FormatError; // The feature/format is not supported
+ case KErrNoMemory:
+ case KErrNotFound:
+ case KErrBadHandle:
+ return QMediaRecorder::ResourceError; // Not able to use camera/recorder resources
+
+ default:
+ return QMediaRecorder::ResourceError; // Other error has occurred
+ }
+}
+
+/*
+ * This function applies all recording settings to make latency during the
+ * start of the recording as short as possible. After this it is not possible to
+ * set settings (inc. output location) before stopping the recording.
+ */
+void S60VideoCaptureSession::applyAllSettings()
+{
+ switch (m_captureState) {
+ case ENotInitialized:
+ case EInitializing:
+ m_commitSettingsWhenReady = true;
+ return;
+ case EInitialized:
+ setOutputLocation(QUrl());
+ m_prepareAfterOpenComplete = true;
+ return;
+ case EOpening:
+ m_prepareAfterOpenComplete = true;
+ return;
+ case EOpenComplete:
+ // Do nothing, ready to commit
+ break;
+ case EPreparing:
+ m_commitSettingsWhenReady = true;
+ return;
+ case EPrepared:
+ // Revert state internally, since logically applying settings means going
+ // from OpenComplete ==> Preparing ==> Prepared.
+ m_captureState = EOpenComplete;
+ break;
+ case ERecording:
+ case EPaused:
+ setError(KErrNotReady, tr("Cannot apply settings while recording."));
+ return;
+
+ default:
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+
+ // Commit settings - State is now OpenComplete (possibly reverted from Prepared)
+ commitVideoEncoderSettings();
+
+ // If capture state has been changed to:
+ // * Opening: A different media container has been requested
+ // * Other: Failure during the setting committing
+ // ==> Return
+ if (m_captureState != EOpenComplete)
+ return;
+
+ // Start preparing
+ m_captureState = EPreparing;
+ emit stateChanged(m_captureState);
+
+ if (m_cameraEngine->IsCameraReady())
+ m_videoRecorder->Prepare();
+}
+
+void S60VideoCaptureSession::setCameraHandle(CCameraEngine* cameraHandle)
+{
+ m_cameraEngine = cameraHandle;
+
+ // Initialize settings for the new camera
+ initializeVideoCaptureSettings();
+
+ resetSession();
+}
+
+void S60VideoCaptureSession::notifySettingsSet()
+{
+ m_captureSettingsSet = true;
+}
+
+void S60VideoCaptureSession::doInitializeVideoRecorderL()
+{
+ if (m_captureState > ENotInitialized)
+ resetSession();
+
+ m_captureState = EInitializing;
+ emit stateChanged(m_captureState);
+
+ // Open Dummy file to be able to query supported settings
+ int cameraHandle = m_cameraEngine->Camera() ? m_cameraEngine->Camera()->Handle() : 0;
+
+ TUid controllerUid;
+ TUid formatUid;
+ selectController(m_requestedContainer, controllerUid, formatUid);
+
+ if (m_videoRecorder) {
+ // File open completes in MvruoOpenComplete
+ TRAPD(err, m_videoRecorder->OpenFileL(KDummyVideoFile, cameraHandle, controllerUid, formatUid));
+ setError(err, tr("Failed to initialize video recorder."));
+ m_container = m_requestedContainer;
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+void S60VideoCaptureSession::resetSession(bool errorHandling)
+{
+ if (m_videoRecorder) {
+ delete m_videoRecorder;
+ m_videoRecorder = 0;
+ }
+
+ if (m_captureState != ENotInitialized) {
+ if (m_durationTimer->isActive())
+ m_durationTimer->stop();
+ m_captureState = ENotInitialized;
+ emit stateChanged(m_captureState);
+ }
+
+ // Reset error to be able to recover
+ m_error = KErrNone;
+
+ // Reset flags
+ m_openWhenReady = false;
+ m_prepareAfterOpenComplete = false;
+ m_startAfterPrepareComplete = false;
+ m_uncommittedSettings = false;
+ m_commitSettingsWhenReady = false;
+
+ TRAPD(err, m_videoRecorder = CVideoRecorderUtility::NewL(*this));
+ if (err) {
+ qWarning("Failed to create video recorder.");
+ if (errorHandling)
+ emit error(QMediaRecorder::ResourceError, tr("Failed to recover from video error."));
+ else
+ setError(err, tr("Failure in creation of video recorder device."));
+ return;
+ }
+
+ updateVideoCaptureContainers();
+}
+
+QList<QSize> S60VideoCaptureSession::supportedVideoResolutions(bool *continuous)
+{
+ QList<QSize> resolutions;
+
+ // Secondary Camera
+ if (m_cameraEngine->CurrentCameraIndex() != 0) {
+ TCameraInfo *info = m_cameraEngine->CameraInfo();
+ if (info) {
+ TInt videoResolutionCount = info->iNumVideoFrameSizesSupported;
+ CCamera *camera = m_cameraEngine->Camera();
+ if (camera) {
+ for (TInt i = 0; i < videoResolutionCount; ++i) {
+ TSize checkedResolution;
+ camera->EnumerateVideoFrameSizes(checkedResolution, i, CCamera::EFormatYUV420Planar);
+ QSize qtResolution(checkedResolution.iWidth, checkedResolution.iHeight);
+ if (!resolutions.contains(qtResolution))
+ resolutions.append(qtResolution);
+ }
+ } else {
+ setError(KErrGeneral, tr("Could not query supported video resolutions."));
+ }
+ } else {
+ setError(KErrGeneral, tr("Could not query supported video resolutions."));
+ }
+
+ // Primary Camera
+ } else {
+
+ if (m_videoParametersForEncoder.count() > 0) {
+
+ // Also arbitrary resolutions are supported
+ if (continuous)
+ *continuous = true;
+
+ // Append all supported resolutions to the list
+ foreach (MaxResolutionRatesAndTypes parameters, m_videoParametersForEncoder)
+ for (int i = 0; i < parameters.frameRatePictureSizePair.count(); ++i)
+ if (!resolutions.contains(parameters.frameRatePictureSizePair[i].frameSize))
+ resolutions.append(parameters.frameRatePictureSizePair[i].frameSize);
+ }
+ }
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ resolutions << QSize(160, 120);
+ resolutions << QSize(352, 288);
+ resolutions << QSize(640,480);
+#endif // Q_CC_NOKIAX86
+
+ return resolutions;
+}
+
+QList<QSize> S60VideoCaptureSession::supportedVideoResolutions(const QVideoEncoderSettings &settings, bool *continuous)
+{
+ QList<QSize> supportedFrameSizes;
+
+ // Secondary Camera
+ if (m_cameraEngine->CurrentCameraIndex() != 0) {
+ TCameraInfo *info = m_cameraEngine->CameraInfo();
+ if (info) {
+ TInt videoResolutionCount = info->iNumVideoFrameSizesSupported;
+ CCamera *camera = m_cameraEngine->Camera();
+ if (camera) {
+ for (TInt i = 0; i < videoResolutionCount; ++i) {
+ TSize checkedResolution;
+ camera->EnumerateVideoFrameSizes(checkedResolution, i, CCamera::EFormatYUV420Planar);
+ QSize qtResolution(checkedResolution.iWidth, checkedResolution.iHeight);
+ if (!supportedFrameSizes.contains(qtResolution))
+ supportedFrameSizes.append(qtResolution);
+ }
+ } else {
+ setError(KErrGeneral, tr("Could not query supported video resolutions."));
+ }
+ } else {
+ setError(KErrGeneral, tr("Could not query supported video resolutions."));
+ }
+
+ // Primary Camera
+ } else {
+
+ if (settings.codec().isEmpty())
+ return supportedFrameSizes;
+
+ if (!m_videoCodecList.contains(settings.codec(), Qt::CaseInsensitive))
+ return supportedFrameSizes;
+
+ // Also arbitrary resolutions are supported
+ if (continuous)
+ *continuous = true;
+
+ // Find maximum resolution (using defined framerate if set)
+ for (int i = 0; i < m_videoParametersForEncoder.count(); ++i) {
+ // Check if encoder supports the requested codec
+ if (!m_videoParametersForEncoder[i].mimeTypes.contains(settings.codec(), Qt::CaseInsensitive))
+ continue;
+
+ foreach (SupportedFrameRatePictureSize pair, m_videoParametersForEncoder[i].frameRatePictureSizePair) {
+ if (!supportedFrameSizes.contains(pair.frameSize)) {
+ QSize maxForMime = maximumResolutionForMimeType(settings.codec());
+ if (settings.frameRate() != 0) {
+ if (settings.frameRate() <= pair.frameRate) {
+ if ((pair.frameSize.width() * pair.frameSize.height()) <= (maxForMime.width() * maxForMime.height()))
+ supportedFrameSizes.append(pair.frameSize);
+ }
+ } else {
+ if ((pair.frameSize.width() * pair.frameSize.height()) <= (maxForMime.width() * maxForMime.height()))
+ supportedFrameSizes.append(pair.frameSize);
+ }
+ }
+ }
+ }
+ }
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ supportedFrameSizes << QSize(160, 120);
+ supportedFrameSizes << QSize(352, 288);
+ supportedFrameSizes << QSize(640,480);
+#endif
+
+ return supportedFrameSizes;
+}
+
+QList<qreal> S60VideoCaptureSession::supportedVideoFrameRates(bool *continuous)
+{
+ QList<qreal> supportedRatesList;
+
+ if (m_videoParametersForEncoder.count() > 0) {
+ // Insert min and max to the list
+ supportedRatesList.append(1.0); // Use 1fps as sensible minimum
+ qreal foundMaxFrameRate(0.0);
+
+ // Also arbitrary framerates are supported
+ if (continuous)
+ *continuous = true;
+
+ // Find max framerate
+ foreach (MaxResolutionRatesAndTypes parameters, m_videoParametersForEncoder) {
+ for (int i = 0; i < parameters.frameRatePictureSizePair.count(); ++i) {
+ qreal maxFrameRate = parameters.frameRatePictureSizePair[i].frameRate;
+ if (maxFrameRate > foundMaxFrameRate)
+ foundMaxFrameRate = maxFrameRate;
+ }
+ }
+
+ supportedRatesList.append(foundMaxFrameRate);
+ }
+
+ // Add also other standard framerates to the list
+ if (!supportedRatesList.isEmpty()) {
+ if (supportedRatesList.last() > 30.0) {
+ if (!supportedRatesList.contains(30.0))
+ supportedRatesList.insert(1, 30.0);
+ }
+ if (supportedRatesList.last() > 25.0) {
+ if (!supportedRatesList.contains(25.0))
+ supportedRatesList.insert(1, 25.0);
+ }
+ if (supportedRatesList.last() > 15.0) {
+ if (!supportedRatesList.contains(15.0))
+ supportedRatesList.insert(1, 15.0);
+ }
+ if (supportedRatesList.last() > 10.0) {
+ if (!supportedRatesList.contains(10))
+ supportedRatesList.insert(1, 10.0);
+ }
+ }
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ supportedRatesList << 30.0 << 25.0 << 15.0 << 10.0 << 5.0;
+#endif
+
+ return supportedRatesList;
+}
+
+QList<qreal> S60VideoCaptureSession::supportedVideoFrameRates(const QVideoEncoderSettings &settings, bool *continuous)
+{
+ QList<qreal> supportedFrameRates;
+
+ if (settings.codec().isEmpty())
+ return supportedFrameRates;
+ if (!m_videoCodecList.contains(settings.codec(), Qt::CaseInsensitive))
+ return supportedFrameRates;
+
+ // Also arbitrary framerates are supported
+ if (continuous)
+ *continuous = true;
+
+ // Find maximum framerate (using defined resolution if set)
+ for (int i = 0; i < m_videoParametersForEncoder.count(); ++i) {
+ // Check if encoder supports the requested codec
+ if (!m_videoParametersForEncoder[i].mimeTypes.contains(settings.codec(), Qt::CaseInsensitive))
+ continue;
+
+ foreach (SupportedFrameRatePictureSize pair, m_videoParametersForEncoder[i].frameRatePictureSizePair) {
+ if (!supportedFrameRates.contains(pair.frameRate)) {
+ qreal maxRateForMime = maximumFrameRateForMimeType(settings.codec());
+ if (settings.resolution().width() != 0 && settings.resolution().height() != 0) {
+ if((settings.resolution().width() * settings.resolution().height()) <= (pair.frameSize.width() * pair.frameSize.height())) {
+ if (pair.frameRate <= maxRateForMime)
+ supportedFrameRates.append(pair.frameRate);
+ }
+ } else {
+ if (pair.frameRate <= maxRateForMime)
+ supportedFrameRates.append(pair.frameRate);
+ }
+ }
+ }
+ }
+
+ // Add also other standard framerates to the list
+ if (!supportedFrameRates.isEmpty()) {
+ if (supportedFrameRates.last() > 30.0) {
+ if (!supportedFrameRates.contains(30.0))
+ supportedFrameRates.insert(1, 30.0);
+ }
+ if (supportedFrameRates.last() > 25.0) {
+ if (!supportedFrameRates.contains(25.0))
+ supportedFrameRates.insert(1, 25.0);
+ }
+ if (supportedFrameRates.last() > 15.0) {
+ if (!supportedFrameRates.contains(15.0))
+ supportedFrameRates.insert(1, 15.0);
+ }
+ if (supportedFrameRates.last() > 10.0) {
+ if (!supportedFrameRates.contains(10))
+ supportedFrameRates.insert(1, 10.0);
+ }
+ }
+
+#ifdef Q_CC_NOKIAX86 // Emulator
+ supportedFrameRates << 30.0 << 25.0 << 15.0 << 10.0 << 5.0;
+#endif
+
+ return supportedFrameRates;
+}
+
+bool S60VideoCaptureSession::setOutputLocation(const QUrl &sink)
+{
+ m_requestedSink = sink;
+
+ if (m_error)
+ return false;
+
+ switch (m_captureState) {
+ case ENotInitialized:
+ case EInitializing:
+ case EOpening:
+ case EPreparing:
+ m_openWhenReady = true;
+ return true;
+
+ case EInitialized:
+ case EOpenComplete:
+ case EPrepared:
+ // Continue
+ break;
+
+ case ERecording:
+ case EPaused:
+ setError(KErrNotReady, tr("Cannot set file name while recording."));
+ return false;
+
+ default:
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return false;
+ }
+
+ // Empty URL - Use default file name and path (C:\Data\Videos\video.mp4)
+ if (sink.isEmpty()) {
+
+ // Make sure default directory exists
+ QDir videoDir(QDir::rootPath());
+ if (!videoDir.exists(KDefaultVideoPath))
+ videoDir.mkpath(KDefaultVideoPath);
+ QString defaultFile = KDefaultVideoPath;
+ defaultFile.append("\\");
+ defaultFile.append(KDefaultVideoFileName);
+ m_sink.setUrl(defaultFile);
+
+ } else { // Non-empty URL
+
+ QString fullUrl = sink.scheme();
+
+ // Relative URL
+ if (sink.isRelative()) {
+
+ // Extract file name and path from the URL
+ fullUrl = KDefaultVideoPath;
+ fullUrl.append("\\");
+ fullUrl.append(QDir::toNativeSeparators(sink.path()));
+
+ // Absolute URL
+ } else {
+
+ // Extract file name and path from the URL
+ if (fullUrl == "file") {
+ fullUrl = QDir::toNativeSeparators(sink.path().right(sink.path().length() - 1));
+ } else {
+ fullUrl.append(":");
+ fullUrl.append(QDir::toNativeSeparators(sink.path()));
+ }
+ }
+
+ QString fileName = fullUrl.right(fullUrl.length() - fullUrl.lastIndexOf("\\") - 1);
+ QString directory = fullUrl.left(fullUrl.lastIndexOf("\\"));
+ if (directory.lastIndexOf("\\") == (directory.length() - 1))
+ directory = directory.left(directory.length() - 1);
+
+ // URL is Absolute path, not including file name
+ if (!fileName.contains(".")) {
+ if (fileName != "") {
+ directory.append("\\");
+ directory.append(fileName);
+ }
+ fileName = KDefaultVideoFileName;
+ }
+
+ // Make sure absolute directory exists
+ QDir videoDir(QDir::rootPath());
+ if (!videoDir.exists(directory))
+ videoDir.mkpath(directory);
+
+ QString resolvedURL = directory;
+ resolvedURL.append("\\");
+ resolvedURL.append(fileName);
+ m_sink = QUrl(resolvedURL);
+ }
+
+ // State is either Initialized, OpenComplete or Prepared, Close previously opened file
+ if (m_videoRecorder)
+ m_videoRecorder->Close();
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+
+ // Open file
+
+ QString fileName = QDir::toNativeSeparators(m_sink.toString());
+ TPtrC16 fileSink(reinterpret_cast<const TUint16*>(fileName.utf16()));
+
+ int cameraHandle = m_cameraEngine->Camera() ? m_cameraEngine->Camera()->Handle() : 0;
+
+ TUid controllerUid;
+ TUid formatUid;
+ selectController(m_requestedContainer, controllerUid, formatUid);
+
+ if (m_videoRecorder) {
+ // File open completes in MvruoOpenComplete
+ TRAPD(err, m_videoRecorder->OpenFileL(fileSink, cameraHandle, controllerUid, formatUid));
+ setError(err, tr("Failed to initialize video recorder."));
+ m_container = m_requestedContainer;
+ m_captureState = EOpening;
+ emit stateChanged(m_captureState);
+ }
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+
+ m_uncommittedSettings = true;
+ return true;
+}
+
+QUrl S60VideoCaptureSession::outputLocation() const
+{
+ return m_sink;
+}
+
+qint64 S60VideoCaptureSession::position()
+{
+ // Update position only if recording is ongoing
+ if ((m_captureState == ERecording) && m_videoRecorder) {
+ // Signal will be automatically emitted of position changes
+ TRAPD(err, m_position = m_videoRecorder->DurationL().Int64() / 1000);
+ setError(err, tr("Cannot retrieve video position."));
+ }
+
+ return m_position;
+}
+
+S60VideoCaptureSession::TVideoCaptureState S60VideoCaptureSession::state() const
+{
+ return m_captureState;
+}
+
+bool S60VideoCaptureSession::isMuted() const
+{
+ return m_muted;
+}
+
+void S60VideoCaptureSession::setMuted(const bool muted)
+{
+ // CVideoRecorderUtility can mute/unmute only if not recording
+ if (m_captureState > EPrepared) {
+ if (muted)
+ setError(KErrNotSupported, tr("Muting audio is not supported during recording."));
+ else
+ setError(KErrNotSupported, tr("Unmuting audio is not supported during recording."));
+ return;
+ }
+
+ // Check if request is already active
+ if (muted == isMuted())
+ return;
+
+ m_muted = muted;
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::commitVideoEncoderSettings()
+{
+ if (m_captureState == EOpenComplete) {
+
+ if (m_container != m_requestedContainer) {
+ setOutputLocation(m_requestedSink);
+ return;
+ }
+
+ TRAPD(err, doSetCodecsL());
+ if (err) {
+ setError(err, tr("Failed to set audio or video codec."));
+ m_audioSettings.setCodec(KMimeTypeDefaultAudioCodec);
+ m_videoSettings.setCodec(KMimeTypeDefaultVideoCodec);
+ }
+
+ doSetVideoResolution(m_videoSettings.resolution());
+ doSetFrameRate(m_videoSettings.frameRate());
+ doSetBitrate(m_videoSettings.bitRate());
+
+ // Audio/Video EncodingMode are not supported in Symbian
+
+#ifndef S60_31_PLATFORM
+ if (m_audioSettings.sampleRate() != -1 && m_audioSettings.sampleRate() != 0) {
+ TRAP(err, m_videoRecorder->SetAudioSampleRateL((TInt)m_audioSettings.sampleRate()));
+ if (err != KErrNotSupported) {
+ setError(err, tr("Setting audio sample rate failed."));
+ } else {
+ setError(err, tr("Setting audio sample rate is not supported."));
+ m_audioSettings.setSampleRate(KDefaultSampleRate); // Reset
+ }
+ }
+#endif // S60_31_PLATFORM
+
+ TRAP(err, m_videoRecorder->SetAudioBitRateL((TInt)m_audioSettings.bitRate()));
+ if (err != KErrNotSupported) {
+ if (err == KErrArgument) {
+ setError(KErrNotSupported, tr("Requested audio bitrate is not supported or previously set codec is not supported with requested bitrate."));
+ int fallback = 16000;
+ TRAP(err, m_videoRecorder->SetAudioBitRateL(TInt(fallback)));
+ if (err == KErrNone)
+ m_audioSettings.setBitRate(fallback);
+ } else {
+ setError(err, tr("Setting audio bitrate failed."));
+ }
+ }
+
+#ifndef S60_31_PLATFORM
+ if (m_audioSettings.channelCount() != -1) {
+ TRAP(err, m_videoRecorder->SetAudioChannelsL(TUint(m_audioSettings.channelCount())));
+ if (err != KErrNotSupported) {
+ setError(err, tr("Setting audio channel count failed."));
+ } else {
+ setError(err, tr("Setting audio channel count is not supported."));
+ m_audioSettings.setChannelCount(KDefaultChannelCount); // Reset
+ }
+ }
+#endif // S60_31_PLATFORM
+
+ TBool isAudioMuted = EFalse;
+ TRAP(err, isAudioMuted = !m_videoRecorder->AudioEnabledL());
+ if (err != KErrNotSupported && err != KErrNone)
+ setError(err, tr("Failure when checking if audio is enabled."));
+
+ if (m_muted != (bool)isAudioMuted) {
+ TRAP(err, m_videoRecorder->SetAudioEnabledL(TBool(!m_muted)));
+ if (err) {
+ if (err != KErrNotSupported) {
+ setError(err, tr("Failed to mute/unmute audio."));
+ } else {
+ setError(err, tr("Muting/unmuting audio is not supported."));
+ }
+ }
+ else
+ emit mutedChanged(m_muted);
+ }
+
+ m_uncommittedSettings = false; // Reset
+ }
+}
+
+void S60VideoCaptureSession::queryAudioEncoderSettings()
+{
+ if (!m_videoRecorder)
+ return;
+
+ switch (m_captureState) {
+ case ENotInitialized:
+ case EInitializing:
+ case EOpening:
+ case EPreparing:
+ return;
+
+ // Possible to query settings from CVideoRecorderUtility
+ case EInitialized:
+ case EOpenComplete:
+ case EPrepared:
+ case ERecording:
+ case EPaused:
+ break;
+
+ default:
+ return;
+ }
+
+ TInt err = KErrNone;
+
+ // Codec
+ TFourCC audioCodec;
+ TRAP(err, audioCodec = m_videoRecorder->AudioTypeL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying audio codec failed."));
+ }
+ QString codec = "";
+ foreach (TFourCC aCodec, m_audioCodecList) {
+ if (audioCodec == aCodec)
+ codec = m_audioCodecList.key(aCodec);
+ }
+ m_audioSettings.setCodec(codec);
+
+#ifndef S60_31_PLATFORM
+ // Samplerate
+ TInt sampleRate = -1;
+ TRAP(err, sampleRate = m_videoRecorder->AudioSampleRateL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying audio sample rate failed."));
+ }
+ m_audioSettings.setSampleRate(int(sampleRate));
+#endif // S60_31_PLATFORM
+
+ // BitRate
+ TInt bitRate = -1;
+ TRAP(err, bitRate = m_videoRecorder->AudioBitRateL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying audio bitrate failed."));
+ }
+ m_audioSettings.setBitRate(int(bitRate));
+
+#ifndef S60_31_PLATFORM
+ // ChannelCount
+ TUint channelCount = 0;
+ TRAP(err, channelCount = m_videoRecorder->AudioChannelsL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying audio channel count failed."));
+ }
+ if (channelCount != 0)
+ m_audioSettings.setChannelCount(int(channelCount));
+ else
+ m_audioSettings.setChannelCount(-1);
+#endif // S60_31_PLATFORM
+
+ // EncodingMode
+ m_audioSettings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding);
+
+ // IsMuted
+ TBool isEnabled = ETrue;
+ TRAP(err, isEnabled = m_videoRecorder->AudioEnabledL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying whether audio is muted failed."));
+ }
+ m_muted = bool(!isEnabled);
+}
+
+void S60VideoCaptureSession::queryVideoEncoderSettings()
+{
+ if (!m_videoRecorder)
+ return;
+
+ switch (m_captureState) {
+ case ENotInitialized:
+ case EInitializing:
+ case EOpening:
+ case EPreparing:
+ return;
+
+ // Possible to query settings from CVideoRecorderUtility
+ case EInitialized:
+ case EOpenComplete:
+ case EPrepared:
+ case ERecording:
+ case EPaused:
+ break;
+
+ default:
+ return;
+ }
+
+ TInt err = KErrNone;
+
+ // Codec
+ const TDesC8 &videoMimeType = m_videoRecorder->VideoFormatMimeType();
+ QString videoMimeTypeString = "";
+ if (videoMimeType.Length() > 0) {
+ // First convert the 8-bit descriptor to Unicode
+ HBufC16* videoCodec;
+ videoCodec = CnvUtfConverter::ConvertToUnicodeFromUtf8L(videoMimeType);
+ CleanupStack::PushL(videoCodec);
+
+ // Then deep copy QString from that
+ videoMimeTypeString = QString::fromUtf16(videoCodec->Ptr(), videoCodec->Length());
+ m_videoSettings.setCodec(videoMimeTypeString);
+
+ CleanupStack::PopAndDestroy(videoCodec);
+ }
+
+ // Resolution
+ TSize symbianResolution;
+ TRAP(err, m_videoRecorder->GetVideoFrameSizeL(symbianResolution));
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying video resolution failed."));
+ }
+ QSize resolution = QSize(symbianResolution.iWidth, symbianResolution.iHeight);
+ m_videoSettings.setResolution(resolution);
+
+ // FrameRate
+ TReal32 frameRate = 0;
+ TRAP(err, frameRate = m_videoRecorder->VideoFrameRateL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying video framerate failed."));
+ }
+ m_videoSettings.setFrameRate(qreal(frameRate));
+
+ // BitRate
+ TInt bitRate = -1;
+ TRAP(err, bitRate = m_videoRecorder->VideoBitRateL());
+ if (err) {
+ if (err != KErrNotSupported)
+ setError(err, tr("Querying video bitrate failed."));
+ }
+ m_videoSettings.setBitRate(int(bitRate));
+
+ // EncodingMode
+ m_audioSettings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding);
+}
+
+void S60VideoCaptureSession::videoEncoderSettings(QVideoEncoderSettings &videoSettings)
+{
+ switch (m_captureState) {
+ // CVideoRecorderUtility, return requested settings
+ case ENotInitialized:
+ case EInitializing:
+ case EInitialized:
+ case EOpening:
+ case EOpenComplete:
+ case EPreparing:
+ break;
+
+ // Possible to query settings from CVideoRecorderUtility
+ case EPrepared:
+ case ERecording:
+ case EPaused:
+ queryVideoEncoderSettings();
+ break;
+
+ default:
+ videoSettings = QVideoEncoderSettings();
+ setError(KErrGeneral, tr("Unexpected video error."));
+ return;
+ }
+
+ videoSettings = m_videoSettings;
+}
+
+void S60VideoCaptureSession::audioEncoderSettings(QAudioEncoderSettings &audioSettings)
+{
+ switch (m_captureState) {
+ // CVideoRecorderUtility, return requested settings
+ case ENotInitialized:
+ case EInitializing:
+ case EInitialized:
+ case EOpening:
+ case EOpenComplete:
+ case EPreparing:
+ break;
+
+ // Possible to query settings from CVideoRecorderUtility
+ case EPrepared:
+ case ERecording:
+ case EPaused:
+ queryAudioEncoderSettings();
+ break;
+
+ default:
+ audioSettings = QAudioEncoderSettings();
+ setError(KErrGeneral, tr("Unexpected video error."));
+ return;
+ }
+
+ audioSettings = m_audioSettings;
+}
+
+void S60VideoCaptureSession::validateRequestedCodecs()
+{
+ if (!m_audioCodecList.contains(m_audioSettings.codec())) {
+ m_audioSettings.setCodec(KMimeTypeDefaultAudioCodec);
+ setError(KErrNotSupported, tr("Currently selected audio codec is not supported by the platform."));
+ }
+ if (!m_videoCodecList.contains(m_videoSettings.codec())) {
+ m_videoSettings.setCodec(KMimeTypeDefaultVideoCodec);
+ setError(KErrNotSupported, tr("Currently selected video codec is not supported by the platform."));
+ }
+}
+
+void S60VideoCaptureSession::setVideoCaptureQuality(const QtMultimediaKit::EncodingQuality quality,
+ const VideoQualityDefinition mode)
+{
+ // Sensible presets
+ switch (mode) {
+ case ENoVideoQuality:
+ // Do nothing
+ break;
+ case EOnlyVideoQuality:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setResolution(QSize(128,96));
+ m_videoSettings.setFrameRate(10);
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(128000);
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setResolution(QSize(352,288));
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(384000);
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ if (m_cameraEngine && m_cameraEngine->CurrentCameraIndex() == 0)
+ m_videoSettings.setResolution(QSize(640,480)); // Primary camera
+ else
+ m_videoSettings.setResolution(QSize(352,288)); // Other cameras
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(2000000);
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ case EVideoQualityAndResolution:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setFrameRate(10);
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(128000);
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(384000);
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ m_videoSettings.setFrameRate(15);
+ m_videoSettings.setBitRate(2000000);
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ case EVideoQualityAndFrameRate:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setResolution(QSize(128,96));
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ m_videoSettings.setBitRate(128000);
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setResolution(QSize(352,288));
+ m_videoSettings.setBitRate(384000);
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ if (m_cameraEngine && m_cameraEngine->CurrentCameraIndex() == 0)
+ m_videoSettings.setResolution(QSize(640,480)); // Primary camera
+ else
+ m_videoSettings.setResolution(QSize(352,288)); // Other cameras
+ m_videoSettings.setBitRate(2000000);
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ case EVideoQualityAndBitRate:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setResolution(QSize(128,96));
+ m_videoSettings.setFrameRate(10);
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ m_videoSettings.setFrameRate(15);
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ m_videoSettings.setFrameRate(15);
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setResolution(QSize(352,288));
+ m_videoSettings.setFrameRate(15);
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ if (m_cameraEngine && m_cameraEngine->CurrentCameraIndex() == 0)
+ m_videoSettings.setResolution(QSize(640,480)); // Primary camera
+ else
+ m_videoSettings.setResolution(QSize(352,288)); // Other cameras
+ m_videoSettings.setFrameRate(15);
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ case EVideoQualityAndResolutionAndBitRate:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setFrameRate(10);
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setFrameRate(15);
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setFrameRate(15);
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setFrameRate(15);
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ m_videoSettings.setFrameRate(15);
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ case EVideoQualityAndResolutionAndFrameRate:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setBitRate(64000);
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setBitRate(128000);
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setBitRate(384000);
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ m_videoSettings.setBitRate(2000000);
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ case EVideoQualityAndFrameRateAndBitRate:
+ if (quality == QtMultimediaKit::VeryLowQuality) {
+ m_videoSettings.setResolution(QSize(128,96));
+ } else if (quality == QtMultimediaKit::LowQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ } else if (quality == QtMultimediaKit::NormalQuality) {
+ m_videoSettings.setResolution(QSize(176,144));
+ } else if (quality == QtMultimediaKit::HighQuality) {
+ m_videoSettings.setResolution(QSize(352,288));
+ } else if (quality == QtMultimediaKit::VeryHighQuality) {
+ if (m_cameraEngine && m_cameraEngine->CurrentCameraIndex() == 0)
+ m_videoSettings.setResolution(QSize(640,480)); // Primary camera
+ else
+ m_videoSettings.setResolution(QSize(352,288)); // Other cameras
+ } else {
+ m_videoSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported video quality."));
+ return;
+ }
+ break;
+ }
+
+ m_videoSettings.setQuality(quality);
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::setAudioCaptureQuality(const QtMultimediaKit::EncodingQuality quality,
+ const AudioQualityDefinition mode)
+{
+ // Based on audio quality definition mode, select proper SampleRate and BitRate
+ switch (mode) {
+ case EOnlyAudioQuality:
+ switch (quality) {
+ case QtMultimediaKit::VeryLowQuality:
+ m_audioSettings.setBitRate(16000);
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::LowQuality:
+ m_audioSettings.setBitRate(16000);
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::NormalQuality:
+ m_audioSettings.setBitRate(32000);
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::HighQuality:
+ m_audioSettings.setBitRate(64000);
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::VeryHighQuality:
+ m_audioSettings.setBitRate(64000);
+ m_audioSettings.setSampleRate(-1);
+ break;
+ default:
+ m_audioSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported audio quality."));
+ return;
+ }
+ break;
+ case EAudioQualityAndBitRate:
+ switch (quality) {
+ case QtMultimediaKit::VeryLowQuality:
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::LowQuality:
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::NormalQuality:
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::HighQuality:
+ m_audioSettings.setSampleRate(-1);
+ break;
+ case QtMultimediaKit::VeryHighQuality:
+ m_audioSettings.setSampleRate(-1);
+ break;
+ default:
+ m_audioSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported audio quality."));
+ return;
+ }
+ break;
+ case EAudioQualityAndSampleRate:
+ switch (quality) {
+ case QtMultimediaKit::VeryLowQuality:
+ m_audioSettings.setBitRate(16000);
+ break;
+ case QtMultimediaKit::LowQuality:
+ m_audioSettings.setBitRate(16000);
+ break;
+ case QtMultimediaKit::NormalQuality:
+ m_audioSettings.setBitRate(32000);
+ break;
+ case QtMultimediaKit::HighQuality:
+ m_audioSettings.setBitRate(64000);
+ break;
+ case QtMultimediaKit::VeryHighQuality:
+ m_audioSettings.setBitRate(64000);
+ break;
+ default:
+ m_audioSettings.setQuality(QtMultimediaKit::NormalQuality);
+ setError(KErrNotSupported, tr("Unsupported audio quality."));
+ return;
+ }
+ break;
+ case ENoAudioQuality:
+ // No actions required, just set quality parameter
+ break;
+
+ default:
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+
+ m_audioSettings.setQuality(quality);
+ m_uncommittedSettings = true;
+}
+
+int S60VideoCaptureSession::initializeVideoRecording()
+{
+ if (m_error)
+ return m_error;
+
+ TRAPD(symbianError, doInitializeVideoRecorderL());
+ setError(symbianError, tr("Failed to initialize video recorder."));
+
+ return symbianError;
+}
+
+void S60VideoCaptureSession::releaseVideoRecording()
+{
+ if (m_captureState >= ERecording) {
+ m_videoRecorder->Stop();
+ if (m_durationTimer->isActive())
+ m_durationTimer->stop();
+ }
+
+ if (m_captureState >= EInitialized)
+ m_videoRecorder->Close();
+
+ // Reset state
+ m_captureState = ENotInitialized;
+
+ // Reset error to be able to recover from error
+ m_error = KErrNone;
+
+ // Reset flags
+ m_openWhenReady = false;
+ m_prepareAfterOpenComplete = false;
+ m_startAfterPrepareComplete = false;
+ m_uncommittedSettings = false;
+ m_commitSettingsWhenReady = false;
+}
+
+void S60VideoCaptureSession::startRecording()
+{
+ if (m_error) {
+ setError(m_error, tr("Unexpected recording error."));
+ return;
+ }
+
+ switch (m_captureState) {
+ case ENotInitialized:
+ case EInitializing:
+ case EInitialized:
+ if (m_captureState == EInitialized)
+ setOutputLocation(m_requestedSink);
+ m_startAfterPrepareComplete = true;
+ return;
+
+ case EOpening:
+ case EPreparing:
+ // Execute FileOpenL() and Prepare() asap and then start recording
+ m_startAfterPrepareComplete = true;
+ return;
+ case EOpenComplete:
+ case EPrepared:
+ if (m_captureState == EPrepared && !m_uncommittedSettings)
+ break;
+
+ // Revert state internally, since logically applying settings means going
+ // from OpenComplete ==> Preparing ==> Prepared.
+ m_captureState = EOpenComplete;
+ m_startAfterPrepareComplete = true;
+
+ // Commit settings and prepare with them
+ applyAllSettings();
+ return;
+ case ERecording:
+ // Discard
+ return;
+ case EPaused:
+ // Continue
+ break;
+
+ default:
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+
+ // State should now be either Prepared with no Uncommitted Settings or Paused
+
+ if (!m_cameraStarted) {
+ m_startAfterPrepareComplete = true;
+ return;
+ }
+
+ if (m_cameraEngine && !m_cameraEngine->IsCameraReady()) {
+ setError(KErrNotReady, tr("Camera not ready to start video recording."));
+ return;
+ }
+
+ if (m_videoRecorder) {
+ m_videoRecorder->Record();
+ m_captureState = ERecording;
+ emit stateChanged(m_captureState);
+ m_durationTimer->start();
+
+ // Reset all flags
+ m_openWhenReady = false;
+ m_prepareAfterOpenComplete = false;
+ m_startAfterPrepareComplete = false;
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+void S60VideoCaptureSession::pauseRecording()
+{
+ if (m_captureState == ERecording) {
+ if (m_videoRecorder) {
+ TRAPD(err, m_videoRecorder->PauseL());
+ setError(err, tr("Pausing video recording failed."));
+ m_captureState = EPaused;
+ emit stateChanged(m_captureState);
+ if (m_durationTimer->isActive())
+ m_durationTimer->stop();
+
+ // Notify last duration
+ TRAP(err, m_position = m_videoRecorder->DurationL().Int64() / 1000);
+ setError(err, tr("Cannot retrieve video position."));
+ emit positionChanged(m_position);
+ }
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+}
+
+void S60VideoCaptureSession::stopRecording(const bool reInitialize)
+{
+ if (m_captureState != ERecording && m_captureState != EPaused)
+ return; // Ignore
+
+ if (m_videoRecorder) {
+ m_videoRecorder->Stop();
+ m_videoRecorder->Close();
+
+ // Notify muting is disabled if needed
+ if (m_muted)
+ emit mutedChanged(false);
+
+ m_captureState = ENotInitialized;
+ emit stateChanged(m_captureState);
+
+ if (m_durationTimer->isActive())
+ m_durationTimer->stop();
+
+ // VideoRecording will be re-initialized unless explicitly requested not to do so
+ if (reInitialize) {
+ if (m_cameraEngine->IsCameraReady())
+ initializeVideoRecording();
+ }
+ }
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+}
+
+void S60VideoCaptureSession::updateVideoCaptureContainers()
+{
+ TRAPD(err, doUpdateVideoCaptureContainersL());
+ setError(err, tr("Failed to gather video container information."));
+}
+
+void S60VideoCaptureSession::doUpdateVideoCaptureContainersL()
+{
+ // Clear container data structure
+ QList<TInt> mapControllers = m_videoControllerMap.keys();
+ for (int i = 0; i < mapControllers.size(); ++i) {
+ foreach(VideoFormatData data, m_videoControllerMap[mapControllers[i]]){
+ data.supportedMimeTypes.clear();
+ }
+ m_videoControllerMap[mapControllers[i]].clear();
+ }
+ m_videoControllerMap.clear();
+
+ // Resolve the supported video format and retrieve a list of controllers
+ CMMFControllerPluginSelectionParameters* pluginParameters =
+ CMMFControllerPluginSelectionParameters::NewLC();
+ CMMFFormatSelectionParameters* format =
+ CMMFFormatSelectionParameters::NewLC();
+
+ // Set the play and record format selection parameters to be blank.
+ // Format support is only retrieved if requested.
+ pluginParameters->SetRequiredPlayFormatSupportL(*format);
+ pluginParameters->SetRequiredRecordFormatSupportL(*format);
+
+ // Set the media IDs
+ RArray<TUid> mediaIds;
+ CleanupClosePushL(mediaIds);
+
+ User::LeaveIfError(mediaIds.Append(KUidMediaTypeVideo));
+
+ // Get plugins that support at least video
+ pluginParameters->SetMediaIdsL(mediaIds,
+ CMMFPluginSelectionParameters::EAllowOtherMediaIds);
+ pluginParameters->SetPreferredSupplierL(KNullDesC,
+ CMMFPluginSelectionParameters::EPreferredSupplierPluginsFirstInList);
+
+ // Array to hold all the controllers support the match data
+ RMMFControllerImplInfoArray controllers;
+ CleanupResetAndDestroyPushL(controllers);
+ pluginParameters->ListImplementationsL(controllers);
+
+ // Find the first controller with at least one record format available
+ for (TInt index = 0; index < controllers.Count(); ++index) {
+
+ m_videoControllerMap.insert(controllers[index]->Uid().iUid, QHash<TInt,VideoFormatData>());
+
+ const RMMFFormatImplInfoArray& recordFormats = controllers[index]->RecordFormats();
+ for (TInt j = 0; j < recordFormats.Count(); ++j) {
+ VideoFormatData formatData;
+ formatData.description = QString::fromUtf16(
+ recordFormats[j]->DisplayName().Ptr(),
+ recordFormats[j]->DisplayName().Length());
+
+ const CDesC8Array& mimeTypes = recordFormats[j]->SupportedMimeTypes();
+ for (int k = 0; k < mimeTypes.Count(); ++k) {
+ TPtrC8 mimeType = mimeTypes[k];
+ QString type = QString::fromUtf8((char *)mimeType.Ptr(),
+ mimeType.Length());
+ formatData.supportedMimeTypes.append(type);
+ }
+
+ m_videoControllerMap[controllers[index]->Uid().iUid].insert(recordFormats[j]->Uid().iUid, formatData);
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&controllers);
+ CleanupStack::PopAndDestroy(&mediaIds);
+ CleanupStack::PopAndDestroy(format);
+ CleanupStack::PopAndDestroy(pluginParameters);
+}
+
+/*
+ * This goes through the available controllers and selects proper one based
+ * on the format. Function sets proper UIDs to be used for controller and format.
+ */
+void S60VideoCaptureSession::selectController(const QString &format,
+ TUid &controllerUid,
+ TUid &formatUid)
+{
+ QList<TInt> controllers = m_videoControllerMap.keys();
+ QList<TInt> formats;
+
+ for (int i = 0; i < controllers.count(); ++i) {
+ formats = m_videoControllerMap[controllers[i]].keys();
+ for (int j = 0; j < formats.count(); ++j) {
+ VideoFormatData formatData = m_videoControllerMap[controllers[i]][formats[j]];
+ if (formatData.supportedMimeTypes.contains(format, Qt::CaseInsensitive)) {
+ controllerUid = TUid::Uid(controllers[i]);
+ formatUid = TUid::Uid(formats[j]);
+ }
+ }
+ }
+}
+
+QStringList S60VideoCaptureSession::supportedVideoCaptureCodecs()
+{
+ return m_videoCodecList;
+}
+
+QStringList S60VideoCaptureSession::supportedAudioCaptureCodecs()
+{
+ QStringList keys = m_audioCodecList.keys();
+ keys.sort();
+ return keys;
+}
+
+QList<int> S60VideoCaptureSession::supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous)
+{
+ QList<int> rates;
+
+ TRAPD(err, rates = doGetSupportedSampleRatesL(settings, continuous));
+ if (err != KErrNotSupported)
+ setError(err, tr("Failed to query information of supported sample rates."));
+
+ return rates;
+}
+
+QList<int> S60VideoCaptureSession::doGetSupportedSampleRatesL(const QAudioEncoderSettings &settings, bool *continuous)
+{
+ QList<int> sampleRates;
+
+ if (m_captureState < EOpenComplete)
+ return sampleRates;
+
+#ifndef S60_31_PLATFORM
+ RArray<TUint> supportedSampleRates;
+ CleanupClosePushL(supportedSampleRates);
+
+ if (!settings.codec().isEmpty()) {
+
+ TFourCC currentAudioCodec;
+ currentAudioCodec = m_videoRecorder->AudioTypeL();
+
+ TFourCC requestedAudioCodec;
+ if (qstrcmp(settings.codec().toLocal8Bit().constData(), "audio/aac") == 0)
+ requestedAudioCodec.Set(KMMFFourCCCodeAAC);
+ else if (qstrcmp(settings.codec().toLocal8Bit().constData(), "audio/amr") == 0)
+ requestedAudioCodec.Set(KMMFFourCCCodeAMR);
+ m_videoRecorder->SetAudioTypeL(requestedAudioCodec);
+
+ m_videoRecorder->GetSupportedAudioSampleRatesL(supportedSampleRates);
+
+ m_videoRecorder->SetAudioTypeL(currentAudioCodec);
+ }
+ else
+ m_videoRecorder->GetSupportedAudioSampleRatesL(supportedSampleRates);
+
+ for (int i = 0; i < supportedSampleRates.Count(); ++i)
+ sampleRates.append(int(supportedSampleRates[i]));
+
+ CleanupStack::PopAndDestroy(); // RArray<TUint> supportedSampleRates
+#else // S60 3.1 Platform
+ Q_UNUSED(settings);
+#endif // S60_31_PLATFORM
+
+ if (continuous)
+ *continuous = false;
+
+ return sampleRates;
+}
+
+void S60VideoCaptureSession::setAudioSampleRate(const int sampleRate)
+{
+ if (sampleRate != -1)
+ m_audioSettings.setSampleRate(sampleRate);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::setAudioBitRate(const int bitRate)
+{
+ if (bitRate != -1)
+ m_audioSettings.setBitRate(bitRate);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::setAudioChannelCount(const int channelCount)
+{
+ if (channelCount != -1)
+ m_audioSettings.setChannelCount(channelCount);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::setVideoCaptureCodec(const QString &codecName)
+{
+ if (codecName == m_videoSettings.codec())
+ return;
+
+ if (codecName.isEmpty())
+ m_videoSettings.setCodec(KMimeTypeDefaultVideoCodec); // Use default
+ else
+ m_videoSettings.setCodec(codecName);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::setAudioCaptureCodec(const QString &codecName)
+{
+ if (codecName == m_audioSettings.codec())
+ return;
+
+ if (codecName.isEmpty()) {
+ m_audioSettings.setCodec(KMimeTypeDefaultAudioCodec); // Use default
+ } else {
+ // If information of supported codecs is already available check that
+ // given codec is supported
+ if (m_captureState >= EOpenComplete) {
+ if (m_audioCodecList.contains(codecName)) {
+ m_audioSettings.setCodec(codecName);
+ m_uncommittedSettings = true;
+ } else {
+ setError(KErrNotSupported, tr("Requested audio codec is not supported"));
+ }
+ } else {
+ m_audioSettings.setCodec(codecName);
+ m_uncommittedSettings = true;
+ }
+ }
+}
+
+QString S60VideoCaptureSession::videoCaptureCodecDescription(const QString &codecName)
+{
+ QString codecDescription;
+ if (codecName.contains("video/H263-2000", Qt::CaseInsensitive))
+ codecDescription.append("H.263 Video Codec");
+ else if (codecName.contains("video/mp4v-es", Qt::CaseInsensitive))
+ codecDescription.append("MPEG-4 Part 2 Video Codec");
+ else if (codecName.contains("video/H264", Qt::CaseInsensitive))
+ codecDescription.append("H.264 AVC (MPEG-4 Part 10) Video Codec");
+ else
+ codecDescription.append("Video Codec");
+
+ return codecDescription;
+}
+
+void S60VideoCaptureSession::doSetCodecsL()
+{
+ // Determine Profile and Level for the video codec if needed
+ // (MimeType/Profile-level-id contains "profile" if profile/level info is available)
+ if (!m_videoSettings.codec().contains(QString("profile"), Qt::CaseInsensitive))
+ m_videoSettings.setCodec(determineProfileAndLevel());
+
+ if (m_videoRecorder) {
+ TPtrC16 str(reinterpret_cast<const TUint16*>(m_videoSettings.codec().utf16()));
+ HBufC8* videoCodec(0);
+ videoCodec = CnvUtfConverter::ConvertFromUnicodeToUtf8L(str);
+ CleanupStack::PushL(videoCodec);
+
+ TFourCC audioCodec = m_audioCodecList[m_audioSettings.codec()];
+
+ TInt vErr = KErrNone;
+ TInt aErr = KErrNone;
+ TRAP(vErr, m_videoRecorder->SetVideoTypeL(*videoCodec));
+ TRAP(aErr, m_videoRecorder->SetAudioTypeL(audioCodec));
+
+ User::LeaveIfError(vErr);
+ User::LeaveIfError(aErr);
+
+ CleanupStack::PopAndDestroy(videoCodec);
+ }
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+}
+
+QString S60VideoCaptureSession::determineProfileAndLevel()
+{
+ QString determinedMimeType = m_videoSettings.codec();
+
+ // H.263
+ if (determinedMimeType.contains(QString("video/H263-2000"), Qt::CaseInsensitive)) {
+ if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (176*144)) {
+ if (m_videoSettings.frameRate() > 15.0)
+ determinedMimeType.append("; profile=0; level=20");
+ else
+ determinedMimeType.append("; profile=0; level=40");
+ } else {
+ if (m_videoSettings.bitRate() > 64000)
+ determinedMimeType.append("; profile=0; level=45");
+ else
+ determinedMimeType.append("; profile=0; level=10");
+ }
+
+ // MPEG-4
+ } else if (determinedMimeType.contains(QString("video/mp4v-es"), Qt::CaseInsensitive)) {
+ if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (720*480)) {
+ determinedMimeType.append("; profile-level-id=6");
+ } else if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (640*480)) {
+ determinedMimeType.append("; profile-level-id=5");
+ } else if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (352*288)) {
+ determinedMimeType.append("; profile-level-id=4");
+ } else if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (176*144)) {
+ if (m_videoSettings.frameRate() > 15.0)
+ determinedMimeType.append("; profile-level-id=3");
+ else
+ determinedMimeType.append("; profile-level-id=2");
+ } else {
+ if (m_videoSettings.bitRate() > 64000)
+ determinedMimeType.append("; profile-level-id=9");
+ else
+ determinedMimeType.append("; profile-level-id=1");
+ }
+
+ // H.264
+ } else if (determinedMimeType.contains(QString("video/H264"), Qt::CaseInsensitive)) {
+ if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (640*480)) {
+ determinedMimeType.append("; profile-level-id=42801F");
+ } else if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (352*288)) {
+ determinedMimeType.append("; profile-level-id=42801E");
+ } else if ((m_videoSettings.resolution().width() * m_videoSettings.resolution().height()) > (176*144)) {
+ if (m_videoSettings.frameRate() > 15.0)
+ determinedMimeType.append("; profile-level-id=428015");
+ else
+ determinedMimeType.append("; profile-level-id=42800C");
+ } else {
+ determinedMimeType.append("; profile-level-id=42900B");
+ }
+ }
+
+ return determinedMimeType;
+}
+
+void S60VideoCaptureSession::setBitrate(const int bitrate)
+{
+ m_videoSettings.setBitRate(bitrate);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::doSetBitrate(const int &bitrate)
+{
+ if (bitrate != -1) {
+ if (m_videoRecorder) {
+ TRAPD(err, m_videoRecorder->SetVideoBitRateL(bitrate));
+ if (err) {
+ if (err == KErrNotSupported || err == KErrArgument) {
+ setError(KErrNotSupported, tr("Requested video bitrate is not supported."));
+ m_videoSettings.setBitRate(64000); // Reset
+ } else {
+ setError(err, tr("Failed to set video bitrate."));
+ }
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+ }
+}
+
+void S60VideoCaptureSession::setVideoResolution(const QSize &resolution)
+{
+ m_videoSettings.setResolution(resolution);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::doSetVideoResolution(const QSize &resolution)
+{
+ TSize size((TInt)resolution.width(), (TInt)resolution.height());
+
+ // Make sure resolution is not too big if main camera is not used
+ if (m_cameraEngine->CurrentCameraIndex() != 0) {
+ TCameraInfo *info = m_cameraEngine->CameraInfo();
+ if (info) {
+ TInt videoResolutionCount = info->iNumVideoFrameSizesSupported;
+ TSize maxCameraVideoResolution = TSize(0,0);
+ CCamera *camera = m_cameraEngine->Camera();
+ if (camera) {
+ for (TInt i = 0; i < videoResolutionCount; ++i) {
+ TSize checkedResolution;
+ // Use YUV video max frame size in the check (Through
+ // CVideoRecorderUtility/DevVideoRecord it is possible to
+ // query only encoder maximums)
+ camera->EnumerateVideoFrameSizes(checkedResolution, i, CCamera::EFormatYUV420Planar);
+ if ((checkedResolution.iWidth * checkedResolution.iHeight) >
+ (maxCameraVideoResolution.iWidth * maxCameraVideoResolution.iHeight))
+ maxCameraVideoResolution = checkedResolution;
+ }
+ if ((maxCameraVideoResolution.iWidth * maxCameraVideoResolution.iHeight) <
+ (size.iWidth * size.iHeight)) {
+ size = maxCameraVideoResolution;
+ setError(KErrNotSupported, tr("Requested resolution is not supported for this camera."));
+ }
+ }
+ else
+ setError(KErrGeneral, tr("Could not query supported video resolutions."));
+ }else
+ setError(KErrGeneral, tr("Could not query supported video resolutions."));
+ }
+
+ if (resolution.width() != -1 && resolution.height() != -1) {
+ if (m_videoRecorder) {
+ TRAPD(err, m_videoRecorder->SetVideoFrameSizeL((TSize)size));
+ if (err == KErrNotSupported || err == KErrArgument) {
+ setError(KErrNotSupported, tr("Requested video resolution is not supported."));
+ TSize fallBack(640,480);
+ TRAPD(err, m_videoRecorder->SetVideoFrameSizeL(fallBack));
+ if (err == KErrNone) {
+ m_videoSettings.setResolution(QSize(fallBack.iWidth,fallBack.iHeight));
+ } else {
+ fallBack = TSize(176,144);
+ TRAPD(err, m_videoRecorder->SetVideoFrameSizeL(fallBack));
+ if (err == KErrNone)
+ m_videoSettings.setResolution(QSize(fallBack.iWidth,fallBack.iHeight));
+ }
+ } else {
+ setError(err, tr("Failed to set video resolution."));
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+ }
+}
+
+void S60VideoCaptureSession::setFrameRate(qreal rate)
+{
+ m_videoSettings.setFrameRate(rate);
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::doSetFrameRate(qreal rate)
+{
+ if (rate != 0) {
+ if (m_videoRecorder) {
+ bool continuous = false;
+ QList<qreal> list = supportedVideoFrameRates(&continuous);
+ qreal maxRate = 0.0;
+ foreach (qreal fRate, list)
+ if (fRate > maxRate)
+ maxRate = fRate;
+ if (maxRate >= rate && rate > 0) {
+ TRAPD(err, m_videoRecorder->SetVideoFrameRateL((TReal32)rate));
+ if (err == KErrNotSupported) {
+ setError(KErrNotSupported, tr("Requested framerate is not supported."));
+ TReal32 fallBack = 15.0;
+ TRAPD(err, m_videoRecorder->SetVideoFrameRateL(fallBack));
+ if (err == KErrNone)
+ m_videoSettings.setFrameRate((qreal)fallBack);
+ } else {
+ if (err == KErrArgument) {
+ setError(KErrNotSupported, tr("Requested framerate is not supported."));
+ m_videoSettings.setFrameRate(15.0); // Reset
+ } else {
+ setError(err, tr("Failed to set video framerate."));
+ }
+ }
+ } else {
+ setError(KErrNotSupported, tr("Requested framerate is not supported."));
+ m_videoSettings.setFrameRate(15.0); // Reset
+ }
+ } else {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ }
+ }
+}
+
+void S60VideoCaptureSession::setVideoEncodingMode(const QtMultimediaKit::EncodingMode mode)
+{
+ // This has no effect as it has no support in Symbian
+
+ if (mode == QtMultimediaKit::ConstantQualityEncoding) {
+ m_videoSettings.setEncodingMode(mode);
+ return;
+ }
+
+ setError(KErrNotSupported, tr("Requested video encoding mode is not supported"));
+
+ // m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::setAudioEncodingMode(const QtMultimediaKit::EncodingMode mode)
+{
+ // This has no effect as it has no support in Symbian
+
+ if (mode == QtMultimediaKit::ConstantQualityEncoding) {
+ m_audioSettings.setEncodingMode(mode);
+ return;
+ }
+
+ setError(KErrNotSupported, tr("Requested audio encoding mode is not supported"));
+
+ // m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::initializeVideoCaptureSettings()
+{
+ // Check if user has already requested some settings
+ if (m_captureSettingsSet)
+ return;
+
+ QSize resolution(-1, -1);
+ qreal frameRate(0);
+ int bitRate(-1);
+
+ if (m_cameraEngine) {
+
+ if (m_videoRecorder && m_captureState >= EInitialized) {
+
+ // Resolution
+ QList<QSize> resos = supportedVideoResolutions(0);
+ foreach (QSize reso, resos) {
+ if ((reso.width() * reso.height()) > (resolution.width() * resolution.height()))
+ resolution = reso;
+ }
+
+ // Needed to query supported framerates for this codec/resolution pair
+ m_videoSettings.setCodec(KMimeTypeDefaultVideoCodec);
+ m_videoSettings.setResolution(resolution);
+
+ // FrameRate
+ QList<qreal> fRates = supportedVideoFrameRates(m_videoSettings, 0);
+ foreach (qreal rate, fRates) {
+ if (rate > frameRate)
+ frameRate = rate;
+ }
+
+ // BitRate
+#ifdef SYMBIAN_3_PLATFORM
+ if (m_cameraEngine->CurrentCameraIndex() == 0)
+ bitRate = KBiR_H264_PLID_42801F // 14Mbps
+ else
+ bitRate = KBiR_H264_PLID_428016 // 4Mbps
+#else // Other platforms
+ if (m_cameraEngine->CurrentCameraIndex() == 0)
+ bitRate = KBiR_MPEG4_PLID_4 // 2/4Mbps
+ else
+ bitRate = KBiR_MPEG4_PLID_3 // 384kbps
+#endif // SYMBIAN_3_PLATFORM
+
+ } else {
+#ifdef SYMBIAN_3_PLATFORM
+ if (m_cameraEngine->CurrentCameraIndex() == 0) {
+ // Primary camera
+ resolution = KResH264_PLID_42801F; // 1280x720
+ frameRate = KFrR_H264_PLID_42801F; // 30fps
+ bitRate = KBiR_H264_PLID_42801F; // 14Mbps
+ } else {
+ // Other cameras
+ resolution = KResH264_PLID_42801E; // 640x480
+ frameRate = KFrR_H264_PLID_428014; // 30fps
+ bitRate = KBiR_H264_PLID_428016; // 4Mbps
+ }
+#else // Other platforms
+ if (m_cameraEngine->CurrentCameraIndex() == 0) {
+ // Primary camera
+ resolution = KResMPEG4_PLID_4; // 640x480
+ frameRate = KFrR_MPEG4_PLID_4; // 15/30fps
+ bitRate = KBiR_MPEG4_PLID_4; // 2/4Mbps
+ } else {
+ // Other cameras
+ resolution = KResMPEG4_PLID_3; // 352x288
+ frameRate = KFrR_MPEG4; // 15fps
+ bitRate = KBiR_MPEG4_PLID_3; // 384kbps
+ }
+#endif // SYMBIAN_3_PLATFORM
+ }
+ } else {
+#ifdef SYMBIAN_3_PLATFORM
+ resolution = KResH264_PLID_42801F;
+ frameRate = KFrR_H264_PLID_42801F;
+ bitRate = KBiR_H264_PLID_42801F;
+#else // Pre-Symbian3 Platforms
+ resolution = KResMPEG4_PLID_4;
+ frameRate = KFrR_MPEG4_PLID_4;
+ bitRate = KBiR_MPEG4_PLID_4;
+#endif // SYMBIAN_3_PLATFORM
+ }
+
+ // Set specified settings (Resolution, FrameRate and BitRate)
+ m_videoSettings.setResolution(resolution);
+ m_videoSettings.setFrameRate(frameRate);
+ m_videoSettings.setBitRate(bitRate);
+
+ // Video Settings: Codec, EncodingMode and Quality
+ m_videoSettings.setCodec(KMimeTypeDefaultVideoCodec);
+ m_videoSettings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding);
+ m_videoSettings.setQuality(QtMultimediaKit::VeryHighQuality);
+
+ // Audio Settings
+ m_audioSettings.setCodec(KMimeTypeDefaultAudioCodec);
+ m_audioSettings.setBitRate(KDefaultBitRate);
+ m_audioSettings.setSampleRate(KDefaultSampleRate);
+ m_audioSettings.setChannelCount(KDefaultChannelCount);
+ m_audioSettings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding);
+ m_audioSettings.setQuality(QtMultimediaKit::VeryHighQuality);
+}
+
+QSize S60VideoCaptureSession::pixelAspectRatio()
+{
+#ifndef S60_31_PLATFORM
+ TVideoAspectRatio par;
+ TRAPD(err, m_videoRecorder->GetPixelAspectRatioL(par));
+ if (err)
+ setError(err, tr("Failed to query current pixel aspect ratio."));
+ return QSize(par.iNumerator, par.iDenominator);
+#else // S60_31_PLATFORM
+ return QSize();
+#endif // !S60_31_PLATFORM
+}
+
+void S60VideoCaptureSession::setPixelAspectRatio(const QSize par)
+{
+#ifndef S60_31_PLATFORM
+
+ const TVideoAspectRatio videoPar(par.width(), par.height());
+ TRAPD(err, m_videoRecorder->SetPixelAspectRatioL(videoPar));
+ if (err)
+ setError(err, tr("Failed to set pixel aspect ratio."));
+#else // S60_31_PLATFORM
+ Q_UNUSED(par);
+#endif // !S60_31_PLATFORM
+
+ m_uncommittedSettings = true;
+}
+
+int S60VideoCaptureSession::gain()
+{
+ TInt gain = 0;
+ TRAPD(err, gain = m_videoRecorder->GainL());
+ if (err)
+ setError(err, tr("Failed to query video gain."));
+ return (int)gain;
+}
+
+void S60VideoCaptureSession::setGain(const int gain)
+{
+ TRAPD(err, m_videoRecorder->SetGainL(gain));
+ if (err)
+ setError(err, tr("Failed to set video gain."));
+
+ m_uncommittedSettings = true;
+}
+
+int S60VideoCaptureSession::maxClipSizeInBytes() const
+{
+ return m_maxClipSize;
+}
+
+void S60VideoCaptureSession::setMaxClipSizeInBytes(const int size)
+{
+ TRAPD(err, m_videoRecorder->SetMaxClipSizeL(size));
+ if (err) {
+ setError(err, tr("Failed to set maximum video size."));
+ } else
+ m_maxClipSize = size;
+
+ m_uncommittedSettings = true;
+}
+
+void S60VideoCaptureSession::MvruoOpenComplete(TInt aError)
+{
+ if (m_error)
+ return;
+
+ if (aError == KErrNone && m_videoRecorder) {
+ if (m_captureState == EInitializing) {
+ // Dummy file open completed, initialize settings
+ TRAPD(err, doPopulateAudioCodecsL());
+ setError(err, tr("Failed to gather information of supported audio codecs."));
+
+ // For DevVideoRecord codecs are populated during
+ // doPopulateVideoCodecsDataL()
+ TRAP(err, doPopulateVideoCodecsL());
+ setError(err, tr("Failed to gather information of supported video codecs."));
+#ifndef S60_DEVVIDEO_RECORDING_SUPPORTED
+ // Max parameters needed to be populated, if not using DevVideoRecord
+ // Otherwise done already in constructor
+ doPopulateMaxVideoParameters();
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+
+ m_captureState = EInitialized;
+ emit stateChanged(m_captureState);
+
+ // Initialize settings if not already done
+ initializeVideoCaptureSettings();
+
+ // Validate codecs to be used
+ validateRequestedCodecs();
+
+ if (m_openWhenReady || m_prepareAfterOpenComplete || m_startAfterPrepareComplete) {
+ setOutputLocation(m_requestedSink);
+ m_openWhenReady = false; // Reset
+ }
+ if (m_commitSettingsWhenReady) {
+ applyAllSettings();
+ m_commitSettingsWhenReady = false; // Reset
+ }
+ return;
+
+ } else if (m_captureState == EOpening) {
+ // Actual file open completed
+ m_captureState = EOpenComplete;
+ emit stateChanged(m_captureState);
+
+ // Prepare right away
+ if (m_startAfterPrepareComplete || m_prepareAfterOpenComplete) {
+ m_prepareAfterOpenComplete = false; // Reset
+
+ // Commit settings and prepare with them
+ applyAllSettings();
+ }
+ return;
+
+ } else if (m_captureState == ENotInitialized) {
+ // Resources released while waiting OpenFileL to complete
+ m_videoRecorder->Close();
+ return;
+
+ } else {
+ setError(KErrGeneral, tr("Unexpected camera error."));
+ return;
+ }
+ }
+
+ m_videoRecorder->Close();
+ if (aError == KErrNotFound || aError == KErrNotSupported || aError == KErrArgument)
+ setError(KErrGeneral, tr("Requested video container or controller is not supported."));
+ else
+ setError(KErrGeneral, tr("Failure during video recorder initialization."));
+}
+
+void S60VideoCaptureSession::MvruoPrepareComplete(TInt aError)
+{
+ if (m_error)
+ return;
+
+ if(aError == KErrNone) {
+ if (m_captureState == ENotInitialized) {
+ // Resources released while waiting for Prepare to complete
+ m_videoRecorder->Close();
+ return;
+ }
+
+ emit captureSizeChanged(m_videoSettings.resolution());
+
+ m_captureState = EPrepared;
+ emit stateChanged(EPrepared);
+
+ // Check the actual active settings
+ queryAudioEncoderSettings();
+ queryVideoEncoderSettings();
+
+ if (m_openWhenReady == true) {
+ setOutputLocation(m_requestedSink);
+ m_openWhenReady = false; // Reset
+ }
+
+ if (m_commitSettingsWhenReady) {
+ applyAllSettings();
+ m_commitSettingsWhenReady = false; // Reset
+ }
+
+ if (m_startAfterPrepareComplete) {
+ m_startAfterPrepareComplete = false; // Reset
+ startRecording();
+ }
+ } else {
+ m_videoRecorder->Close();
+ if (aError == KErrNotSupported)
+ setError(aError, tr("Camera preparation for video recording failed because of unsupported setting."));
+ else
+ setError(aError, tr("Failed to prepare camera for video recording."));
+ }
+}
+
+void S60VideoCaptureSession::MvruoRecordComplete(TInt aError)
+{
+ if (!m_videoRecorder) {
+ setError(KErrNotReady, tr("Unexpected camera error."));
+ return;
+ }
+
+ if((aError == KErrNone || aError == KErrCompletion)) {
+ m_videoRecorder->Stop();
+
+ // Reset state
+ if (m_captureState != ENotInitialized) {
+ m_captureState = ENotInitialized;
+ emit stateChanged(m_captureState);
+ if (m_durationTimer->isActive())
+ m_durationTimer->stop();
+ }
+
+ if (m_cameraEngine->IsCameraReady())
+ initializeVideoRecording();
+ }
+ m_videoRecorder->Close();
+
+ // Notify muting is disabled if needed
+ if (m_muted)
+ emit mutedChanged(false);
+
+ if (aError == KErrDiskFull)
+ setError(aError, tr("Not enough space for video, recording stopped."));
+ else
+ setError(aError, tr("Recording stopped due to unexpected error."));
+}
+
+void S60VideoCaptureSession::MvruoEvent(const TMMFEvent& aEvent)
+{
+ Q_UNUSED(aEvent);
+}
+
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+void S60VideoCaptureSession::MdvroReturnPicture(TVideoPicture *aPicture)
+{
+ // Not used
+ Q_UNUSED(aPicture);
+}
+
+void S60VideoCaptureSession::MdvroSupplementalInfoSent()
+{
+ // Not used
+}
+
+void S60VideoCaptureSession::MdvroNewBuffers()
+{
+ // Not used
+}
+
+void S60VideoCaptureSession::MdvroFatalError(TInt aError)
+{
+ setError(aError, tr("Unexpected camera error."));
+}
+
+void S60VideoCaptureSession::MdvroInitializeComplete(TInt aError)
+{
+ // Not used
+ Q_UNUSED(aError);
+}
+
+void S60VideoCaptureSession::MdvroStreamEnd()
+{
+ // Not used
+}
+
+/*
+ * This populates video codec information (supported codecs, resolutions,
+ * framerates, etc.) using DevVideoRecord API.
+ */
+void S60VideoCaptureSession::doPopulateVideoCodecsDataL()
+{
+ RArray<TUid> encoders;
+ CleanupClosePushL(encoders);
+
+ CMMFDevVideoRecord *mDevVideoRecord = CMMFDevVideoRecord::NewL(*this);
+ CleanupStack::PushL(mDevVideoRecord);
+
+ // Retrieve list of all encoders provided by the platform
+ mDevVideoRecord->GetEncoderListL(encoders);
+
+ for (int i = 0; i < encoders.Count(); ++i ) {
+
+ CVideoEncoderInfo *encoderInfo = mDevVideoRecord->VideoEncoderInfoLC(encoders[i]);
+
+ // Discard encoders that are not HW accelerated and do not support direct capture
+ if (encoderInfo->Accelerated() == false || encoderInfo->SupportsDirectCapture() == false) {
+ CleanupStack::Check(encoderInfo);
+ CleanupStack::PopAndDestroy(encoderInfo);
+ continue;
+ }
+
+ m_videoParametersForEncoder.append(MaxResolutionRatesAndTypes());
+ int newIndex = m_videoParametersForEncoder.count() - 1;
+
+ m_videoParametersForEncoder[newIndex].bitRate = (int)encoderInfo->MaxBitrate();
+
+ // Get supported MIME Types
+ const RPointerArray<CCompressedVideoFormat> &videoFormats = encoderInfo->SupportedOutputFormats();
+ for(int x = 0; x < videoFormats.Count(); ++x) {
+ QString codecMimeType = QString::fromUtf8((char *)videoFormats[x]->MimeType().Ptr(),videoFormats[x]->MimeType().Length());
+
+ m_videoParametersForEncoder[newIndex].mimeTypes.append(codecMimeType);
+ }
+
+ // Get supported maximum Resolution/Framerate pairs
+ const RArray<TPictureRateAndSize> &ratesAndSizes = encoderInfo->MaxPictureRates();
+ SupportedFrameRatePictureSize data;
+ for(int j = 0; j < ratesAndSizes.Count(); ++j) {
+ data.frameRate = ratesAndSizes[j].iPictureRate;
+ data.frameSize = QSize(ratesAndSizes[j].iPictureSize.iWidth, ratesAndSizes[j].iPictureSize.iHeight);
+
+ // Save data to the hash
+ m_videoParametersForEncoder[newIndex].frameRatePictureSizePair.append(data);
+ }
+
+ CleanupStack::Check(encoderInfo);
+ CleanupStack::PopAndDestroy(encoderInfo);
+ }
+
+ CleanupStack::Check(mDevVideoRecord);
+ CleanupStack::PopAndDestroy(mDevVideoRecord);
+ CleanupStack::PopAndDestroy(); // RArray<TUid> encoders
+}
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+
+QStringList S60VideoCaptureSession::supportedVideoContainers()
+{
+ QStringList containers;
+
+ QList<TInt> controllers = m_videoControllerMap.keys();
+ for (int i = 0; i < controllers.count(); ++i) {
+ foreach (VideoFormatData formatData, m_videoControllerMap[controllers[i]]) {
+ for (int j = 0; j < formatData.supportedMimeTypes.count(); ++j) {
+ if (containers.contains(formatData.supportedMimeTypes[j], Qt::CaseInsensitive) == false)
+ containers.append(formatData.supportedMimeTypes[j]);
+ }
+ }
+ }
+
+ return containers;
+}
+
+bool S60VideoCaptureSession::isSupportedVideoContainer(const QString &containerName)
+{
+ return supportedVideoContainers().contains(containerName, Qt::CaseInsensitive);
+}
+
+QString S60VideoCaptureSession::videoContainer() const
+{
+ return m_container;
+}
+
+void S60VideoCaptureSession::setVideoContainer(const QString &containerName)
+{
+ if (containerName == m_requestedContainer)
+ return;
+
+ if (containerName.isEmpty()) {
+ m_requestedContainer = KMimeTypeDefaultContainer; // Use default
+ } else {
+ if (supportedVideoContainers().contains(containerName)) {
+ m_requestedContainer = containerName;
+ } else {
+ setError(KErrNotSupported, tr("Requested video container is not supported."));
+ m_requestedContainer = KMimeTypeDefaultContainer; // Reset to default
+ }
+ }
+
+ m_uncommittedSettings = true;
+}
+
+QString S60VideoCaptureSession::videoContainerDescription(const QString &containerName)
+{
+ QList<TInt> formats;
+ QList<TInt> encoders = m_videoControllerMap.keys();
+ for (int i = 0; i < encoders.count(); ++i) {
+ formats = m_videoControllerMap[encoders[i]].keys();
+ for (int j = 0; j < formats.count(); ++j) {
+ if (m_videoControllerMap[encoders[i]][formats[j]].supportedMimeTypes.contains(containerName, Qt::CaseInsensitive))
+ return m_videoControllerMap[encoders[i]][formats[j]].description;
+ }
+ }
+
+ return QString();
+}
+
+void S60VideoCaptureSession::cameraStatusChanged(QCamera::Status status)
+{
+ if (status == QCamera::ActiveStatus) {
+ m_cameraStarted = true;
+
+ // Continue preparation or start recording if previously requested
+ if (m_captureState == EInitialized
+ && (m_openWhenReady || m_prepareAfterOpenComplete || m_startAfterPrepareComplete)) {
+ setOutputLocation(m_requestedSink);
+ m_openWhenReady = false; // Reset
+ } else if ((m_captureState == EOpenComplete || m_captureState == EPrepared)
+ && (m_prepareAfterOpenComplete || m_startAfterPrepareComplete)) {
+ startRecording();
+ m_prepareAfterOpenComplete = false; // Reset
+ }
+
+ } else if (status == QCamera::UnloadedStatus) {
+ m_cameraStarted = false;
+ releaseVideoRecording();
+ } else {
+ m_cameraStarted = false;
+ }
+}
+
+void S60VideoCaptureSession::durationTimerTriggered()
+{
+ // Update position only if recording is ongoing
+ if ((m_captureState == ERecording) && m_videoRecorder) {
+ // Signal will be automatically emitted of position changes
+ TRAPD(err, m_position = m_videoRecorder->DurationL().Int64() / 1000);
+ setError(err, tr("Cannot retrieve video position."));
+
+ emit positionChanged(m_position);
+ }
+}
+
+void S60VideoCaptureSession::doPopulateAudioCodecsL()
+{
+ if (m_captureState == EInitializing) {
+ m_audioCodecList.clear();
+
+ RArray<TFourCC> audioTypes;
+ CleanupClosePushL(audioTypes);
+
+ if (m_videoRecorder)
+ m_videoRecorder->GetSupportedAudioTypesL(audioTypes);
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+
+ for (TInt i = 0; i < audioTypes.Count(); i++) {
+ TUint32 codec = audioTypes[i].FourCC();
+
+ if (codec == KMMFFourCCCodeAMR)
+ m_audioCodecList.insert(QString("audio/amr"), KMMFFourCCCodeAMR);
+ if (codec == KMMFFourCCCodeAAC)
+ m_audioCodecList.insert(QString("audio/aac"), KMMFFourCCCodeAAC);
+ }
+ CleanupStack::PopAndDestroy(&audioTypes);
+ }
+}
+
+void S60VideoCaptureSession::doPopulateVideoCodecsL()
+{
+ if (m_captureState == EInitializing) {
+ m_videoCodecList.clear();
+
+ CDesC8ArrayFlat* videoTypes = new (ELeave) CDesC8ArrayFlat(10);
+ CleanupStack::PushL(videoTypes);
+
+ if (m_videoRecorder)
+ m_videoRecorder->GetSupportedVideoTypesL(*videoTypes);
+ else
+ setError(KErrNotReady, tr("Unexpected camera error."));
+
+ for (TInt i = 0; i < videoTypes->Count(); i++) {
+ TPtrC8 videoType = videoTypes->MdcaPoint(i);
+ QString codecMimeType = QString::fromUtf8((char *)videoType.Ptr(), videoType.Length());
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+ for (int j = 0; j < m_videoParametersForEncoder.size(); ++j) {
+ if (m_videoParametersForEncoder[j].mimeTypes.contains(codecMimeType, Qt::CaseInsensitive)) {
+ m_videoCodecList << codecMimeType;
+ break;
+ }
+ }
+#else // CVideoRecorderUtility
+ m_videoCodecList << codecMimeType;
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+ }
+ CleanupStack::PopAndDestroy(videoTypes);
+ }
+}
+
+#ifndef S60_DEVVIDEO_RECORDING_SUPPORTED
+/*
+ * Maximum resolution, framerate and bitrate can not be queried via MMF or
+ * ECam, but needs to be set according to the definitions of the video
+ * standard in question. In video standards, the values often depend on each
+ * other, but the below function defines constant maximums.
+ */
+void S60VideoCaptureSession::doPopulateMaxVideoParameters()
+{
+ m_videoParametersForEncoder.append(MaxResolutionRatesAndTypes()); // For H.263
+ m_videoParametersForEncoder.append(MaxResolutionRatesAndTypes()); // For MPEG-4
+ m_videoParametersForEncoder.append(MaxResolutionRatesAndTypes()); // For H.264
+
+ for (int i = 0; i < m_videoCodecList.count(); ++i) {
+
+ // Use all lower case for comparisons
+ QString codec = m_videoCodecList[i].toLower();
+
+ if (codec.contains("video/h263-2000", Qt::CaseInsensitive)) {
+ // H.263
+ if (codec == "video/h263-2000" ||
+ codec == "video/h263-2000; profile=0" ||
+ codec == "video/h263-2000; profile=0; level=10" ||
+ codec == "video/h263-2000; profile=3") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(176,144)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 64000)
+ m_videoParametersForEncoder[0].bitRate = 64000;
+ continue;
+ } else if (codec == "video/h263-2000; profile=0; level=20") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 128000)
+ m_videoParametersForEncoder[0].bitRate = 128000;
+ continue;
+ } else if (codec == "video/h263-2000; profile=0; level=30") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 384000)
+ m_videoParametersForEncoder[0].bitRate = 384000;
+ continue;
+ } else if (codec == "video/h263-2000; profile=0; level=40") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 2048000)
+ m_videoParametersForEncoder[0].bitRate = 2048000;
+ continue;
+ } else if (codec == "video/h263-2000; profile=0; level=45") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(176,144)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 128000)
+ m_videoParametersForEncoder[0].bitRate = 128000;
+ continue;
+ } else if (codec == "video/h263-2000; profile=0; level=50") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 4096000)
+ m_videoParametersForEncoder[0].bitRate = 4096000;
+ continue;
+ }
+
+ } else if (codec.contains("video/mp4v-es", Qt::CaseInsensitive)) {
+ // Mpeg-4
+ if (codec == "video/mp4v-es" ||
+ codec == "video/mp4v-es; profile-level-id=1" ||
+ codec == "video/mp4v-es; profile-level-id=8") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(176,144)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 64000)
+ m_videoParametersForEncoder[0].bitRate = 64000;
+ continue;
+ } else if (codec == "video/mp4v-es; profile-level-id=2" ||
+ codec == "video/mp4v-es; profile-level-id=9") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 128000)
+ m_videoParametersForEncoder[0].bitRate = 128000;
+ continue;
+ } else if (codec == "video/mp4v-es; profile-level-id=3") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 384000)
+ m_videoParametersForEncoder[0].bitRate = 384000;
+ continue;
+ } else if (codec == "video/mp4v-es; profile-level-id=4") {
+#if (defined(S60_31_PLATFORM) | defined(S60_32_PLATFORM))
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(640,480)));
+#else // S60 5.0 and later platforms
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(640,480)));
+#endif
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 4000000)
+ m_videoParametersForEncoder[0].bitRate = 4000000;
+ continue;
+ } else if (codec == "video/mp4v-es; profile-level-id=5") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(25.0, QSize(720,576)));
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(720,480)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 8000000)
+ m_videoParametersForEncoder[0].bitRate = 8000000;
+ continue;
+ } else if (codec == "video/mp4v-es; profile-level-id=6") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(1280,720)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 12000000)
+ m_videoParametersForEncoder[0].bitRate = 12000000;
+ continue;
+ }
+
+ } else if (codec.contains("video/h264", Qt::CaseInsensitive)) {
+ // H.264
+ if (codec == "video/h264" ||
+ codec == "video/h264; profile-level-id=42800a") {
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(176,144)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 64000)
+ m_videoParametersForEncoder[0].bitRate = 64000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=42900b") { // BP, L1b
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(176,144)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 128000)
+ m_videoParametersForEncoder[0].bitRate = 128000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=42800b") { // BP, L1.1
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(7.5, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 192000)
+ m_videoParametersForEncoder[0].bitRate = 192000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=42800c") { // BP, L1.2
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(15.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 384000)
+ m_videoParametersForEncoder[0].bitRate = 384000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=42800d") { // BP, L1.3
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 768000)
+ m_videoParametersForEncoder[0].bitRate = 768000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=428014") { // BP, L2
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 2000000)
+ m_videoParametersForEncoder[0].bitRate = 2000000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=428015") { // BP, L2.1
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(50.0, QSize(352,288)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 4000000)
+ m_videoParametersForEncoder[0].bitRate = 4000000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=428016") { // BP, L2.2
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(16.9, QSize(640,480)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 4000000)
+ m_videoParametersForEncoder[0].bitRate = 4000000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=42801e") { // BP, L3
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(33.8, QSize(640,480)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 10000000)
+ m_videoParametersForEncoder[0].bitRate = 10000000;
+ continue;
+ } else if (codec == "video/h264; profile-level-id=42801f") { // BP, L3.1
+ m_videoParametersForEncoder[0].frameRatePictureSizePair.append(SupportedFrameRatePictureSize(30.0, QSize(1280,720)));
+ m_videoParametersForEncoder[0].mimeTypes.append(codec);
+ if (m_videoParametersForEncoder[0].bitRate < 14000000)
+ m_videoParametersForEncoder[0].bitRate = 14000000;
+ continue;
+ }
+ }
+ }
+}
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+
+/*
+ * This function returns the maximum resolution defined by the video standards
+ * for different MIME Types.
+ */
+QSize S60VideoCaptureSession::maximumResolutionForMimeType(const QString &mimeType) const
+{
+ QSize maxSize(-1,-1);
+ // Use all lower case for comparisons
+ QString lowerMimeType = mimeType.toLower();
+
+ if (lowerMimeType == "video/h263-2000") {
+ maxSize = KResH263;
+ } else if (lowerMimeType == "video/h263-2000; profile=0") {
+ maxSize = KResH263_Profile0;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=10") {
+ maxSize = KResH263_Profile0_Level10;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=20") {
+ maxSize = KResH263_Profile0_Level20;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=30") {
+ maxSize = KResH263_Profile0_Level30;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=40") {
+ maxSize = KResH263_Profile0_Level40;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=45") {
+ maxSize = KResH263_Profile0_Level45;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=50") {
+ maxSize = KResH263_Profile0_Level50;
+ } else if (lowerMimeType == "video/h263-2000; profile=3") {
+ maxSize = KResH263_Profile3;
+ } else if (lowerMimeType == "video/mp4v-es") {
+ maxSize = KResMPEG4;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=1") {
+ maxSize = KResMPEG4_PLID_1;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=2") {
+ maxSize = KResMPEG4_PLID_2;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=3") {
+ maxSize = KResMPEG4_PLID_3;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=4") {
+ maxSize = KResMPEG4_PLID_4;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=5") {
+ maxSize = KResMPEG4_PLID_5;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=6") {
+ maxSize = KResMPEG4_PLID_6;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=8") {
+ maxSize = KResMPEG4_PLID_8;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=9") {
+ maxSize = KResMPEG4_PLID_9;
+ } else if (lowerMimeType == "video/h264") {
+ maxSize = KResH264;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800a" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400a" ||
+ lowerMimeType == "video/h264; profile-level-id=64400a") { // L1
+ maxSize = KResH264_PLID_42800A;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42900b" ||
+ lowerMimeType == "video/h264; profile-level-id=4d500b" ||
+ lowerMimeType == "video/h264; profile-level-id=644009") { // L1.b
+ maxSize = KResH264_PLID_42900B;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800b" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400b" ||
+ lowerMimeType == "video/h264; profile-level-id=64400b") { // L1.1
+ maxSize = KResH264_PLID_42800B;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800c" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400c" ||
+ lowerMimeType == "video/h264; profile-level-id=64400c") { // L1.2
+ maxSize = KResH264_PLID_42800C;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800d" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400d" ||
+ lowerMimeType == "video/h264; profile-level-id=64400d") { // L1.3
+ maxSize = KResH264_PLID_42800D;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428014" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4014" ||
+ lowerMimeType == "video/h264; profile-level-id=644014") { // L2
+ maxSize = KResH264_PLID_428014;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428015" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4015" ||
+ lowerMimeType == "video/h264; profile-level-id=644015") { // L2.1
+ maxSize = KResH264_PLID_428015;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428016" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4016" ||
+ lowerMimeType == "video/h264; profile-level-id=644016") { // L2.2
+ maxSize = KResH264_PLID_428016;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42801e" ||
+ lowerMimeType == "video/h264; profile-level-id=4d401e" ||
+ lowerMimeType == "video/h264; profile-level-id=64401e") { // L3
+ maxSize = KResH264_PLID_42801E;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42801f" ||
+ lowerMimeType == "video/h264; profile-level-id=4d401f" ||
+ lowerMimeType == "video/h264; profile-level-id=64401f") { // L3.1
+ maxSize = KResH264_PLID_42801F;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428020" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4020" ||
+ lowerMimeType == "video/h264; profile-level-id=644020") { // L3.2
+ maxSize = KResH264_PLID_428020;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428028" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4028" ||
+ lowerMimeType == "video/h264; profile-level-id=644028") { // L4
+ maxSize = KResH264_PLID_428028;
+ }
+
+ return maxSize;
+}
+
+/*
+ * This function returns the maximum framerate defined by the video standards
+ * for different MIME Types.
+ */
+
+qreal S60VideoCaptureSession::maximumFrameRateForMimeType(const QString &mimeType) const
+{
+ qreal maxRate(-1.0);
+ // Use all lower case for comparisons
+ QString lowerMimeType = mimeType.toLower();
+
+ if (lowerMimeType == "video/h263-2000") {
+ maxRate = KFrR_H263;
+ } else if (lowerMimeType == "video/h263-2000; profile=0") {
+ maxRate = KFrR_H263_Profile0;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=10") {
+ maxRate = KFrR_H263_Profile0_Level10;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=20") {
+ maxRate = KFrR_H263_Profile0_Level20;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=30") {
+ maxRate = KFrR_H263_Profile0_Level30;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=40") {
+ maxRate = KFrR_H263_Profile0_Level40;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=45") {
+ maxRate = KFrR_H263_Profile0_Level45;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=50") {
+ maxRate = KFrR_H263_Profile0_Level50;
+ } else if (lowerMimeType == "video/h263-2000; profile=3") {
+ maxRate = KFrR_H263_Profile3;
+ } else if (lowerMimeType == "video/mp4v-es") {
+ maxRate = KFrR_MPEG4;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=1") {
+ maxRate = KFrR_MPEG4_PLID_1;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=2") {
+ maxRate = KFrR_MPEG4_PLID_2;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=3") {
+ maxRate = KFrR_MPEG4_PLID_3;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=4") {
+ maxRate = KFrR_MPEG4_PLID_4;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=5") {
+ maxRate = KFrR_MPEG4_PLID_5;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=6") {
+ maxRate = KFrR_MPEG4_PLID_6;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=8") {
+ maxRate = KFrR_MPEG4_PLID_8;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=9") {
+ maxRate = KFrR_MPEG4_PLID_9;
+ } else if (lowerMimeType == "video/h264") {
+ maxRate = KFrR_H264;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800a" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400a" ||
+ lowerMimeType == "video/h264; profile-level-id=64400a") { // L1
+ maxRate = KFrR_H264_PLID_42800A;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42900b" ||
+ lowerMimeType == "video/h264; profile-level-id=4d500b" ||
+ lowerMimeType == "video/h264; profile-level-id=644009") { // L1.b
+ maxRate = KFrR_H264_PLID_42900B;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800b" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400b" ||
+ lowerMimeType == "video/h264; profile-level-id=64400b") { // L1.1
+ maxRate = KFrR_H264_PLID_42800B;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800c" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400c" ||
+ lowerMimeType == "video/h264; profile-level-id=64400c") { // L1.2
+ maxRate = KFrR_H264_PLID_42800C;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800d" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400d" ||
+ lowerMimeType == "video/h264; profile-level-id=64400d") { // L1.3
+ maxRate = KFrR_H264_PLID_42800D;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428014" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4014" ||
+ lowerMimeType == "video/h264; profile-level-id=644014") { // L2
+ maxRate = KFrR_H264_PLID_428014;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428015" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4015" ||
+ lowerMimeType == "video/h264; profile-level-id=644015") { // L2.1
+ maxRate = KFrR_H264_PLID_428015;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428016" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4016" ||
+ lowerMimeType == "video/h264; profile-level-id=644016") { // L2.2
+ maxRate = KFrR_H264_PLID_428016;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42801e" ||
+ lowerMimeType == "video/h264; profile-level-id=4d401e" ||
+ lowerMimeType == "video/h264; profile-level-id=64401e") { // L3
+ maxRate = KFrR_H264_PLID_42801E;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42801f" ||
+ lowerMimeType == "video/h264; profile-level-id=4d401f" ||
+ lowerMimeType == "video/h264; profile-level-id=64401f") { // L3.1
+ maxRate = KFrR_H264_PLID_42801F;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428020" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4020" ||
+ lowerMimeType == "video/h264; profile-level-id=644020") { // L3.2
+ maxRate = KFrR_H264_PLID_428020;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428028" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4028" ||
+ lowerMimeType == "video/h264; profile-level-id=644028") { // L4
+ maxRate = KFrR_H264_PLID_428028;
+ }
+
+ return maxRate;
+}
+
+/*
+ * This function returns the maximum bitrate defined by the video standards
+ * for different MIME Types.
+ */
+int S60VideoCaptureSession::maximumBitRateForMimeType(const QString &mimeType) const
+{
+ int maxRate(-1.0);
+ // Use all lower case for comparisons
+ QString lowerMimeType = mimeType.toLower();
+
+ if (lowerMimeType == "video/h263-2000") {
+ maxRate = KBiR_H263;
+ } else if (lowerMimeType == "video/h263-2000; profile=0") {
+ maxRate = KBiR_H263_Profile0;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=10") {
+ maxRate = KBiR_H263_Profile0_Level10;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=20") {
+ maxRate = KBiR_H263_Profile0_Level20;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=30") {
+ maxRate = KBiR_H263_Profile0_Level30;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=40") {
+ maxRate = KBiR_H263_Profile0_Level40;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=45") {
+ maxRate = KBiR_H263_Profile0_Level45;
+ } else if (lowerMimeType == "video/h263-2000; profile=0; level=50") {
+ maxRate = KBiR_H263_Profile0_Level50;
+ } else if (lowerMimeType == "video/h263-2000; profile=3") {
+ maxRate = KBiR_H263_Profile3;
+ } else if (lowerMimeType == "video/mp4v-es") {
+ maxRate = KBiR_MPEG4;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=1") {
+ maxRate = KBiR_MPEG4_PLID_1;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=2") {
+ maxRate = KBiR_MPEG4_PLID_2;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=3") {
+ maxRate = KBiR_MPEG4_PLID_3;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=4") {
+ maxRate = KBiR_MPEG4_PLID_4;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=5") {
+ maxRate = KBiR_MPEG4_PLID_5;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=6") {
+ maxRate = KBiR_MPEG4_PLID_6;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=8") {
+ maxRate = KBiR_MPEG4_PLID_8;
+ } else if (lowerMimeType == "video/mp4v-es; profile-level-id=9") {
+ maxRate = KBiR_MPEG4_PLID_9;
+ } else if (lowerMimeType == "video/h264") {
+ maxRate = KBiR_H264;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800a" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400a" ||
+ lowerMimeType == "video/h264; profile-level-id=64400a") { // L1
+ maxRate = KBiR_H264_PLID_42800A;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42900b" ||
+ lowerMimeType == "video/h264; profile-level-id=4d500b" ||
+ lowerMimeType == "video/h264; profile-level-id=644009") { // L1.b
+ maxRate = KBiR_H264_PLID_42900B;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800b" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400b" ||
+ lowerMimeType == "video/h264; profile-level-id=64400b") { // L1.1
+ maxRate = KBiR_H264_PLID_42800B;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800c" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400c" ||
+ lowerMimeType == "video/h264; profile-level-id=64400c") { // L1.2
+ maxRate = KBiR_H264_PLID_42800C;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42800d" ||
+ lowerMimeType == "video/h264; profile-level-id=4d400d" ||
+ lowerMimeType == "video/h264; profile-level-id=64400d") { // L1.3
+ maxRate = KBiR_H264_PLID_42800D;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428014" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4014" ||
+ lowerMimeType == "video/h264; profile-level-id=644014") { // L2
+ maxRate = KBiR_H264_PLID_428014;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428015" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4015" ||
+ lowerMimeType == "video/h264; profile-level-id=644015") { // L2.1
+ maxRate = KBiR_H264_PLID_428015;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428016" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4016" ||
+ lowerMimeType == "video/h264; profile-level-id=644016") { // L2.2
+ maxRate = KBiR_H264_PLID_428016;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42801e" ||
+ lowerMimeType == "video/h264; profile-level-id=4d401e" ||
+ lowerMimeType == "video/h264; profile-level-id=64401e") { // L3
+ maxRate = KBiR_H264_PLID_42801E;
+ } else if (lowerMimeType == "video/h264; profile-level-id=42801f" ||
+ lowerMimeType == "video/h264; profile-level-id=4d401f" ||
+ lowerMimeType == "video/h264; profile-level-id=64401f") { // L3.1
+ maxRate = KBiR_H264_PLID_42801F;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428020" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4020" ||
+ lowerMimeType == "video/h264; profile-level-id=644020") { // L3.2
+ maxRate = KBiR_H264_PLID_428020;
+ } else if (lowerMimeType == "video/h264; profile-level-id=428028" ||
+ lowerMimeType == "video/h264; profile-level-id=4d4028" ||
+ lowerMimeType == "video/h264; profile-level-id=644028") { // L4
+ maxRate = KBiR_H264_PLID_428028;
+ }
+
+ return maxRate;
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60videocapturesession.h b/src/plugins/symbian/ecam/s60videocapturesession.h
new file mode 100644
index 000000000..cfa101f57
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videocapturesession.h
@@ -0,0 +1,414 @@
+/****************************************************************************
+**
+** 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 S60VIDEOCAPTURESESSION_H
+#define S60VIDEOCAPTURESESSION_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qhash.h>
+
+#include <qmediaencodersettings.h>
+#include <qcamera.h>
+#include <qmediarecorder.h>
+
+#include "s60cameraengine.h"
+
+#include <e32base.h>
+#include <videorecorder.h> // CVideoRecorderUtility
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+#include <mmf/devvideo/devvideorecord.h>
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+
+QT_USE_NAMESPACE
+
+class QTimer;
+
+/*
+ * VideoSession is the main class handling all video recording related
+ * operations. It uses mainly CVideoRecorderUtility to do it's tasks, but if
+ * DevVideoRecord is available it is used to provide more detailed
+ * information of the supported video settings.
+ */
+class S60VideoCaptureSession : public QObject,
+ public MVideoRecorderUtilityObserver
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+ ,public MMMFDevVideoRecordObserver
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+{
+ Q_OBJECT
+ Q_ENUMS(Error)
+ Q_ENUMS(EcamErrors)
+ Q_ENUMS(TVideoCaptureState)
+
+public: // Enums
+
+ enum TVideoCaptureState
+ {
+ ENotInitialized = 0, // 0 - VideoRecording is not initialized, instance may or may not be created
+ EInitializing, // 1 - Initialization is ongoing
+ EInitialized, // 2 - VideoRecording is initialized, OpenFile is called with dummy file
+ EOpening, // 3 - OpenFile called with actual output location, waiting completion
+ EOpenComplete, // 4 - OpenFile completed with the actual output location
+ EPreparing, // 5 - Preparing VideoRecording to use set video settings
+ EPrepared, // 6 - VideoRecording is prepared with the set settings, ready to record
+ ERecording, // 7 - Video recording is ongoing
+ EPaused // 8 - Video recording has been started and paused
+ };
+
+ enum AudioQualityDefinition
+ {
+ ENoAudioQuality = 0, // 0 - Both BitRate and SampleRate settings available
+ EOnlyAudioQuality, // 1 - No BitRate or SampleRate settings available, use Quality to set them
+ EAudioQualityAndBitRate, // 2 - BitRate setting available, use Quality to set SampleRate
+ EAudioQualityAndSampleRate, // 3 - SampleRate setting available, use Quality to set BitRate
+ };
+
+ enum VideoQualityDefinition
+ {
+ ENoVideoQuality = 0, // 0 - All, Resolution, FrameRate and BitRate available
+ EOnlyVideoQuality, // 1 - None available, use Quality to set Resolution, FrameRate and BitRate
+ EVideoQualityAndResolution, // 2 - Only Resolution available, use Quality to set FrameRate and BitRate
+ EVideoQualityAndFrameRate, // 3 - Only FrameRate available, use Quality to set Resolution and BitRate
+ EVideoQualityAndBitRate, // 4 - Only BitRate available, use Quality to set Resolution and FrameRate
+ EVideoQualityAndResolutionAndBitRate, // 5 - No FrameRate available, use Quality to set it
+ EVideoQualityAndResolutionAndFrameRate, // 6 - No BitRate available, use Quality to set it
+ EVideoQualityAndFrameRateAndBitRate // 7 - No Resolution available, use Quality to set it
+ };
+
+public: // Constructor & Destructor
+
+ S60VideoCaptureSession(QObject *parent = 0);
+ ~S60VideoCaptureSession();
+
+public: // MVideoRecorderUtilityObserver
+
+ void MvruoOpenComplete(TInt aError);
+ void MvruoPrepareComplete(TInt aError);
+ void MvruoRecordComplete(TInt aError);
+ void MvruoEvent(const TMMFEvent& aEvent);
+
+#ifdef S60_DEVVIDEO_RECORDING_SUPPORTED
+public: // MMMFDevVideoRecordObserver
+ void MdvroReturnPicture(TVideoPicture *aPicture);
+ void MdvroSupplementalInfoSent();
+ void MdvroNewBuffers();
+ void MdvroFatalError(TInt aError);
+ void MdvroInitializeComplete(TInt aError);
+ void MdvroStreamEnd();
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+
+public: // Methods
+
+ void setError(const TInt error, const QString &description);
+ void setCameraHandle(CCameraEngine* cameraHandle);
+ void notifySettingsSet();
+
+ qint64 position();
+ TVideoCaptureState state() const;
+ bool isMuted() const;
+
+ // Controls
+ int initializeVideoRecording();
+ void releaseVideoRecording();
+ void applyAllSettings();
+
+ void startRecording();
+ void pauseRecording();
+ void stopRecording(const bool reInitialize = true);
+ void setMuted(const bool muted);
+
+ // Output Location
+ bool setOutputLocation(const QUrl &sink);
+ QUrl outputLocation() const;
+
+ // Resolution
+ void setVideoResolution(const QSize &resolution);
+ QList<QSize> supportedVideoResolutions(bool *continuous);
+ QList<QSize> supportedVideoResolutions(const QVideoEncoderSettings &settings, bool *continuous);
+
+ // Framerate
+ void setFrameRate(const qreal rate);
+ QList<qreal> supportedVideoFrameRates(bool *continuous);
+ QList<qreal> supportedVideoFrameRates(const QVideoEncoderSettings &settings, bool *continuous);
+
+ // Other Video Settings
+ void setBitrate(const int bitrate);
+ void setVideoEncodingMode(const QtMultimediaKit::EncodingMode mode);
+
+ // Video Codecs
+ void setVideoCaptureCodec(const QString &codecName);
+ QStringList supportedVideoCaptureCodecs();
+ QString videoCaptureCodecDescription(const QString &codecName);
+
+ // Audio Codecs
+ void setAudioCaptureCodec(const QString &codecName);
+ QStringList supportedAudioCaptureCodecs();
+
+ // Encoder Settings
+ void videoEncoderSettings(QVideoEncoderSettings &videoSettings);
+ void audioEncoderSettings(QAudioEncoderSettings &audioSettings);
+
+ // Quality
+ void setVideoCaptureQuality(const QtMultimediaKit::EncodingQuality quality,
+ const VideoQualityDefinition mode);
+ void setAudioCaptureQuality(const QtMultimediaKit::EncodingQuality quality,
+ const AudioQualityDefinition mode);
+
+ // Video Containers
+ QString videoContainer() const;
+ void setVideoContainer(const QString &containerName);
+ QStringList supportedVideoContainers();
+ bool isSupportedVideoContainer(const QString &containerName);
+ QString videoContainerDescription(const QString &containerName);
+
+ // Audio Settings
+ QList<int> supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous);
+ void setAudioSampleRate(const int sampleRate);
+ void setAudioBitRate(const int bitRate);
+ void setAudioChannelCount(const int channelCount);
+ void setAudioEncodingMode(const QtMultimediaKit::EncodingMode mode);
+
+ // Video Options
+ QSize pixelAspectRatio();
+ void setPixelAspectRatio(const QSize par);
+ int gain();
+ void setGain(const int gain);
+ int maxClipSizeInBytes() const;
+ void setMaxClipSizeInBytes(const int size);
+
+private: // Internal
+
+ QMediaRecorder::Error fromSymbianErrorToQtMultimediaError(int aError);
+
+ void initializeVideoCaptureSettings();
+ void doInitializeVideoRecorderL();
+ void commitVideoEncoderSettings();
+ void queryAudioEncoderSettings();
+ void queryVideoEncoderSettings();
+ void validateRequestedCodecs();
+ void resetSession(bool errorHandling = false);
+
+ void doSetCodecsL();
+ QString determineProfileAndLevel();
+ void doSetVideoResolution(const QSize &resolution);
+ void doSetFrameRate(qreal rate);
+ void doSetBitrate(const int &bitrate);
+
+ void updateVideoCaptureContainers();
+ void doUpdateVideoCaptureContainersL();
+ void selectController(const QString &format,
+ TUid &controllerUid,
+ TUid &formatUid);
+
+ void doPopulateVideoCodecsDataL();
+ void doPopulateVideoCodecsL();
+#ifndef S60_DEVVIDEO_RECORDING_SUPPORTED
+ void doPopulateMaxVideoParameters();
+#endif // S60_DEVVIDEO_RECORDING_SUPPORTED
+ void doPopulateAudioCodecsL();
+
+ QList<int> doGetSupportedSampleRatesL(const QAudioEncoderSettings &settings,
+ bool *continuous);
+ QSize maximumResolutionForMimeType(const QString &mimeType) const;
+ qreal maximumFrameRateForMimeType(const QString &mimeType) const;
+ int maximumBitRateForMimeType(const QString &mimeType) const;
+
+signals: // Notification Signals
+
+ void stateChanged(S60VideoCaptureSession::TVideoCaptureState);
+ void positionChanged(qint64);
+ void mutedChanged(bool);
+ void captureSizeChanged(const QSize&);
+ void error(int, const QString&);
+
+private slots: // Internal Slots
+
+ void cameraStatusChanged(QCamera::Status);
+ void durationTimerTriggered();
+
+private: // Structs
+
+ /*
+ * This structure holds the information of supported video mime types for
+ * the format and also description for it.
+ */
+ struct VideoFormatData {
+ QString description;
+ QStringList supportedMimeTypes;
+ };
+
+ /*
+ * This structure is used to define supported resolutions and framerate
+ * (depending on each other) for each supported encoder mime type (defining
+ * encoder, profile and level)
+ */
+ struct SupportedFrameRatePictureSize {
+ SupportedFrameRatePictureSize() {}
+ SupportedFrameRatePictureSize(qreal rate, QSize size):
+ frameRate(rate),
+ frameSize(size) {}
+ qreal frameRate;
+ QSize frameSize;
+ };
+
+ /*
+ * This structure defines supported resolution/framerate pairs and maximum
+ * bitrate for a single encodec device. It also the supported mime types
+ * (codec, profile and level) of the encoder device.
+ *
+ * Structure defines 2 contructors:
+ * - First with no attributes
+ * - Second, which will construct the sructure appending one
+ * resolution/framerate pair to the list of
+ * SupportedFrameRatePictureSizes and setting the given bitrate as
+ * maximum. This second constructor is for convenience.
+ *
+ * This struct is used in m_videoParametersForEncoder (QList).
+ *
+ * Here's a visualization of an example strcuture:
+ * STRUCT:
+ * |-- Resolution/FrameRate Pairs:
+ * | |- VGA / 30fps
+ * | |- 720p / 25fps
+ * | |- Etc.
+ * |
+ * |-- MimeTypes:
+ * | |- video/mp4v-es; profile-level-id=1
+ * | |- video/mp4v-es; profile-level-id=2
+ * | |- Etc.
+ * |
+ * |-- Max BitRate: 1Mbps
+ */
+ struct MaxResolutionRatesAndTypes {
+ MaxResolutionRatesAndTypes() {}
+ MaxResolutionRatesAndTypes(QSize size, qreal fRate, int bRate):
+ bitRate(bRate)
+ {
+ frameRatePictureSizePair.append(SupportedFrameRatePictureSize(fRate,size));
+ }
+ QList<SupportedFrameRatePictureSize> frameRatePictureSizePair;
+ QStringList mimeTypes;
+ int bitRate;
+ };
+
+private: // Data
+
+ CCameraEngine *m_cameraEngine;
+ CVideoRecorderUtility *m_videoRecorder;
+ QTimer *m_durationTimer;
+ qint64 m_position;
+ // Symbian ErrorCode
+ mutable int m_error;
+ // This defines whether Camera is in ActiveStatus or not
+ bool m_cameraStarted;
+ // Internal state of the video recorder
+ TVideoCaptureState m_captureState;
+ // Actual output file name/path
+ QUrl m_sink;
+ // Requested output file name/path, this may be different from m_sink if
+ // asynchronous operation was ongoing in the CVideoRecorderUtility when new
+ // outputLocation was set.
+ QUrl m_requestedSink;
+ // Requested videoSettings. The may not be active settings before those are
+ // committed (with commitVideoEncoderSettings())
+ QVideoEncoderSettings m_videoSettings;
+ // Requested audioSettings. The may not be active settings before those are
+ // committed (with commitVideoEncoderSettings())
+ QAudioEncoderSettings m_audioSettings;
+ // Tells whether settings should be initialized when changing the camera
+ bool m_captureSettingsSet;
+ // Active container
+ QString m_container;
+ // Requested container, this may be different from m_container if
+ // asynchronous operation was ongoing in the CVideoRecorderUtility when new
+ // container was set.
+ QString m_requestedContainer;
+ // Requested muted value. This may not be active value before settings are
+ // committed (with commitVideoEncoderSettings())
+ bool m_muted;
+ // Maximum ClipSize in Bytes
+ int m_maxClipSize;
+ // List of supported video codec mime types
+ QStringList m_videoCodecList;
+ // Hash of supported video codec mime types and corresponding FourCC codes
+ QHash<QString, TFourCC> m_audioCodecList;
+ // Map of video capture controllers information. It is populated during
+ // doUpdateVideoCaptureContainersL().
+ //
+ // Here's a visualization of an example strcuture:
+ // m_videoControllerMap(HASH):
+ // |
+ // |-- Controller 1 : HASH
+ // | |- Container 1 (UID) : FormatData
+ // | | |- Description
+ // | | |- List of supported MimeTypes
+ // | |- Container 2 (UID) : FormatData
+ // | | |- Description
+ // | | |- List of supported MimeTypes
+ // | |- Etc.
+ // |
+ // |-- Controller 2: HASH
+ // | |- Container 1 (UID) : FormatData
+ // | | |- Description
+ // | | |- List of supported MimeTypes
+ // | |- Etc.
+ //
+ QHash<TInt, QHash<TInt,VideoFormatData> > m_videoControllerMap;
+ // List of Encoder information. If DevVideoRecord is available info is
+ // gathered during doPopulateVideoCodecsDataL() for each encoder (hw
+ // accelerated and supporting camera input) found. If DevVideoRecord is not
+ // available, the info is set in doPopulateMaxVideoParameters() based on
+ // supported codec list received from CVideoRecorderUtility.
+ QList<MaxResolutionRatesAndTypes> m_videoParametersForEncoder;
+ // Set if OpenFileL should be executed when currently ongoing operation
+ // is completed.
+ bool m_openWhenReady;
+ // Set if video capture should be prepared after OpenFileL has completed
+ bool m_prepareAfterOpenComplete;
+ // Set if video capture should be started when Prepare has completed
+ bool m_startAfterPrepareComplete;
+ // Tells if settings have been set after last Prepare()
+ bool m_uncommittedSettings;
+ // Tells if settings need to be applied after ongoing operation has finished
+ bool m_commitSettingsWhenReady;
+};
+
+#endif // S60VIDEOCAPTURESESSION_H
diff --git a/src/plugins/symbian/ecam/s60videodevicecontrol.cpp b/src/plugins/symbian/ecam/s60videodevicecontrol.cpp
new file mode 100644
index 000000000..3d55d3110
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videodevicecontrol.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** 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 <QtCore/qstring.h>
+#include <QtGui/qicon.h>
+
+#include "s60videodevicecontrol.h"
+#include "s60cameracontrol.h"
+#include "s60cameraconstants.h"
+
+S60VideoDeviceControl::S60VideoDeviceControl(QObject *parent) :
+ QVideoDeviceControl(parent)
+{
+}
+
+S60VideoDeviceControl::S60VideoDeviceControl(S60CameraControl *control, QObject *parent) :
+ QVideoDeviceControl(parent),
+ m_selectedDevice(KDefaultCameraDevice)
+{
+ m_control = control;
+ connect(m_control, SIGNAL(devicesChanged()), this, SIGNAL(devicesChanged()));
+}
+
+S60VideoDeviceControl::~S60VideoDeviceControl()
+{
+}
+
+int S60VideoDeviceControl::deviceCount() const
+{
+ return S60CameraControl::deviceCount();
+}
+
+QString S60VideoDeviceControl::deviceName(int index) const
+{
+ return S60CameraControl::name(index);
+}
+
+QString S60VideoDeviceControl::deviceDescription(int index) const
+{
+ return S60CameraControl::description(index);
+}
+
+QIcon S60VideoDeviceControl::deviceIcon(int index) const
+{
+ Q_UNUSED(index);
+ return QIcon();
+}
+
+int S60VideoDeviceControl::defaultDevice() const
+{
+ return KDefaultCameraDevice;
+}
+
+int S60VideoDeviceControl::selectedDevice() const
+{
+ return m_selectedDevice;
+}
+
+void S60VideoDeviceControl::setSelectedDevice(int index)
+{
+ // Inform that we selected new device
+ if (m_selectedDevice != index) {
+ m_control->setSelectedDevice(index);
+ m_selectedDevice = index;
+ emit selectedDeviceChanged(m_selectedDevice);
+ emit selectedDeviceChanged(deviceName(m_selectedDevice));
+ }
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60videodevicecontrol.h b/src/plugins/symbian/ecam/s60videodevicecontrol.h
new file mode 100644
index 000000000..03249441a
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videodevicecontrol.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** 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 S60VIDEODEVICECONTROL_H
+#define S60VIDEODEVICECONTROL_H
+
+#include "qvideodevicecontrol.h"
+
+QT_USE_NAMESPACE
+
+class S60CameraControl;
+class QString;
+class QIcon;
+
+/*
+ * Control for providing information of the video device (r. camera) and to
+ * enable other camera device (e.g. secondary camera if one exists).
+ */
+class S60VideoDeviceControl : public QVideoDeviceControl
+{
+ Q_OBJECT
+
+public: // Constructors & Destructor
+
+ S60VideoDeviceControl(QObject *parent);
+ S60VideoDeviceControl(S60CameraControl *control, QObject *parent = 0);
+ virtual ~S60VideoDeviceControl();
+
+public: // QVideoDeviceControl
+
+ int deviceCount() const;
+
+ QString deviceName(int index) const;
+ QString deviceDescription(int index) const;
+ QIcon deviceIcon(int index) const;
+
+ int defaultDevice() const;
+ int selectedDevice() const;
+
+public slots: // QVideoDeviceControl
+
+ void setSelectedDevice(int index);
+
+/*
+Q_SIGNALS:
+void selectedDeviceChanged(int index);
+void selectedDeviceChanged(const QString &deviceName);
+void devicesChanged();
+*/
+
+private: // Data
+
+ S60CameraControl *m_control;
+ int m_selectedDevice;
+};
+
+#endif // S60VIDEODEVICECONTROL_H
diff --git a/src/plugins/symbian/ecam/s60videoencodercontrol.cpp b/src/plugins/symbian/ecam/s60videoencodercontrol.cpp
new file mode 100644
index 000000000..34b28e28e
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videoencodercontrol.cpp
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** 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 "s60videoencodercontrol.h"
+#include "s60videocapturesession.h"
+
+S60VideoEncoderControl::S60VideoEncoderControl(QObject *parent) :
+ QVideoEncoderControl(parent)
+{
+}
+
+S60VideoEncoderControl::S60VideoEncoderControl(S60VideoCaptureSession *session, QObject *parent) :
+ QVideoEncoderControl(parent)
+{
+ m_session = session;
+}
+
+S60VideoEncoderControl::~S60VideoEncoderControl()
+{
+}
+
+QStringList S60VideoEncoderControl::supportedVideoCodecs() const
+{
+ return m_session->supportedVideoCaptureCodecs();
+}
+
+QString S60VideoEncoderControl::videoCodecDescription(const QString &codecName) const
+{
+ return m_session->videoCaptureCodecDescription(codecName);
+}
+
+QList<qreal> S60VideoEncoderControl::supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const
+{
+ if (!settings.isNull())
+ return m_session->supportedVideoFrameRates(settings, continuous);
+ return m_session->supportedVideoFrameRates(continuous);
+}
+
+QList<QSize> S60VideoEncoderControl::supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous) const
+{
+ if (!settings.isNull())
+ return m_session->supportedVideoResolutions(settings, continuous);
+ return m_session->supportedVideoResolutions(continuous);
+}
+
+QStringList S60VideoEncoderControl::supportedEncodingOptions(const QString &codec) const
+{
+ // Possible settings: EncodingMode, Codec, Resolution, FrameRate, BitRate, Quality
+ // Possible (codec specific) options: PixelAspectRatio, Gain, MaxClipSizeInBytes
+
+ // Following options are valid for all codecs
+ Q_UNUSED(codec);
+
+ QStringList options;
+ options.append("pixelAspectRatio");
+ options.append("gain");
+ options.append("maxClipSizeInBytes");
+
+ return options;
+}
+
+QVariant S60VideoEncoderControl::encodingOption(const QString &codec, const QString &name) const
+{
+ Q_UNUSED(codec);
+
+ // Possible settings: EncodingMode, Codec, Resolution, FrameRate, BitRate, Quality
+ // Possible (codec specific) options: PixelAspectRatio, Gain, MaxClipSizeInBytes
+
+ QVariant returnValue;
+
+ if (qstrcmp(name.toLocal8Bit().constData(), "pixelAspectRatio") == 0)
+ returnValue.setValue(m_session->pixelAspectRatio());
+ else if (qstrcmp(name.toLocal8Bit().constData(), "gain") == 0)
+ returnValue.setValue((int)m_session->gain());
+ else if (qstrcmp(name.toLocal8Bit().constData(), "maxClipSizeInBytes") == 0)
+ returnValue.setValue(m_session->maxClipSizeInBytes());
+
+ return returnValue;
+}
+
+void S60VideoEncoderControl::setEncodingOption(
+ const QString &codec, const QString &name, const QVariant &value)
+{
+ // Set the codec first if not already set
+ m_session->setVideoCaptureCodec(codec);
+
+ if (qstrcmp(name.toLocal8Bit().constData(), "pixelAspectRatio") == 0)
+ m_session->setPixelAspectRatio(value.toSize());
+ else if (qstrcmp(name.toLocal8Bit().constData(), "gain") == 0)
+ m_session->setGain(value.toInt());
+ else if (qstrcmp(name.toLocal8Bit().constData(), "maxClipSizeInBytes") == 0)
+ m_session->setMaxClipSizeInBytes(value.toInt());
+ else
+ m_session->setError(KErrNotSupported, tr("Requested encoding option is not supported"));
+}
+
+QVideoEncoderSettings S60VideoEncoderControl::videoSettings() const
+{
+ QVideoEncoderSettings settings;
+ m_session->videoEncoderSettings(settings);
+
+ return settings;
+}
+
+void S60VideoEncoderControl::setVideoSettings(const QVideoEncoderSettings &settings)
+{
+ // Notify that settings have been implicitly set and there's no need to
+ // initialize them in case camera is changed
+ m_session->notifySettingsSet();
+
+ if (settings.codec().isEmpty()
+ || (settings.resolution() == QSize(-1,-1) && settings.frameRate() == 0 && settings.bitRate() == -1)) {
+ if (!settings.codec().isEmpty())
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EOnlyVideoQuality);
+ } else if (settings.resolution() != QSize(-1,-1) && settings.frameRate() == 0 && settings.bitRate() == -1) { // Only Resolution
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setVideoResolution(settings.resolution());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EVideoQualityAndResolution);
+
+ } else if (settings.resolution() == QSize(-1,-1) && settings.frameRate() != 0 && settings.bitRate() == -1) { // Only Framerate
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setFrameRate(settings.frameRate());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EVideoQualityAndFrameRate);
+
+ } else if (settings.resolution() == QSize(-1,-1) && settings.frameRate() == 0 && settings.bitRate() != -1) { // Only BitRate
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setBitrate(settings.bitRate());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EVideoQualityAndBitRate);
+
+ } else if (settings.resolution() != QSize(-1,-1) && settings.frameRate() != 0 && settings.bitRate() == -1) { // Resolution and FrameRate
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setVideoResolution(settings.resolution());
+ m_session->setFrameRate(settings.frameRate());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EVideoQualityAndResolutionAndFrameRate);
+
+ } else if (settings.resolution() != QSize(-1,-1) && settings.frameRate() == 0 && settings.bitRate() != -1) { // Resolution and BitRate
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setVideoResolution(settings.resolution());
+ m_session->setBitrate(settings.bitRate());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EVideoQualityAndResolutionAndBitRate);
+
+ } else if (settings.resolution() == QSize(-1,-1) && settings.frameRate() != 0 && settings.bitRate() != -1) { // FrameRate and BitRate
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setFrameRate(settings.frameRate());
+ m_session->setBitrate(settings.bitRate());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::EVideoQualityAndFrameRateAndBitRate);
+
+ } else { // All: Resolution, BitRate and FrameRate
+ m_session->setVideoCaptureCodec(settings.codec());
+ m_session->setVideoEncodingMode(settings.encodingMode());
+ m_session->setVideoResolution(settings.resolution());
+ m_session->setFrameRate(settings.frameRate());
+ m_session->setBitrate(settings.bitRate());
+ m_session->setVideoCaptureQuality(settings.quality(), S60VideoCaptureSession::ENoVideoQuality);
+ }
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60videoencodercontrol.h b/src/plugins/symbian/ecam/s60videoencodercontrol.h
new file mode 100644
index 000000000..4554d9291
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videoencodercontrol.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** 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 S60VIDEOENCODERCONTROL_H
+#define S60VIDEOENCODERCONTROL_H
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmap.h>
+
+#include "qvideoencodercontrol.h"
+
+QT_USE_NAMESPACE
+
+class S60VideoCaptureSession;
+
+/*
+ * Control for video settings when recording video using QMediaRecorder.
+ */
+class S60VideoEncoderControl : public QVideoEncoderControl
+{
+ Q_OBJECT
+
+public: // Contructors & Destructor
+
+ S60VideoEncoderControl(QObject *parent = 0);
+ S60VideoEncoderControl(S60VideoCaptureSession *session, QObject *parent = 0);
+ virtual ~S60VideoEncoderControl();
+
+public: // QVideoEncoderControl
+
+ // Resolution
+ QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous = 0) const;
+
+ // Framerate
+ QList<qreal> supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous = 0) const;
+
+ // Video Codec
+ QStringList supportedVideoCodecs() const;
+ QString videoCodecDescription(const QString &codecName) const;
+
+ // Video Settings
+ QVideoEncoderSettings videoSettings() const;
+ void setVideoSettings(const QVideoEncoderSettings &settings);
+
+ // Encoding Options
+ QStringList supportedEncodingOptions(const QString &codec) const;
+ QVariant encodingOption(const QString &codec, const QString &name) const;
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
+
+private: // Data
+
+ S60VideoCaptureSession* m_session;
+
+};
+
+#endif // S60VIDEOENCODERCONTROL_H
diff --git a/src/plugins/symbian/ecam/s60videorenderercontrol.cpp b/src/plugins/symbian/ecam/s60videorenderercontrol.cpp
new file mode 100644
index 000000000..8cc3546b5
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videorenderercontrol.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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 <qabstractvideosurface.h>
+
+#include "s60videorenderercontrol.h"
+
+S60VideoRendererControl::S60VideoRendererControl(QObject *parent) :
+ QVideoRendererControl(parent),
+ m_surface(0)
+{
+}
+
+S60VideoRendererControl::~S60VideoRendererControl()
+{
+ // Stop surface if still active
+ if (m_surface)
+ if (m_surface->isActive())
+ m_surface->stop();
+}
+
+QAbstractVideoSurface *S60VideoRendererControl::surface() const
+{
+ return m_surface;
+}
+
+void S60VideoRendererControl::setSurface(QAbstractVideoSurface *surface)
+{
+ if (surface == 0) {
+ // Stop current surface if needed
+ if (m_surface)
+ if (m_surface->isActive())
+ m_surface->stop();
+ }
+
+ m_surface = surface;
+ emit viewFinderSurfaceSet();
+}
+
+// End of file
diff --git a/src/plugins/symbian/ecam/s60videorenderercontrol.h b/src/plugins/symbian/ecam/s60videorenderercontrol.h
new file mode 100644
index 000000000..b35433f86
--- /dev/null
+++ b/src/plugins/symbian/ecam/s60videorenderercontrol.h
@@ -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 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 S60VIDEORENDERERCONTROL_H
+#define S60VIDEORENDERERCONTROL_H
+
+#include <qvideorenderercontrol.h>
+
+/*
+ * Control for QGraphicsVideoItem. Viewfinder frames are streamed to a surface
+ * which is drawn to the display by the Qt Graphics Vide Framework.
+ * VideoRendererControl uses only Bitmap Viewfinder.
+ */
+class S60VideoRendererControl : public QVideoRendererControl
+{
+ Q_OBJECT
+
+public: // Constructor & Destructor
+
+ S60VideoRendererControl(QObject *parent = 0);
+ virtual ~S60VideoRendererControl();
+
+public: // S60VideoRendererControl
+
+ QAbstractVideoSurface *surface() const;
+ void setSurface(QAbstractVideoSurface *surface);
+
+signals: // Internal Signals
+
+ void viewFinderSurfaceSet();
+
+private: // Data
+
+ QAbstractVideoSurface *m_surface;
+
+};
+
+#endif // S60VIDEORENDERERCONTROL_H
diff --git a/src/plugins/symbian/mmf/audiosource/audiosource_s60.pri b/src/plugins/symbian/mmf/audiosource/audiosource_s60.pri
new file mode 100644
index 000000000..7732600fa
--- /dev/null
+++ b/src/plugins/symbian/mmf/audiosource/audiosource_s60.pri
@@ -0,0 +1,31 @@
+INCLUDEPATH += $$PWD
+
+DEFINES += AUDIOSOURCEUSED
+
+symbian:LIBS += -lmediaclientaudio \
+ -lmmfcontrollerframework \
+ -lefsrv \
+ -lbafl \
+
+!contains(S60_VERSION, 3.1) {
+ contains(audiorouting_s60_enabled,yes) {
+ #We use audioinputrouting.lib for recording audio from different sources -lmediaclientaudioinputstream \ -lcone \
+ DEFINES += AUDIOINPUT_ROUTING
+ message("Audio Input Routing enabled onwards 3.2 SDK")
+ LIBS += -laudioinputrouting
+ }
+}
+
+HEADERS += $$PWD/s60audioencodercontrol.h \
+ $$PWD/s60audiomediarecordercontrol.h \
+ $$PWD/s60audioendpointselector.h \
+ $$PWD/s60audiocaptureservice.h \
+ $$PWD/s60audiocapturesession.h \
+ $$PWD/S60audiocontainercontrol.h
+
+SOURCES += $$PWD/s60audioencodercontrol.cpp \
+ $$PWD/s60audiomediarecordercontrol.cpp \
+ $$PWD/s60audioendpointselector.cpp \
+ $$PWD/s60audiocaptureservice.cpp \
+ $$PWD/s60audiocapturesession.cpp \
+ $$PWD/S60audiocontainercontrol.cpp
diff --git a/src/plugins/symbian/mmf/audiosource/s60audiocaptureservice.cpp b/src/plugins/symbian/mmf/audiosource/s60audiocaptureservice.cpp
new file mode 100644
index 000000000..742ac8f82
--- /dev/null
+++ b/src/plugins/symbian/mmf/audiosource/s60audiocaptureservice.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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$
+** 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 "DebugMacros.h"
+#include <QDebug>
+
+#include "s60audiocaptureservice.h"
+#include "s60audiocapturesession.h"
+#include "s60audioendpointselector.h"
+#include "s60audioencodercontrol.h"
+#include "s60audiomediarecordercontrol.h"
+#include "s60audiocontainercontrol.h"
+
+S60AudioCaptureService::S60AudioCaptureService(QObject *parent):
+ QMediaService(parent)
+{
+ DP0("S60AudioCaptureService::S60AudioCaptureService +++");
+
+ m_session = new S60AudioCaptureSession(this);
+ m_encoderControl = new S60AudioEncoderControl(m_session,this);
+ m_recorderControl = new S60AudioMediaRecorderControl(m_session,this);
+ m_endpointSelector = new S60AudioEndpointSelector(m_session,this);
+ m_containerControl = new S60AudioContainerControl(m_session, this);
+
+ DP0("S60AudioCaptureService::S60AudioCaptureService ---");
+}
+
+S60AudioCaptureService::~S60AudioCaptureService()
+{
+ DP0("S60AudioCaptureService::~S60AudioCaptureService +++");
+ DP0("S60AudioCaptureService::~S60AudioCaptureService ---");
+}
+
+QMediaControl *S60AudioCaptureService::requestControl(const char *name)
+{
+ DP0("S60AudioCaptureService::requestControl");
+
+ if (qstrcmp(name,QMediaRecorderControl_iid) == 0)
+ return m_recorderControl;
+
+ if (qstrcmp(name,QAudioEncoderControl_iid) == 0)
+ return m_encoderControl;
+
+ if (qstrcmp(name,QAudioEndpointSelector_iid) == 0)
+ return m_endpointSelector;
+
+ if (qstrcmp(name,QMediaContainerControl_iid) == 0)
+ return m_containerControl;
+
+ return 0;
+}
+
+void S60AudioCaptureService::releaseControl(QMediaControl *control)
+{
+ DP0("S60AudioCaptureService::releaseControl +++");
+
+ Q_UNUSED(control)
+
+ DP0("S60AudioCaptureService::releaseControl ---");
+}
diff --git a/src/plugins/symbian/mmf/audiosource/s60audiocaptureservice.h b/src/plugins/symbian/mmf/audiosource/s60audiocaptureservice.h
new file mode 100644
index 000000000..86d71a994
--- /dev/null
+++ b/src/plugins/symbian/mmf/audiosource/s60audiocaptureservice.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60AUDIOCAPTURESERVICE_H
+#define S60AUDIOCAPTURESERVICE_H
+
+#include <QtCore/qobject.h>
+
+#include <qmediaservice.h>
+
+QT_USE_NAMESPACE
+
+class S60AudioCaptureSession;
+class S60AudioEncoderControl;
+class S60AudioMediaRecorderControl;
+class S60AudioEndpointSelector;
+class S60AudioContainerControl;
+
+
+class S60AudioCaptureService : public QMediaService
+{
+ Q_OBJECT
+public:
+ S60AudioCaptureService(QObject *parent = 0);
+ ~S60AudioCaptureService();
+
+ QMediaControl *requestControl(const char *name);
+ void releaseControl(QMediaControl *control);
+private:
+ S60AudioCaptureSession *m_session;
+ S60AudioEncoderControl *m_encoderControl;
+ S60AudioEndpointSelector *m_endpointSelector;
+ S60AudioMediaRecorderControl *m_recorderControl;
+ S60AudioContainerControl *m_containerControl;
+};
+
+#endif // S60AUDIOCAPTURESERVICE_H
diff --git a/src/plugins/symbian/mmf/audiosource/s60audiocapturesession.cpp b/src/plugins/symbian/mmf/audiosource/s60audiocapturesession.cpp
new file mode 100644
index 000000000..79b6a53a0
--- /dev/null
+++ b/src/plugins/symbian/mmf/audiosource/s60audiocapturesession.cpp
@@ -0,0 +1,937 @@
+/****************************************************************************
+**
+** 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$
+** 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 "DebugMacros.h"
+
+#include "s60audiocapturesession.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qurl.h>
+#include <QDir>
+
+#include <mda/common/audio.h>
+#include <mda/common/resource.h>
+#include <mda/client/utility.h>
+#include <mdaaudiosampleeditor.h>
+#include <mmf/common/mmfcontrollerpluginresolver.h>
+#include <mmf/common/mmfcontroller.h>
+#include <badesca.h>
+#include <bautils.h>
+#include <f32file.h>
+
+#ifdef AUDIOINPUT_ROUTING
+const QString S60AudioCaptureSession::microPhone("Microphone");
+const QString S60AudioCaptureSession::voiceCall("Voice Call");
+const QString S60AudioCaptureSession::fmRadio("FM Radio");
+#endif
+
+S60AudioCaptureSession::S60AudioCaptureSession(QObject *parent):
+ QObject(parent)
+ , m_recorderUtility(NULL)
+ , m_captureState(ENotInitialized)
+ , m_controllerIdMap(QHash<QString, ControllerData>())
+ , m_audioCodeclist(QHash<QString, CodecData>())
+ , m_error(QMediaRecorder::NoError)
+ , m_isMuted(false)
+{
+ DP0("S60AudioCaptureSession::S60AudioCaptureSession +++");
+#ifdef AUDIOINPUT_ROUTING
+ m_audioInput = NULL;
+ m_setActiveEndPoint = FALSE;
+ m_audioEndpoint = S60AudioCaptureSession::microPhone;
+#endif //AUDIOINPUT_ROUTING
+ TRAPD(err, initializeSessionL());
+ setError(err);
+
+ DP0("S60AudioCaptureSession::S60AudioCaptureSession ---");
+}
+
+void S60AudioCaptureSession::initializeSessionL()
+{
+ DP0("S60AudioCaptureSession::initializeSessionL +++");
+
+ m_recorderUtility = CMdaAudioRecorderUtility::NewL(*this, 0, EMdaPriorityNormal, EMdaPriorityPreferenceTimeAndQuality);
+ updateAudioContainersL();
+ populateAudioCodecsDataL();
+ setDefaultSettings();
+#ifdef AUDIOINPUT_ROUTING
+ initAudioInputs();
+#endif
+ User::LeaveIfError(m_fsSession.Connect());
+ m_captureState = EInitialized;
+ emit stateChanged(m_captureState);
+
+ DP0("S60AudioCaptureSession::initializeSessionL ---");
+}
+
+void S60AudioCaptureSession::setError(TInt aError)
+{
+ DP0("S60AudioCaptureSession::setError +++");
+
+ DP1("S60AudioCaptureSession::setError:", aError);
+
+ if (aError == KErrNone)
+ return;
+
+ m_error = aError;
+ QMediaRecorder::Error recorderError = fromSymbianErrorToMultimediaError(m_error);
+
+ // TODO: fix to user friendly string at some point
+ // These error string are only dev usable
+ QString symbianError;
+ symbianError.append("Symbian:");
+ symbianError.append(QString::number(m_error));
+ stop();
+ emit error(recorderError, symbianError);
+
+ DP0("S60AudioCaptureSession::setError ---");
+}
+
+QMediaRecorder::Error S60AudioCaptureSession::fromSymbianErrorToMultimediaError(int error)
+{
+ DP0("S60AudioCaptureSession::fromSymbianErrorToMultimediaError +++");
+
+ DP1("S60AudioCaptureSession::fromSymbianErrorToMultimediaError:", error);
+
+ switch(error) {
+ case KErrNoMemory:
+ case KErrNotFound:
+ case KErrBadHandle:
+ case KErrAbort:
+ case KErrCorrupt:
+ case KErrGeneral:
+ case KErrPathNotFound:
+ case KErrUnknown:
+ case KErrNotReady:
+ case KErrInUse:
+ case KErrAccessDenied:
+ case KErrLocked:
+ case KErrPermissionDenied:
+ case KErrAlreadyExists:
+ return QMediaRecorder::ResourceError;
+ case KErrNotSupported:
+ case KErrArgument:
+ return QMediaRecorder::FormatError;
+ case KErrNone:
+ default:
+ DP0("S60AudioCaptureSession::fromSymbianErrorToMultimediaError: ---");
+ return QMediaRecorder::NoError;
+ }
+}
+
+S60AudioCaptureSession::~S60AudioCaptureSession()
+{
+ DP0("S60AudioCaptureSession::~S60AudioCaptureSession +++");
+ //stop the utility before deleting it
+ stop();
+ if (m_recorderUtility)
+ delete m_recorderUtility;
+ m_fsSession.Close();
+ DP0("S60AudioCaptureSession::~S60AudioCaptureSession ---");
+}
+
+QAudioFormat S60AudioCaptureSession::format() const
+{
+ DP0("S60AudioCaptureSession::format");
+
+ return m_format;
+}
+
+bool S60AudioCaptureSession::setFormat(const QAudioFormat &format)
+{
+ DP0("S60AudioCaptureSession::setFormat +++");
+
+ m_format = format;
+
+ DP0("S60AudioCaptureSession::setFormat ---");
+
+ return true;
+}
+
+QAudioEncoderSettings S60AudioCaptureSession::settings() const
+{
+ DP0("S60AudioCaptureSession::settings");
+
+ return m_audioEncoderSettings;
+}
+
+bool S60AudioCaptureSession::setEncoderSettings(const QAudioEncoderSettings &setting)
+{
+ DP0("S60AudioCaptureSession::setEncoderSettings +++");
+
+ m_audioEncoderSettings = setting;
+
+ DP0("S60AudioCaptureSession::setEncoderSettings ---");
+
+ return true;
+}
+
+QStringList S60AudioCaptureSession::supportedAudioCodecs() const
+{
+ DP0("S60AudioCaptureSession::supportedAudioCodecs");
+
+ return m_audioCodeclist.keys();
+}
+
+QStringList S60AudioCaptureSession::supportedAudioContainers() const
+{
+ DP0("S60AudioCaptureSession::supportedAudioContainers");
+
+ return m_controllerIdMap.keys();
+}
+
+QString S60AudioCaptureSession::codecDescription(const QString &codecName)
+{
+ DP0("S60AudioCaptureSession::codecDescription +++");
+
+ if (m_audioCodeclist.keys().contains(codecName)) {
+
+ DP0("S60AudioCaptureSession::codecDescription ---");
+ return m_audioCodeclist.value(codecName).codecDescription;
+ }
+ else {
+ DP0("S60AudioCaptureSession::codecDescription ---");
+
+ return QString();
+ }
+}
+
+QString S60AudioCaptureSession::audioContainerDescription(const QString &containerName)
+{
+ DP0("S60AudioCaptureSession::audioContainerDescription +++");
+
+ if (m_controllerIdMap.keys().contains(containerName)) {
+ DP0("S60AudioCaptureSession::audioContainerDescription ---");
+
+ return m_controllerIdMap.value(containerName).destinationFormatDescription;
+ }
+ else {
+ DP0("S60AudioCaptureSession::audioContainerDescription ---");
+
+ return QString();
+ }
+}
+
+bool S60AudioCaptureSession::setAudioCodec(const QString &codecName)
+{
+ DP0("S60AudioCaptureSession::setAudioCodec");
+
+ QStringList codecs = supportedAudioCodecs();
+ if(codecs.contains(codecName)) {
+ m_format.setCodec(codecName);
+ return true;
+ }
+ return false;
+}
+
+bool S60AudioCaptureSession::setAudioContainer(const QString &containerMimeType)
+{
+ DP0("S60AudioCaptureSession::setAudioContainer");
+
+ QStringList containers = supportedAudioContainers();
+ if (containerMimeType == "audio/mpeg")
+ {
+ m_container = "audio/mp4";
+ return true;
+ }
+ if(containers.contains(containerMimeType)) {
+ m_container = containerMimeType;
+ return true;
+ }
+ return false;
+}
+
+QString S60AudioCaptureSession::audioCodec() const
+{
+ DP0("S60AudioCaptureSession::audioCodec");
+
+ return m_format.codec();
+}
+
+QString S60AudioCaptureSession::audioContainer() const
+{
+ DP0("S60AudioCaptureSession::audioContainer");
+
+ return m_container;
+}
+
+QUrl S60AudioCaptureSession::outputLocation() const
+{
+ DP0("S60AudioCaptureSession::outputLocation");
+
+ return m_sink;
+}
+
+bool S60AudioCaptureSession::setOutputLocation(const QUrl& sink)
+{
+ DP0("S60AudioCaptureSession::setOutputLocation");
+
+ QString filename = QDir::toNativeSeparators(sink.toString());
+ TPtrC16 path(reinterpret_cast<const TUint16*>(filename.utf16()));
+ TRAPD(err, BaflUtils::EnsurePathExistsL(m_fsSession,path));
+ if (err == KErrNone) {
+ m_sink = sink;
+ setError(err);
+ return true;
+ }else {
+ setError(err);
+ return false;
+ }
+}
+
+qint64 S60AudioCaptureSession::position() const
+{
+ DP0("S60AudioCaptureSession::position");
+
+ if ((m_captureState != ERecording) || !m_recorderUtility)
+ return 0;
+
+ return m_recorderUtility->Duration().Int64() / 1000;
+}
+
+void S60AudioCaptureSession::prepareSinkL()
+{
+ DP0("S60AudioCaptureSession::prepareSinkL +++");
+
+ /* If m_outputLocation is null, set a default location */
+ if (m_sink.isEmpty()) {
+ QDir outputDir(QDir::rootPath());
+ int lastImage = 0;
+ int fileCount = 0;
+ foreach(QString fileName, outputDir.entryList(QStringList() << "recordclip_*")) {
+ int imgNumber = fileName.mid(5, fileName.size() - 9).toInt();
+ lastImage = qMax(lastImage, imgNumber);
+ if (outputDir.exists(fileName))
+ fileCount += 1;
+ }
+ lastImage += fileCount;
+ m_sink = QUrl(QDir::toNativeSeparators(outputDir.canonicalPath() + QString("/recordclip_%1").arg(lastImage + 1, 4, 10, QLatin1Char('0'))));
+ }
+
+ QString sink = QDir::toNativeSeparators(m_sink.toString());
+ TPtrC16 path(reinterpret_cast<const TUint16*>(sink.utf16()));
+ if (BaflUtils::FileExists(m_fsSession, path))
+ BaflUtils::DeleteFile(m_fsSession, path);
+
+ int index = sink.lastIndexOf('.');
+ if (index != -1)
+ sink.chop(sink.length()-index);
+
+ sink.append(m_controllerIdMap.value(m_container).fileExtension);
+ m_sink.setUrl(sink);
+
+ DP0("S60AudioCaptureSession::prepareSinkL ---");
+}
+
+void S60AudioCaptureSession::record()
+{
+ DP0("S60AudioCaptureSession::record +++");
+
+ if (!m_recorderUtility)
+ return;
+
+ if (m_captureState == EInitialized || m_captureState == ERecordComplete) {
+ prepareSinkL();
+ QString filename = m_sink.toString();
+ TPtrC16 sink(reinterpret_cast<const TUint16*>(filename.utf16()));
+ TUid controllerUid(TUid::Uid(m_controllerIdMap.value(m_container).controllerUid));
+ TUid formatUid(TUid::Uid(m_controllerIdMap.value(m_container).destinationFormatUid));
+
+ TRAPD(err,m_recorderUtility->OpenFileL(sink));
+ setError(err);
+ }else if (m_captureState == EPaused) {
+ m_recorderUtility->SetPosition(m_pausedPosition);
+ TRAPD(error, m_recorderUtility->RecordL());
+ setError(error);
+ m_captureState = ERecording;
+ emit stateChanged(m_captureState);
+ }
+
+ DP0("S60AudioCaptureSession::record ---");
+}
+
+void S60AudioCaptureSession::mute(bool muted)
+{
+ DP0("S60AudioCaptureSession::mute +++");
+
+ if (!m_recorderUtility)
+ return;
+
+ if (muted)
+ m_recorderUtility->SetGain(0);
+ else
+ m_recorderUtility->SetGain(m_recorderUtility->MaxGain());
+
+ m_isMuted = muted;
+
+ DP0("S60AudioCaptureSession::mute ---");
+}
+
+bool S60AudioCaptureSession::muted()
+{
+ DP0("S60AudioCaptureSession::muted");
+
+ return m_isMuted;
+}
+
+void S60AudioCaptureSession::setDefaultSettings()
+{
+ DP0("S60AudioCaptureSession::setDefaultSettings +++");
+
+ // Setting AMR to default format if supported
+ if (m_controllerIdMap.count() > 0) {
+ if ( m_controllerIdMap.contains("audio/amr"))
+ m_container = QString("audio/amr");
+ else
+ m_container = m_controllerIdMap.keys()[0];
+ }
+ if (m_audioCodeclist.keys().count() > 0) {
+ if (m_audioCodeclist.keys().contains("AMR")) {
+ m_format.setSampleSize(8);
+ m_format.setChannels(1);
+ m_format.setFrequency(8000);
+ m_format.setSampleType(QAudioFormat::SignedInt);
+ m_format.setCodec("AMR");
+ }else
+ m_format.setCodec(m_audioCodeclist.keys()[0]);
+ }
+
+ DP0("S60AudioCaptureSession::setDefaultSettings ---");
+}
+
+void S60AudioCaptureSession::pause()
+{
+ DP0("S60AudioCaptureSession::pause +++");
+
+ if (!m_recorderUtility)
+ return;
+
+ m_pausedPosition = m_recorderUtility->Position();
+ m_recorderUtility->Stop();
+ m_captureState = EPaused;
+ emit stateChanged(m_captureState);
+
+ DP0("S60AudioCaptureSession::pause ---");
+}
+
+void S60AudioCaptureSession::stop()
+{
+ DP0("S60AudioCaptureSession::stop +++");
+
+ if (!m_recorderUtility)
+ return;
+
+ m_recorderUtility->Stop();
+
+#ifdef AUDIOINPUT_ROUTING
+ //delete audio input instance before closing the utility.
+ if (m_audioInput)
+ {
+ delete m_audioInput;
+ m_audioInput = NULL;
+ }
+#endif //AUDIOINPUT_ROUTING
+
+ m_recorderUtility->Close();
+ m_captureState = ERecordComplete;
+ emit stateChanged(m_captureState);
+}
+
+#ifdef AUDIOINPUT_ROUTING
+
+void S60AudioCaptureSession::initAudioInputs()
+{
+ DP0(" S60AudioCaptureSession::initAudioInputs +++");
+
+ m_audioInputs[S60AudioCaptureSession::microPhone] = QString("Microphone associated with the currently active speaker.");
+ m_audioInputs[S60AudioCaptureSession::voiceCall] = QString("Audio stream associated with the current phone call.");
+ m_audioInputs[S60AudioCaptureSession::fmRadio] = QString("Audio of the currently tuned FM radio station.");
+
+ DP0(" S60AudioCaptureSession::initAudioInputs ---");
+}
+
+#endif //AUDIOINPUT_ROUTING
+
+void S60AudioCaptureSession::setActiveEndpoint(const QString& audioEndpoint)
+{
+ DP0(" S60AudioCaptureSession::setActiveEndpoint +++");
+
+ if (!m_audioInputs.keys().contains(audioEndpoint))
+ return;
+
+ if (activeEndpoint().compare(audioEndpoint) != 0) {
+ m_audioEndpoint = audioEndpoint;
+#ifdef AUDIOINPUT_ROUTING
+ m_setActiveEndPoint = TRUE;
+#endif
+ }
+
+ DP0(" S60AudioCaptureSession::setActiveEndpoint ---");
+}
+
+QList<QString> S60AudioCaptureSession::availableEndpoints() const
+{
+ DP0(" S60AudioCaptureSession::availableEndpoints");
+
+ return m_audioInputs.keys();
+}
+
+QString S60AudioCaptureSession::endpointDescription(const QString& name) const
+{
+ DP0(" S60AudioCaptureSession::endpointDescription +++");
+
+ if (m_audioInputs.keys().contains(name))
+ return m_audioInputs.value(name);
+ return QString();
+}
+
+QString S60AudioCaptureSession::activeEndpoint() const
+{
+ DP0(" S60AudioCaptureSession::activeEndpoint");
+
+ QString inputSourceName = NULL;
+#ifdef AUDIOINPUT_ROUTING
+ if (m_audioInput) {
+ CAudioInput::TAudioInputArray input = m_audioInput->AudioInput();
+ inputSourceName = qStringFromTAudioInputPreference(input[0]);
+ }
+#endif //AUDIOINPUT_ROUTING
+ return inputSourceName;
+}
+
+QString S60AudioCaptureSession::defaultEndpoint() const
+{
+ DP0(" S60AudioCaptureSession::defaultEndpoint");
+
+#ifdef AUDIOINPUT_ROUTING
+ return QString(S60AudioCaptureSession::microPhone);
+#else
+ return NULL;
+#endif
+}
+
+#ifdef AUDIOINPUT_ROUTING
+
+void S60AudioCaptureSession::doSetAudioInputL(const QString& name)
+{
+ DP0(" S60AudioCaptureSession::doSetAudioInputL +++");
+ DP1(" S60AudioCaptureSession::doSetAudioInputL:", name);
+ TInt err(KErrNone);
+
+ if (!m_recorderUtility)
+ return;
+
+ CAudioInput::TAudioInputPreference input = CAudioInput::EDefaultMic;
+
+ if (name.compare(S60AudioCaptureSession::voiceCall) == 0)
+ input = CAudioInput::EVoiceCall;
+// commented because they are not supported on 9.2
+ else if (name.compare(S60AudioCaptureSession::fmRadio) == 0)
+ input = CAudioInput::EFMRadio;
+ else // S60AudioCaptureSession::microPhone
+ input = CAudioInput::EDefaultMic;
+
+ RArray<CAudioInput::TAudioInputPreference> inputArray;
+ inputArray.Append(input);
+
+ if (m_audioInput){
+ TRAP(err,m_audioInput->SetAudioInputL(inputArray.Array()));
+
+ if (err == KErrNone) {
+ emit activeEndpointChanged(name);
+ }
+ else{
+ setError(err);
+ }
+ }
+ inputArray.Close();
+
+ DP0(" S60AudioCaptureSession::doSetAudioInputL ---");
+}
+
+
+QString S60AudioCaptureSession::qStringFromTAudioInputPreference(CAudioInput::TAudioInputPreference input) const
+{
+ DP0(" S60AudioCaptureSession::qStringFromTAudioInputPreference");
+
+ if (input == CAudioInput::EVoiceCall)
+ return S60AudioCaptureSession::voiceCall;
+ else if (input == CAudioInput::EFMRadio)
+ return S60AudioCaptureSession::fmRadio;
+ else
+ return S60AudioCaptureSession::microPhone; // CAudioInput::EDefaultMic
+}
+#endif //AUDIOINPUT_ROUTING
+
+
+void S60AudioCaptureSession::MoscoStateChangeEvent(CBase* aObject,
+ TInt aPreviousState, TInt aCurrentState, TInt aErrorCode)
+{
+ DP0("S60AudioCaptureSession::MoscoStateChangeEvent +++");
+
+ if (aErrorCode==KErrNone) {
+ TRAPD(err, MoscoStateChangeEventL(aObject, aPreviousState, aCurrentState, NULL));
+ setError(err);
+ }
+ else {
+ setError(aErrorCode);
+ }
+ DP1("S60AudioCaptureSession::MoscoStateChangeEvent, aErrorCode:", aErrorCode);
+ DP0("S60AudioCaptureSession::MoscoStateChangeEvent ---");
+}
+
+void S60AudioCaptureSession::MoscoStateChangeEventL(CBase* aObject,
+ TInt aPreviousState, TInt aCurrentState, TInt aErrorCode)
+{
+ DP0("S60AudioCaptureSession::MoscoStateChangeEventL +++");
+
+ DP5("S60AudioCaptureSession::MoscoStateChangeEventL - aPreviousState:", aPreviousState,
+ "aCurrentState:", aCurrentState, "aErrorCode:", aErrorCode);
+ if (aObject != m_recorderUtility)
+ return;
+
+ switch(aCurrentState) {
+ case CMdaAudioClipUtility::EOpen: {
+ if(aPreviousState == CMdaAudioClipUtility::ENotReady) {
+ applyAudioSettingsL();
+ m_recorderUtility->SetGain(m_recorderUtility->MaxGain());
+ TRAPD(err, m_recorderUtility->RecordL());
+ setError(err);
+ m_captureState = EOpenCompelete;
+ emit stateChanged(m_captureState);
+ }
+ break;
+ }
+ case CMdaAudioClipUtility::ENotReady: {
+ m_captureState = EInitialized;
+ emit stateChanged(m_captureState);
+ break;
+ }
+ case CMdaAudioClipUtility::ERecording: {
+ m_captureState = ERecording;
+ emit stateChanged(m_captureState);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ DP0("S60AudioCaptureSession::MoscoStateChangeEventL ---");
+}
+
+void S60AudioCaptureSession::updateAudioContainersL()
+{
+ DP0("S60AudioCaptureSession::updateAudioContainersL +++");
+
+ CMMFControllerPluginSelectionParameters* pluginParameters =
+ CMMFControllerPluginSelectionParameters::NewLC();
+ CMMFFormatSelectionParameters* formatParameters =
+ CMMFFormatSelectionParameters::NewLC();
+
+ pluginParameters->SetRequiredRecordFormatSupportL(*formatParameters);
+
+ RArray<TUid> ids;
+ CleanupClosePushL(ids);
+ User::LeaveIfError(ids.Append(KUidMediaTypeAudio));
+
+ pluginParameters->SetMediaIdsL(ids,
+ CMMFPluginSelectionParameters::EAllowOnlySuppliedMediaIds);
+
+ RMMFControllerImplInfoArray controllers;
+ CleanupResetAndDestroyPushL(controllers);
+
+ //Get all audio record controllers/formats that are supported
+ pluginParameters->ListImplementationsL(controllers);
+
+ for (TInt index=0; index<controllers.Count(); index++) {
+ const RMMFFormatImplInfoArray& recordFormats =
+ controllers[index]->RecordFormats();
+ for (TInt j=0; j<recordFormats.Count(); j++) {
+ const CDesC8Array& mimeTypes = recordFormats[j]->SupportedMimeTypes();
+ const CDesC8Array& fileExtensions = recordFormats[j]->SupportedFileExtensions();
+ TInt mimeCount = mimeTypes.Count();
+ TInt fileExtCount = fileExtensions.Count();
+
+ if (mimeCount > 0 && fileExtCount > 0) {
+ TPtrC8 extension = fileExtensions[0];
+ TPtrC8 mimeType = mimeTypes[0];
+ QString type = QString::fromUtf8((char *)mimeType.Ptr(), mimeType.Length());
+
+ if (type != "audio/basic") {
+ ControllerData data;
+ data.controllerUid = controllers[index]->Uid().iUid;
+ data.destinationFormatUid = recordFormats[j]->Uid().iUid;
+ data.destinationFormatDescription = QString::fromUtf16(
+ recordFormats[j]->DisplayName().Ptr(),
+ recordFormats[j]->DisplayName().Length());
+ data.fileExtension = QString::fromUtf8((char *)extension.Ptr(), extension.Length());
+ m_controllerIdMap[type] = data;
+ }
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(4);//controllers, ids, formatParameters, pluginParameters
+
+ DP0("S60AudioCaptureSession::updateAudioContainersL ---");
+}
+
+void S60AudioCaptureSession::retrieveSupportedAudioSampleRatesL()
+{
+ DP0("S60AudioCaptureSession::retrieveSupportedAudioSampleRatesL +++");
+
+ if (!m_recorderUtility) {
+ DP0("No RecorderUtility");
+ return;
+ }
+
+ m_supportedSampleRates.clear();
+
+ RArray<TUint> supportedSampleRates;
+ CleanupClosePushL(supportedSampleRates);
+ m_recorderUtility->GetSupportedSampleRatesL(supportedSampleRates);
+ for (TInt j = 0; j < supportedSampleRates.Count(); j++ )
+ m_supportedSampleRates.append(supportedSampleRates[j]);
+
+ CleanupStack::PopAndDestroy(&supportedSampleRates);
+
+ DP0("S60AudioCaptureSession::retrieveSupportedAudioSampleRatesL ---");
+}
+
+QList<int> S60AudioCaptureSession::supportedAudioSampleRates(const QAudioEncoderSettings &settings) const
+{
+ DP0("S60AudioCaptureSession::supportedAudioSampleRates +++");
+
+ QList<int> supportedSampleRates;
+
+ if (!settings.codec().isEmpty()) {
+ if (settings.codec() == "AMR")
+ supportedSampleRates.append(8000);
+ else
+ supportedSampleRates = m_supportedSampleRates;
+ }else
+ supportedSampleRates = m_supportedSampleRates;
+
+ DP0("S60AudioCaptureSession::supportedAudioSampleRates ---");
+
+ return supportedSampleRates;
+}
+
+void S60AudioCaptureSession::populateAudioCodecsDataL()
+{
+ DP0("S60AudioCaptureSession::populateAudioCodecsDataL +++");
+
+ if (!m_recorderUtility) {
+ DP0("No RecorderUtility");
+
+ return;
+ }
+
+ if (m_controllerIdMap.contains("audio/amr")) {
+ CodecData data;
+ data.codecDescription = QString("GSM AMR Codec");
+ m_audioCodeclist[QString("AMR")]=data;
+ }
+ if (m_controllerIdMap.contains("audio/basic")) {
+ CodecData data;
+ data.fourCC = KMMFFourCCCodeALAW;
+ data.codecDescription = QString("Sun/Next ""Au"" audio codec");
+ m_audioCodeclist[QString("AULAW")]=data;
+ }
+ if (m_controllerIdMap.contains("audio/wav")) {
+ CodecData data;
+ data.fourCC = KMMFFourCCCodePCM16;
+ data.codecDescription = QString("Pulse code modulation");
+ m_audioCodeclist[QString("PCM")]=data;
+ }
+ if (m_controllerIdMap.contains("audio/mp4")) {
+ CodecData data;
+ data.fourCC = KMMFFourCCCodeAAC;
+ data.codecDescription = QString("Advanced Audio Codec");
+ m_audioCodeclist[QString("AAC")]=data;
+ }
+
+ // default samplerates
+ m_supportedSampleRates << 96000 << 88200 << 64000 << 48000 << 44100 << 32000 << 24000 << 22050 << 16000 << 12000 << 11025 << 8000;
+
+ DP0("S60AudioCaptureSession::populateAudioCodecsDataL ---");
+}
+
+void S60AudioCaptureSession::applyAudioSettingsL()
+{
+ DP0("S60AudioCaptureSession::applyAudioSettingsL +++");
+
+ if (!m_recorderUtility)
+ return;
+
+#ifdef AUDIOINPUT_ROUTING
+ //CAudioInput needs to be re-initialized every time recording starts
+ if (m_audioInput) {
+ delete m_audioInput;
+ m_audioInput = NULL;
+ }
+
+ if (m_setActiveEndPoint) {
+ m_audioInput = CAudioInput::NewL(*m_recorderUtility);
+ doSetAudioInputL(m_audioEndpoint);
+ }
+#endif //AUDIOINPUT_ROUTING
+
+ if (m_format.codec() == "AMR")
+ return;
+
+ TFourCC fourCC = m_audioCodeclist.value(m_format.codec()).fourCC;
+
+ if (m_format.codec() == "PCM")
+ fourCC = determinePCMFormat();
+
+ RArray<TFourCC> supportedDataTypes;
+ CleanupClosePushL(supportedDataTypes);
+ TRAPD(err,m_recorderUtility->GetSupportedDestinationDataTypesL(supportedDataTypes));
+ TInt num = supportedDataTypes.Count();
+ if (num > 0 ) {
+ supportedDataTypes.SortUnsigned();
+ int index = supportedDataTypes.Find(fourCC.FourCC());
+ if (index != KErrNotFound) {
+ TRAPD(err,m_recorderUtility->SetDestinationDataTypeL(supportedDataTypes[index]));
+ }
+ }
+
+ supportedDataTypes.Reset();
+ CleanupStack::PopAndDestroy(&supportedDataTypes);
+
+ if (m_recorderUtility->DestinationSampleRateL() != m_format.frequency()) {
+
+ RArray<TUint> supportedSampleRates;
+ CleanupClosePushL(supportedSampleRates);
+ m_recorderUtility->GetSupportedSampleRatesL(supportedSampleRates);
+ for (TInt i = 0; i < supportedSampleRates.Count(); i++ ) {
+ TUint supportedSampleRate = supportedSampleRates[i];
+ if (supportedSampleRate == m_format.frequency()) {
+ m_recorderUtility->SetDestinationSampleRateL(m_format.frequency());
+ break;
+ }
+ }
+ supportedSampleRates.Reset();
+ CleanupStack::PopAndDestroy(&supportedSampleRates);
+ }
+
+ /* If requested channel setting is different than current one */
+ if (m_recorderUtility->DestinationNumberOfChannelsL() != m_format.channels()) {
+ RArray<TUint> supportedChannels;
+ CleanupClosePushL(supportedChannels);
+ m_recorderUtility->GetSupportedNumberOfChannelsL(supportedChannels);
+ for (TInt l = 0; l < supportedChannels.Count(); l++ ) {
+ if (supportedChannels[l] == m_format.channels()) {
+ m_recorderUtility->SetDestinationNumberOfChannelsL(m_format.channels());
+ break;
+ }
+ }
+ supportedChannels.Reset();
+ CleanupStack::PopAndDestroy(&supportedChannels);
+ }
+
+ if (!(m_format.codec().compare("pcm",Qt::CaseInsensitive) == 0)) {
+ if (m_recorderUtility->DestinationBitRateL() != m_audioEncoderSettings.bitRate()) {
+ RArray<TUint> supportedBitRates;
+ CleanupClosePushL(supportedBitRates);
+ m_recorderUtility->GetSupportedBitRatesL(supportedBitRates);
+ for (TInt l = 0; l < supportedBitRates.Count(); l++ ) {
+ if (supportedBitRates[l] == m_audioEncoderSettings.bitRate()) {
+ m_recorderUtility->SetDestinationBitRateL(m_audioEncoderSettings.bitRate());
+ break;
+ }
+ }
+ supportedBitRates.Reset();
+ CleanupStack::PopAndDestroy(&supportedBitRates);
+ }
+ }
+
+ DP0("S60AudioCaptureSession::applyAudioSettingsL ---");
+}
+
+TFourCC S60AudioCaptureSession::determinePCMFormat()
+{
+ DP0("S60AudioCaptureSession::determinePCMFormat +++");
+
+ TFourCC fourCC;
+
+ if (m_format.sampleSize() == 8) {
+ // 8 bit
+ switch (m_format.sampleType()) {
+ case QAudioFormat::SignedInt: {
+ fourCC.Set(KMMFFourCCCodePCM8);
+ break;
+ }
+ case QAudioFormat::UnSignedInt: {
+ fourCC.Set(KMMFFourCCCodePCMU8);
+ break;
+ }
+ case QAudioFormat::Float:
+ case QAudioFormat::Unknown:
+ default: {
+ fourCC.Set(KMMFFourCCCodePCM8);
+ break;
+ }
+ }
+ } else if (m_format.sampleSize() == 16) {
+ // 16 bit
+ switch (m_format.sampleType()) {
+ case QAudioFormat::SignedInt: {
+ fourCC.Set(m_format.byteOrder()==QAudioFormat::BigEndian?
+ KMMFFourCCCodePCM16B:KMMFFourCCCodePCM16);
+ break;
+ }
+ case QAudioFormat::UnSignedInt: {
+ fourCC.Set(m_format.byteOrder()==QAudioFormat::BigEndian?
+ KMMFFourCCCodePCMU16B:KMMFFourCCCodePCMU16);
+ break;
+ }
+ default: {
+ fourCC.Set(KMMFFourCCCodePCM16);
+ break;
+ }
+ }
+ }
+
+ DP0("S60AudioCaptureSession::determinePCMFormat ---");
+
+ return fourCC;
+}
diff --git a/src/plugins/symbian/mmf/audiosource/s60audiocapturesession.h b/src/plugins/symbian/mmf/audiosource/s60audiocapturesession.h
new file mode 100644
index 000000000..a541446e9
--- /dev/null
+++ b/src/plugins/symbian/mmf/audiosource/s60audiocapturesession.h
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60AUDIOCAPTURESESSION_H
+#define S60AUDIOCAPTURESESSION_H
+
+#include <qmobilityglobal.h>
+#include <QtCore/qobject.h>
+#include <QFile>
+#include <QUrl>
+#include <QList>
+#include <QHash>
+#include <QMap>
+#include "qaudioformat.h"
+#include <qmediarecorder.h>
+
+#include <mda/common/audio.h>
+#include <mda/common/resource.h>
+#include <mda/client/utility.h>
+#include <mdaaudiosampleeditor.h>
+#include <mmf/common/mmfutilities.h>
+
+#ifdef AUDIOINPUT_ROUTING
+#include <audioinput.h>
+#endif //AUDIOINPUT_ROUTING
+
+QT_BEGIN_NAMESPACE
+struct ControllerData
+{
+ int controllerUid;
+ int destinationFormatUid;
+ QString destinationFormatDescription;
+ QString fileExtension;
+};
+
+struct CodecData
+{
+ TFourCC fourCC;
+ QString codecDescription;
+};
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class S60AudioCaptureSession : public QObject, public MMdaObjectStateChangeObserver
+{
+ Q_OBJECT
+ Q_PROPERTY(qint64 position READ position NOTIFY positionChanged)
+ Q_ENUMS(TAudioCaptureState)
+public:
+
+ enum TAudioCaptureState
+ {
+ ENotInitialized = 0,
+ EInitialized,
+ EOpenCompelete,
+ ERecording,
+ EPaused,
+ ERecordComplete
+ };
+
+ S60AudioCaptureSession(QObject *parent = 0);
+ ~S60AudioCaptureSession();
+
+ QAudioFormat format() const;
+ bool setFormat(const QAudioFormat &format);
+ QAudioEncoderSettings settings() const;
+ bool setEncoderSettings(const QAudioEncoderSettings &setting);
+ QStringList supportedAudioCodecs() const;
+ QString codecDescription(const QString &codecName);
+ bool setAudioCodec(const QString &codecName);
+ QString audioCodec() const;
+ QString audioContainer() const;
+ QStringList supportedAudioContainers() const;
+ bool setAudioContainer(const QString &containerMimeType);
+ QString audioContainerDescription(const QString &containerName);
+ QList<int> supportedAudioSampleRates(const QAudioEncoderSettings &settings) const;
+ QUrl outputLocation() const;
+ bool setOutputLocation(const QUrl& sink);
+ qint64 position() const;
+ void record();
+ void pause();
+ void stop();
+ void mute(bool muted);
+ bool muted();
+
+ QString activeEndpoint() const;
+ QString defaultEndpoint() const;
+ QList<QString> availableEndpoints() const;
+ QString endpointDescription(const QString& name) const;
+
+#ifdef AUDIOINPUT_ROUTING
+ static const QString microPhone;
+ static const QString voiceCall;
+ static const QString fmRadio;
+#endif //AUDIOINPUT_ROUTING
+private:
+ void initializeSessionL();
+ void setError(TInt aError);
+ QMediaRecorder::Error fromSymbianErrorToMultimediaError(int error);
+ void prepareSinkL();
+ void updateAudioContainersL();
+ void populateAudioCodecsDataL();
+ void retrieveSupportedAudioSampleRatesL();
+ void applyAudioSettingsL();
+ TFourCC determinePCMFormat();
+ void setDefaultSettings();
+ // MMdaObjectStateChangeObserver
+ void MoscoStateChangeEvent(CBase* aObject, TInt aPreviousState,
+ TInt aCurrentState, TInt aErrorCode);
+ void MoscoStateChangeEventL(CBase* aObject, TInt aPreviousState,
+ TInt aCurrentState, TInt aErrorCode);
+
+#ifdef AUDIOINPUT_ROUTING
+ QString qStringFromTAudioInputPreference(CAudioInput::TAudioInputPreference input) const;
+ void initAudioInputs();
+ void doSetAudioInputL(const QString& name);
+#endif //AUDIOINPUT_ROUTING
+
+public Q_SLOTS:
+ void setActiveEndpoint(const QString& audioEndpoint);
+
+
+Q_SIGNALS:
+ void stateChanged(S60AudioCaptureSession::TAudioCaptureState);
+ void positionChanged(qint64 position);
+ void error(int error, const QString &errorString);
+ void activeEndpointChanged(const QString &audioEndpoint);
+private:
+ QString m_container;
+ QUrl m_sink;
+ TTimeIntervalMicroSeconds m_pausedPosition;
+ CMdaAudioRecorderUtility *m_recorderUtility;
+ TAudioCaptureState m_captureState;
+ QAudioFormat m_format;
+ QAudioEncoderSettings m_audioEncoderSettings;
+ QHash<QString, ControllerData> m_controllerIdMap;
+ QHash<QString, CodecData> m_audioCodeclist;
+ QList<int> m_supportedSampleRates;
+ int m_error;
+ bool m_isMuted;
+ RFs m_fsSession;
+
+#ifdef AUDIOINPUT_ROUTING
+ bool m_setActiveEndPoint;
+ CAudioInput *m_audioInput;
+
+#endif //AUDIOINPUT_ROUTING
+ QMap<QString, QString> m_audioInputs;
+ QString m_audioEndpoint;
+
+
+};
+
+#endif // S60AUDIOCAPTURESESSION_H
diff --git a/src/plugins/symbian/mmf/audiosource/s60audiocontainercontrol.cpp b/src/plugins/symbian/mmf/audiosource/s60audiocontainercontrol.cpp
new file mode 100644
index 000000000..d6c2d5db2
--- /dev/null
+++ b/src/plugins/symbian/mmf/audiosource/s60audiocontainercontrol.cpp
@@ -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$
+** 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 "DebugMacros.h"
+
+#include "s60audiocontainercontrol.h"
+#include "s60audiocapturesession.h"
+#include <QtCore/qdebug.h>
+
+S60AudioContainerControl::S60AudioContainerControl(QObject *parent)
+ : QMediaContainerControl(parent)
+{
+ DP0("S60AudioContainerControl::S60AudioContainerControl(QObject *parent) +++");
+
+ DP0("S60AudioContainerControl::S60AudioContainerControl(QObject *parent) ---");
+
+}
+
+S60AudioContainerControl::S60AudioContainerControl(QObject *session, QObject *parent)
+ : QMediaContainerControl(parent)
+{
+ DP0("S60AudioContainerControl::S60AudioContainerControl(QObject *session, QObject *parent) +++");
+
+ m_session = qobject_cast<S60AudioCaptureSession*>(session);
+
+ DP0("S60AudioContainerControl::S60AudioContainerControl(QObject *session, QObject *parent) ---");
+}
+
+QStringList S60AudioContainerControl::supportedContainers() const
+{
+ DP0("S60AudioContainerControl::supportedContainers");
+
+ return m_session->supportedAudioContainers();
+}
+
+QString S60AudioContainerControl::containerMimeType() const
+{
+ DP0("S60AudioContainerControl::containerMimeType");
+
+ return m_session->audioContainer();
+}
+
+void S60AudioContainerControl::setContainerMimeType(const QString &containerMimeType)
+{
+ DP0("S60AudioContainerControl::setContainerMimeType +++");
+
+ m_session->setAudioContainer(containerMimeType);
+
+ DP0("S60AudioContainerControl::setContainerMimeType ---");
+}
+
+QString S60AudioContainerControl::containerDescription(const QString &containerMimeType) const
+{
+ DP0("S60AudioContainerControl::containerDescription");
+
+ return m_session->audioContainerDescription(containerMimeType);
+}
+
diff --git a/src/plugins/symbian/mmf/audiosource/s60audiocontainercontrol.h b/src/plugins/symbian/mmf/audiosource/s60audiocontainercontrol.h
new file mode 100644
index 000000000..4c3498d0f
--- /dev/null
+++ b/src/plugins/symbian/mmf/audiosource/s60audiocontainercontrol.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 S60AUDIOFORMATCONTROL_H
+#define S60AUDIOFORMATCONTROL_H
+
+#include "qmediacontainercontrol.h"
+#include <QtCore/qstringlist.h>
+
+
+QT_USE_NAMESPACE
+
+class S60AudioCaptureSession;
+
+class S60AudioContainerControl : public QMediaContainerControl
+{
+Q_OBJECT
+public:
+ S60AudioContainerControl(QObject *parent = 0);
+ S60AudioContainerControl(QObject *session, QObject *parent = 0);
+ virtual ~S60AudioContainerControl() {};
+
+ QStringList supportedContainers() const;
+ QString containerMimeType() const;
+ void setContainerMimeType(const QString &containerMimeType);
+ QString containerDescription(const QString &containerMimeType) const;
+
+private:
+ S60AudioCaptureSession* m_session;
+};
+
+#endif // S60AUDIOFORMATCONTROL_H
diff --git a/src/plugins/symbian/mmf/audiosource/s60audioencodercontrol.cpp b/src/plugins/symbian/mmf/audiosource/s60audioencodercontrol.cpp
new file mode 100644
index 000000000..b3d02a94a
--- /dev/null
+++ b/src/plugins/symbian/mmf/audiosource/s60audioencodercontrol.cpp
@@ -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$
+** 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 "DebugMacros.h"
+
+#include "s60audioencodercontrol.h"
+#include "s60audiocapturesession.h"
+
+#include "qaudioformat.h"
+
+#include <QtCore/qdebug.h>
+
+S60AudioEncoderControl::S60AudioEncoderControl(QObject *session, QObject *parent)
+ :QAudioEncoderControl(parent), m_quality(QtMultimediaKit::NormalQuality)
+{
+ DP0("S60AudioEncoderControl::S60AudioEncoderControl +++");
+
+ m_session = qobject_cast<S60AudioCaptureSession*>(session);
+ QAudioFormat fmt = m_session->format();
+ // medium, 22050Hz mono S16
+ fmt.setSampleType(QAudioFormat::SignedInt);
+ if (fmt.codec().compare("PCM", Qt::CaseInsensitive) == 0) {
+ fmt.setSampleSize(16);
+ fmt.setFrequency(22050);
+ }
+ fmt.setChannels(1);
+ m_session->setFormat(fmt);
+ m_settings.setChannelCount(fmt.channels());
+ m_settings.setCodec(fmt.codec());
+ m_settings.setSampleRate(fmt.sampleRate());
+
+ DP0("S60AudioEncoderControl::S60AudioEncoderControl ---");
+}
+
+S60AudioEncoderControl::~S60AudioEncoderControl()
+{
+ DP0("S60AudioEncoderControl::~S60AudioEncoderControl +++");
+
+ DP0("S60AudioEncoderControl::~S60AudioEncoderControl ---");
+}
+
+QStringList S60AudioEncoderControl::supportedAudioCodecs() const
+{
+ DP0("S60AudioEncoderControl::supportedAudioCodecs");
+
+ return m_session->supportedAudioCodecs();
+}
+
+QString S60AudioEncoderControl::codecDescription(const QString &codecName) const
+{
+ DP0("S60AudioEncoderControl::codecDescription");
+
+ return m_session->codecDescription(codecName);
+}
+
+QtMultimediaKit::EncodingQuality S60AudioEncoderControl::quality() const
+{
+ DP0("S60AudioEncoderControl::quality");
+
+ return m_quality;
+}
+
+void S60AudioEncoderControl::setQuality(QtMultimediaKit::EncodingQuality value, QAudioFormat &fmt)
+{
+ DP0("S60AudioEncoderControl::setQuality +++");
+
+ switch (value) {
+ case QtMultimediaKit::VeryLowQuality:
+ case QtMultimediaKit::LowQuality:
+ // low, 8000Hz mono U8
+ fmt.setSampleType(QAudioFormat::UnSignedInt);
+ fmt.setSampleSize(8);
+ fmt.setFrequency(8000);
+ fmt.setChannels(1);
+ break;
+ case QtMultimediaKit::NormalQuality:
+ // medium, 22050Hz mono S16
+ fmt.setSampleType(QAudioFormat::SignedInt);
+ fmt.setSampleSize(16);
+ fmt.setFrequency(22050);
+ fmt.setChannels(1);
+ break;
+ case QtMultimediaKit::HighQuality:
+ case QtMultimediaKit::VeryHighQuality:
+ // high, 44100Hz mono S16
+ fmt.setSampleType(QAudioFormat::SignedInt);
+ fmt.setSampleSize(16);
+ fmt.setFrequency(44100);
+ fmt.setChannels(2);
+ break;
+ default:
+ break;
+ }
+
+ DP0("S60AudioEncoderControl::setQuality ---");
+}
+
+QStringList S60AudioEncoderControl::supportedEncodingOptions(const QString &codec) const
+{
+ DP0("S60AudioEncoderControl::supportedEncodingOptions");
+
+ Q_UNUSED(codec)
+ QStringList list;
+ if (codec == "PCM")
+ list << "quality" << "channels" << "samplerate";
+ return list;
+}
+
+QVariant S60AudioEncoderControl::encodingOption(const QString &codec, const QString &name) const
+{
+ DP0("S60AudioEncoderControl::encodingOption");
+
+ if (codec == "PCM") {
+ QAudioFormat fmt = m_session->format();
+
+ if(qstrcmp(name.toLocal8Bit().constData(), "quality") == 0) {
+ return QVariant(quality());
+ }
+ else if(qstrcmp(name.toLocal8Bit().constData(), "channels") == 0) {
+ return QVariant(fmt.channels());
+ }
+ else if(qstrcmp(name.toLocal8Bit().constData(), "samplerate") == 0) {
+ return QVariant(fmt.frequency());
+ }
+ }
+ return QVariant();
+}
+
+void S60AudioEncoderControl::setEncodingOption(
+ const QString &codec, const QString &name, const QVariant &value)
+{
+ DP0("S60AudioEncoderControl::setEncodingOption +++");
+
+ if (codec == "PCM") {
+ QAudioFormat fmt = m_session->format();
+
+ if(qstrcmp(name.toLocal8Bit().constData(), "quality") == 0) {
+ setQuality((QtMultimediaKit::EncodingQuality)value.toInt(), fmt);
+ } else if(qstrcmp(name.toLocal8Bit().constData(), "channels") == 0) {
+ fmt.setChannels(value.toInt());
+ } else if(qstrcmp(name.toLocal8Bit().constData(), "samplerate") == 0) {
+ fmt.setFrequency(value.toInt());
+ }
+ m_session->setFormat(fmt);
+ }
+
+ DP0("S60AudioEncoderControl::setEncodingOption ---");
+}
+
+QList<int> S60AudioEncoderControl::supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous) const
+{
+ DP0("S60AudioEncoderControl::supportedSampleRates");
+
+ if (continuous)
+ *continuous = false;
+
+ return m_session->supportedAudioSampleRates(settings);
+}
+
+QAudioEncoderSettings S60AudioEncoderControl::audioSettings() const
+{
+ DP0("S60AudioEncoderControl::audioSettings");
+
+ return m_settings;
+}
+
+void S60AudioEncoderControl::setAudioSettings(const QAudioEncoderSettings &settings)
+{
+ DP0("S60AudioEncoderControl::setAudioSettings +++");
+
+ QAudioFormat fmt = m_session->format();
+ if (settings.encodingMode() == QtMultimediaKit::ConstantQualityEncoding) {
+ fmt.setCodec(settings.codec());
+ setQuality(settings.quality(), fmt);
+ if (settings.sampleRate() > 0) {
+ fmt.setFrequency(settings.sampleRate());
+ }
+ if (settings.channelCount() > 0)
+ fmt.setChannels(settings.channelCount());
+ }else {
+ if (settings.sampleRate() == 8000) {
+ fmt.setSampleType(QAudioFormat::UnSignedInt);
+ fmt.setSampleSize(8);
+ } else {
+ fmt.setSampleType(QAudioFormat::SignedInt);
+ fmt.setSampleSize(16);
+ }
+ fmt.setCodec(settings.codec());
+ fmt.setFrequency(settings.sampleRate());
+ fmt.setChannels(settings.channelCount());
+ }
+ m_session->setFormat(fmt);
+ m_session->setEncoderSettings(settings);
+ m_settings = settings;
+
+ DP0("S60AudioEncoderControl::setAudioSettings ---");
+}
diff --git a/src/plugins/symbian/mmf/audiosource/s60audioencodercontrol.h b/src/plugins/symbian/mmf/audiosource/s60audioencodercontrol.h
new file mode 100644
index 000000000..236d7d522
--- /dev/null
+++ b/src/plugins/symbian/mmf/audiosource/s60audioencodercontrol.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** 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$
+** 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 AUDIOENCODERCONTROL_H
+#define AUDIOENCODERCONTROL_H
+
+#include <qaudioencodercontrol.h>
+#include <QtCore/qstringlist.h>
+#include "qaudioformat.h"
+
+QT_USE_NAMESPACE
+
+class S60AudioCaptureSession;
+
+class S60AudioEncoderControl : public QAudioEncoderControl
+{
+ Q_OBJECT
+public:
+ S60AudioEncoderControl(QObject *session, QObject *parent = 0);
+ virtual ~S60AudioEncoderControl();
+
+ QStringList supportedAudioCodecs() const;
+ QString codecDescription(const QString &codecName) const;
+
+ QList<int> supportedSampleRates(const QAudioEncoderSettings &settings, bool *continuous = 0) const;
+
+ QAudioEncoderSettings audioSettings() const;
+ void setAudioSettings(const QAudioEncoderSettings&);
+
+ QStringList supportedEncodingOptions(const QString &codec) const;
+ QVariant encodingOption(const QString &codec, const QString &name) const;
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
+
+private:
+ QtMultimediaKit::EncodingQuality quality() const;
+ void setQuality(QtMultimediaKit::EncodingQuality, QAudioFormat &format);
+
+private:
+ S60AudioCaptureSession* m_session;
+ QAudioEncoderSettings m_settings;
+ QtMultimediaKit::EncodingQuality m_quality;
+};
+
+#endif
diff --git a/src/plugins/symbian/mmf/audiosource/s60audioendpointselector.cpp b/src/plugins/symbian/mmf/audiosource/s60audioendpointselector.cpp
new file mode 100644
index 000000000..a2f909316
--- /dev/null
+++ b/src/plugins/symbian/mmf/audiosource/s60audioendpointselector.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "DebugMacros.h"
+
+#include "s60audiocapturesession.h"
+#include "s60audioendpointselector.h"
+
+#include <qaudiodeviceinfo.h>
+
+S60AudioEndpointSelector::S60AudioEndpointSelector(QObject *session, QObject *parent)
+ :QAudioEndpointSelector(parent)
+{
+ DP0("S60AudioEndpointSelector::S60AudioEndpointSelector +++");
+ m_session = qobject_cast<S60AudioCaptureSession*>(session);
+
+ connect(m_session, SIGNAL(activeEndpointChanged(const QString &)), this, SIGNAL(activeEndpointChanged(const QString &)));
+
+ DP0("S60AudioEndpointSelector::S60AudioEndpointSelector ---");
+}
+
+S60AudioEndpointSelector::~S60AudioEndpointSelector()
+{
+ DP0("S60AudioEndpointSelector::~S60AudioEndpointSelector +++");
+
+ DP0("S60AudioEndpointSelector::~S60AudioEndpointSelector ---");
+}
+
+QList<QString> S60AudioEndpointSelector::availableEndpoints() const
+{
+ DP0("S60AudioEndpointSelector::availableEndpoints");
+
+ return m_session->availableEndpoints();
+}
+
+QString S60AudioEndpointSelector::endpointDescription(const QString& name) const
+{
+ DP0("S60AudioEndpointSelector::endpointDescription");
+
+ return m_session->endpointDescription(name);
+}
+
+QString S60AudioEndpointSelector::defaultEndpoint() const
+{
+ DP0("S60AudioEndpointSelector::defaultEndpoint");
+
+ return m_session->defaultEndpoint();
+}
+
+QString S60AudioEndpointSelector::activeEndpoint() const
+{
+ DP0("S60AudioEndpointSelector::activeEndpoint");
+
+ return m_session->activeEndpoint();
+}
+
+void S60AudioEndpointSelector::setActiveEndpoint(const QString& name)
+{
+ DP0("S60AudioEndpointSelector::setActiveEndpoint +++");
+ m_session->setActiveEndpoint(name);
+ DP0("S60AudioEndpointSelector::setActiveEndpoint ---");
+}
diff --git a/src/plugins/symbian/mmf/audiosource/s60audioendpointselector.h b/src/plugins/symbian/mmf/audiosource/s60audioendpointselector.h
new file mode 100644
index 000000000..d89ce8765
--- /dev/null
+++ b/src/plugins/symbian/mmf/audiosource/s60audioendpointselector.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60AUDIOENDPOINTSELECTOR_H
+#define S60AUDIOENDPOINTSELECTOR_H
+
+#include <QStringList>
+
+#include <qaudioendpointselector.h>
+
+QT_USE_NAMESPACE
+
+class S60AudioCaptureSession;
+
+class S60AudioEndpointSelector : public QAudioEndpointSelector
+{
+
+Q_OBJECT
+
+public:
+ S60AudioEndpointSelector(QObject *session, QObject *parent = 0);
+ ~S60AudioEndpointSelector();
+
+ QList<QString> availableEndpoints() const;
+ QString endpointDescription(const QString& name) const;
+ QString defaultEndpoint() const;
+ QString activeEndpoint() const;
+
+
+public Q_SLOTS:
+ void setActiveEndpoint(const QString& name);
+
+private:
+
+ S60AudioCaptureSession* m_session;
+};
+
+#endif // S60AUDIOENDPOINTSELECTOR_H
diff --git a/src/plugins/symbian/mmf/audiosource/s60audiomediarecordercontrol.cpp b/src/plugins/symbian/mmf/audiosource/s60audiomediarecordercontrol.cpp
new file mode 100644
index 000000000..5d80033b3
--- /dev/null
+++ b/src/plugins/symbian/mmf/audiosource/s60audiomediarecordercontrol.cpp
@@ -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$
+** 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 "DebugMacros.h"
+
+#include "s60audiomediarecordercontrol.h"
+#include "s60audiocapturesession.h"
+
+#include <QtCore/qdebug.h>
+
+S60AudioMediaRecorderControl::S60AudioMediaRecorderControl(QObject *session, QObject *parent)
+ :QMediaRecorderControl(parent), m_state(QMediaRecorder::StoppedState)
+{
+ DP0("S60AudioMediaRecorderControl::S60AudioMediaRecorderControl +++");
+
+ m_session = qobject_cast<S60AudioCaptureSession*>(session);
+ connect(m_session, SIGNAL(positionChanged(qint64)), this, SIGNAL(durationChanged(qint64)));
+ connect(m_session, SIGNAL(stateChanged(S60AudioCaptureSession::TAudioCaptureState)), this, SLOT(updateState(S60AudioCaptureSession::TAudioCaptureState)));
+ connect(m_session,SIGNAL(error(int,const QString &)),this,SIGNAL(error(int,const QString &)));
+
+ DP0("S60AudioMediaRecorderControl::S60AudioMediaRecorderControl ---");
+}
+
+S60AudioMediaRecorderControl::~S60AudioMediaRecorderControl()
+{
+ DP0("S60AudioMediaRecorderControl::~S60AudioMediaRecorderControl +++");
+
+ DP0("S60AudioMediaRecorderControl::~S60AudioMediaRecorderControl - - ");
+}
+
+QUrl S60AudioMediaRecorderControl::outputLocation() const
+{
+ DP0("S60AudioMediaRecorderControl::outputLocation");
+
+ return m_session->outputLocation();
+}
+
+bool S60AudioMediaRecorderControl::setOutputLocation(const QUrl& sink)
+{
+ DP0("S60AudioMediaRecorderControl::setOutputLocation");
+
+ return m_session->setOutputLocation(sink);
+}
+
+QMediaRecorder::State S60AudioMediaRecorderControl::convertState(S60AudioCaptureSession::TAudioCaptureState aState) const
+{
+ DP0("S60AudioMediaRecorderControl::convertState +++");
+
+ QMediaRecorder::State state = QMediaRecorder::StoppedState;;
+ switch (aState) {
+ case S60AudioCaptureSession::ERecording:
+ state = QMediaRecorder::RecordingState;
+ break;
+ case S60AudioCaptureSession::EPaused:
+ state = QMediaRecorder::PausedState;
+ break;
+ case S60AudioCaptureSession::ERecordComplete:
+ case S60AudioCaptureSession::ENotInitialized:
+ case S60AudioCaptureSession::EOpenCompelete:
+ case S60AudioCaptureSession::EInitialized:
+ state = QMediaRecorder::StoppedState;
+ break;
+ }
+
+ DP1("S60AudioMediaRecorderControl::convertState:", state);
+
+ DP0("S60AudioMediaRecorderControl::convertState ---");
+
+ return state;
+}
+
+void S60AudioMediaRecorderControl::updateState(S60AudioCaptureSession::TAudioCaptureState aState)
+{
+ DP0("S60AudioMediaRecorderControl::updateState +++");
+
+ QMediaRecorder::State newState = convertState(aState);
+ if (m_state != newState) {
+ m_state = newState;
+ emit stateChanged(m_state);
+ }
+
+ DP0("S60AudioMediaRecorderControl::updateState ---");
+}
+
+QMediaRecorder::State S60AudioMediaRecorderControl::state() const
+{
+ DP0("S60AudioMediaRecorderControl::state");
+
+ return m_state;
+}
+
+qint64 S60AudioMediaRecorderControl::duration() const
+{
+ // DP0("S60AudioMediaRecorderControl::duration +++");
+
+ return m_session->position();
+}
+
+void S60AudioMediaRecorderControl::record()
+{
+ DP0("S60AudioMediaRecorderControl::record +++");
+
+ m_session->record();
+
+ DP0("S60AudioMediaRecorderControl::record ---");
+}
+
+void S60AudioMediaRecorderControl::pause()
+{
+ DP0("S60AudioMediaRecorderControl::pause +++");
+
+ m_session->pause();
+
+ DP0("S60AudioMediaRecorderControl::pause ---");
+}
+
+void S60AudioMediaRecorderControl::stop()
+{
+ DP0("S60AudioMediaRecorderControl::stop +++");
+
+ m_session->stop();
+
+ DP0("S60AudioMediaRecorderControl::stop ---");
+}
+
+bool S60AudioMediaRecorderControl::isMuted() const
+{
+ DP0("S60AudioMediaRecorderControl::isMuted");
+
+ return m_session->muted();
+}
+
+void S60AudioMediaRecorderControl::setMuted(bool muted)
+{
+ DP0("S60AudioMediaRecorderControl::setMuted +++");
+
+ DP1("S60AudioMediaRecorderControl::setMuted:", muted);
+
+ m_session->mute(muted);
+
+ DP0("S60AudioMediaRecorderControl::setMuted +++");
+}
diff --git a/src/plugins/symbian/mmf/audiosource/s60audiomediarecordercontrol.h b/src/plugins/symbian/mmf/audiosource/s60audiomediarecordercontrol.h
new file mode 100644
index 000000000..78e8f4870
--- /dev/null
+++ b/src/plugins/symbian/mmf/audiosource/s60audiomediarecordercontrol.h
@@ -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$
+** 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 S60AUDIOMEDIARECORDERCONTROL_H
+#define S60AUDIOMEDIARECORDERCONTROL_H
+
+#include <QtCore/qobject.h>
+#include <QUrl>
+
+#include "qmediarecorder.h"
+#include "qmediarecordercontrol.h"
+
+#include "s60audiocapturesession.h"
+
+QT_USE_NAMESPACE
+
+//class S60AudioCaptureSession;
+
+class S60AudioMediaRecorderControl : public QMediaRecorderControl
+{
+ Q_OBJECT
+public:
+ S60AudioMediaRecorderControl(QObject *session,QObject *parent = 0);
+ ~S60AudioMediaRecorderControl();
+
+ QUrl outputLocation() const;
+ bool setOutputLocation(const QUrl &sink);
+
+ QMediaRecorder::State state() const;
+
+ qint64 duration() const;
+
+ bool isMuted() const;
+
+ void applySettings() {}
+
+private:
+ QMediaRecorder::State convertState(S60AudioCaptureSession::TAudioCaptureState aState) const;
+
+public slots:
+ void record();
+ void pause();
+ void stop();
+ void setMuted(bool);
+
+private slots:
+ void updateState(S60AudioCaptureSession::TAudioCaptureState aState);
+
+private:
+ S60AudioCaptureSession* m_session;
+ QMediaRecorder::State m_state;
+};
+
+#endif
diff --git a/src/plugins/symbian/mmf/inc/DebugMacros.h b/src/plugins/symbian/mmf/inc/DebugMacros.h
new file mode 100644
index 000000000..449bef088
--- /dev/null
+++ b/src/plugins/symbian/mmf/inc/DebugMacros.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qdebug.h>
+
+#ifndef __DEBUGMACROS_H__
+#define __DEBUGMACROS_H__
+
+// MACROS
+#ifdef _DEBUG
+#define DP0(string) qDebug()<<string
+#define DP1(string,arg1) qDebug()<<string<<arg1
+#define DP2(string,arg1,arg2) qDebug()<<string<<arg1<<arg2
+#define DP3(string,arg1,arg2,arg3) qDebug()<<string<<arg1<<arg2<<arg3
+#define DP4(string,arg1,arg2,arg3,arg4) qDebug()<<string<<arg1<<arg2<<arg3<<arg4
+#define DP5(string,arg1,arg2,arg3,arg4,arg5) qDebug()<<string<<arg1<<arg2<<arg3<<arg4<<arg5
+#define DP6(string,arg1,arg2,arg3,arg4,arg5,arg6) qDebug()<<string<<arg1<<arg2<<arg3<<arg4<<arg5<<arg6
+#else
+#define DP0(string)
+#define DP1(string,arg1)
+#define DP2(string,arg1,arg2)
+#define DP3(string,arg1,arg2,arg3)
+#define DP4(string,arg1,arg2,arg3,arg4)
+#define DP5(string,arg1,arg2,arg3,arg4,arg5)
+#define DP6(string,arg1,arg2,arg3,arg4,arg5,arg6)
+#endif
+
+#endif //__DEBUGMACROS_H__
diff --git a/src/plugins/symbian/mmf/mediaplayer/mediaplayer_s60.pri b/src/plugins/symbian/mmf/mediaplayer/mediaplayer_s60.pri
new file mode 100644
index 000000000..6ec64e2b6
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/mediaplayer_s60.pri
@@ -0,0 +1,92 @@
+INCLUDEPATH += $$PWD
+
+include (../../videooutput/videooutput.pri)
+
+LIBS *= -lmediaclientvideo \
+ -lmediaclientaudio \
+ -lws32 \
+ -lfbscli \
+ -lcone \
+ -lmmfcontrollerframework \
+ -lefsrv \
+ -lbitgdi \
+ -lapgrfx \
+ -lapmime \
+ -lcommdb \
+ -lbafl
+
+# If support to DRM is wanted then comment out the following line
+#CONFIG += drm_supported
+
+# We are building Symbian backend with media player support
+DEFINES += HAS_MEDIA_PLAYER
+# We are building media player with QVideoRendererControl support
+#DEFINES += HAS_VIDEORENDERERCONTROL_IN_VIDEOPLAYER
+
+drm_supported {
+ LIBS += -ldrmaudioplayutility
+ DEFINES += S60_DRM_SUPPORTED
+}
+
+HEADERS += \
+ $$PWD/s60mediaplayercontrol.h \
+ $$PWD/s60mediaplayerservice.h \
+ $$PWD/s60mediaplayersession.h \
+ $$PWD/s60mediametadataprovider.h \
+ $$PWD/s60videoplayersession.h \
+ $$PWD/s60videosurface.h \
+ $$PWD/s60mediarecognizer.h \
+ $$PWD/s60audioplayersession.h \
+ $$PWD/ms60mediaplayerresolver.h \
+ $$PWD/s60mediaplayeraudioendpointselector.h \
+ $$PWD/s60mediastreamcontrol.h \
+ $$PWD/s60medianetworkaccesscontrol.h
+
+SOURCES += \
+ $$PWD/s60mediaplayercontrol.cpp \
+ $$PWD/s60mediaplayerservice.cpp \
+ $$PWD/s60mediaplayersession.cpp \
+ $$PWD/s60mediametadataprovider.cpp \
+ $$PWD/s60videoplayersession.cpp \
+ $$PWD/s60videosurface.cpp \
+ $$PWD/s60mediarecognizer.cpp \
+ $$PWD/s60audioplayersession.cpp \
+ $$PWD/s60mediaplayeraudioendpointselector.cpp \
+ $$PWD/s60mediastreamcontrol.cpp \
+ $$PWD/s60medianetworkaccesscontrol.cpp
+
+contains(DEFINES, HAS_VIDEORENDERERCONTROL_IN_VIDEOPLAYER) {
+ HEADERS += $$PWD/s60videorenderer.h
+ SOURCES += $$PWD/s60videorenderer.cpp
+}
+
+contains(S60_VERSION, 3.1) {
+ #3.1 doesn't provide audio routing in videoplayer
+ contains(audiorouting_s60_enabled,yes) {
+ MMP_RULES += "$${LITERAL_HASH}ifndef WINSCW" \
+ "MACRO HAS_AUDIOROUTING" \
+ "LIBRARY audiooutputrouting.lib" \
+ "$${LITERAL_HASH}endif"
+ message("Note: AudioOutput Routing API not supported for 3.1 winscw target and in videoplayer")
+ }
+
+} else {
+ contains(audiorouting_s60_enabled,yes) {
+ #We use audiooutputrouting.lib for directing audio output to speaker/earspeaker
+ DEFINES += HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ DEFINES += HAS_AUDIOROUTING
+ message("Audiorouting_s60 enabled for post 3.1 sdk")
+ LIBS += -laudiooutputrouting
+ }
+
+}
+
+contains(S60_VERSION, 3.1) {
+ DEFINES += PLAY_RATE_NOT_SUPPORTED
+ message("S60 version 3.1 does not support setplaybackrate")
+}
+contains(S60_VERSION, 3.2) {
+ DEFINES += PLAY_RATE_NOT_SUPPORTED
+ message("S60 version 3.2 does not support setplaybackrate")
+}
+
diff --git a/src/plugins/symbian/mmf/mediaplayer/ms60mediaplayerresolver.h b/src/plugins/symbian/mmf/mediaplayer/ms60mediaplayerresolver.h
new file mode 100644
index 000000000..d836dae3e
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/ms60mediaplayerresolver.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** 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$
+** 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 MS60MEDIAPLAYERRESOLVER_H
+#define MS60MEDIAPLAYERRESOLVER_H
+
+class S60MediaPlayerSession;
+
+class MS60MediaPlayerResolver
+{
+ public:
+ virtual S60MediaPlayerSession* PlayerSession() = 0;
+ virtual S60MediaPlayerSession* VideoPlayerSession() = 0;
+ virtual S60MediaPlayerSession* AudioPlayerSession() = 0;
+};
+
+#endif
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60audioplayersession.cpp b/src/plugins/symbian/mmf/mediaplayer/s60audioplayersession.cpp
new file mode 100644
index 000000000..3a5386ce1
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60audioplayersession.cpp
@@ -0,0 +1,577 @@
+/****************************************************************************
+**
+** 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$
+** 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 "DebugMacros.h"
+
+#include "s60audioplayersession.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qvariant.h>
+
+/*!
+ Constructs the CMdaAudioPlayerUtility object with given \a parent QObject.
+
+ And Registers for Audio Loading Notifications.
+
+*/
+
+S60AudioPlayerSession::S60AudioPlayerSession(QObject *parent)
+ : S60MediaPlayerSession(parent)
+ , m_player(0)
+ , m_audioEndpoint("Default")
+{
+ DP0("S60AudioPlayerSession::S60AudioPlayerSession +++");
+
+#ifdef HAS_AUDIOROUTING
+ m_audioOutput = 0;
+#endif //HAS_AUDIOROUTING
+ QT_TRAP_THROWING(m_player = CAudioPlayer::NewL(*this, 0, EMdaPriorityPreferenceNone));
+ m_player->RegisterForAudioLoadingNotification(*this);
+
+ DP0("S60AudioPlayerSession::S60AudioPlayerSession ---");
+}
+
+
+/*!
+ Destroys the CMdaAudioPlayerUtility object.
+
+ And Unregister the observer.
+
+*/
+
+S60AudioPlayerSession::~S60AudioPlayerSession()
+{
+ DP0("S60AudioPlayerSession::~S60AudioPlayerSession +++");
+#ifdef HAS_AUDIOROUTING
+ if (m_audioOutput)
+ m_audioOutput->UnregisterObserver(*this);
+ delete m_audioOutput;
+#endif
+ m_player->Close();
+ delete m_player;
+
+ DP0("S60AudioPlayerSession::~S60AudioPlayerSession ---");
+}
+
+/*!
+
+ Opens the a file from \a path.
+
+*/
+
+void S60AudioPlayerSession::doLoadL(const TDesC &path)
+{
+ DP0("S60AudioPlayerSession::doLoadL +++");
+
+#ifdef HAS_AUDIOROUTING
+ // m_audioOutput needs to be reinitialized after MapcInitComplete
+ if (m_audioOutput)
+ m_audioOutput->UnregisterObserver(*this);
+ delete m_audioOutput;
+ m_audioOutput = NULL;
+#endif //HAS_AUDIOROUTING
+ m_player->OpenFileL(path);
+
+ DP0("S60AudioPlayerSession::doLoadL ---");
+}
+
+/*!
+
+ Returns the duration of the audio sample in microseconds.
+
+*/
+
+qint64 S60AudioPlayerSession::doGetDurationL() const
+{
+ // DP0("S60AudioPlayerSession::doGetDurationL");
+
+ return m_player->Duration().Int64() / qint64(1000);
+}
+
+/*!
+ * Returns the current playback position in microseconds from the start of the clip.
+
+*/
+
+qint64 S60AudioPlayerSession::doGetPositionL() const
+{
+ // DP0("S60AudioPlayerSession::doGetPositionL");
+
+ TTimeIntervalMicroSeconds ms = 0;
+ m_player->GetPosition(ms);
+ return ms.Int64() / qint64(1000);
+}
+
+/*!
+ Returns TRUE if Video available or else FALSE
+ */
+
+bool S60AudioPlayerSession::isVideoAvailable()
+{
+ DP0("S60AudioPlayerSession::isVideoAvailable");
+
+ return false;
+}
+
+/*!
+ Returns TRUE if Audio available or else FALSE
+ */
+bool S60AudioPlayerSession::isAudioAvailable()
+{
+ DP0("S60AudioPlayerSession::isAudioAvailable");
+
+ return true; // this is a bit happy scenario, but we do emit error that we can't play
+}
+
+/*!
+ Starts loading Media and sets media status to Buffering.
+
+ */
+
+void S60AudioPlayerSession::MaloLoadingStarted()
+{
+ DP0("S60AudioPlayerSession::MaloLoadingStarted +++");
+
+ buffering();
+
+ DP0("S60AudioPlayerSession::MaloLoadingStarted ---");
+}
+
+
+/*!
+ Indicates loading Media is completed.
+
+ And sets media status to Buffered.
+
+ */
+
+void S60AudioPlayerSession::MaloLoadingComplete()
+{
+ DP0("S60AudioPlayerSession::MaloLoadingComplete +++");
+
+ buffered();
+
+ DP0("S60AudioPlayerSession::MaloLoadingComplete ---");
+}
+
+/*!
+ Start or resume playing the current source.
+*/
+
+void S60AudioPlayerSession::doPlay()
+{
+ DP0("S60AudioPlayerSession::doPlay +++");
+
+ // For some reason loading progress callback are not called on emulator
+ // Same is the case with hardware. Will be fixed as part of QTMOBILITY-782.
+
+ //#ifdef __WINSCW__
+ buffering();
+ //#endif
+ m_player->Play();
+ //#ifdef __WINSCW__
+ buffered();
+ //#endif
+
+ DP0("S60AudioPlayerSession::doPlay ---");
+}
+
+
+/*!
+ Pause playing the current source.
+*/
+
+
+void S60AudioPlayerSession::doPauseL()
+{
+ DP0("S60AudioPlayerSession::doPauseL +++");
+
+ m_player->Pause();
+
+ DP0("S60AudioPlayerSession::doPauseL ---");
+}
+
+
+/*!
+
+ Stop playing, and reset the play position to the beginning.
+*/
+
+void S60AudioPlayerSession::doStop()
+{
+ DP0("S60AudioPlayerSession::doStop +++");
+
+ m_player->Stop();
+
+ DP0("S60AudioPlayerSession::doStop ---");
+}
+
+/*!
+ Closes the current audio clip (allowing another clip to be opened)
+*/
+
+void S60AudioPlayerSession::doClose()
+{
+ DP0("S60AudioPlayerSession::doClose +++");
+
+#ifdef HAS_AUDIOROUTING
+ if (m_audioOutput) {
+ m_audioOutput->UnregisterObserver(*this);
+ delete m_audioOutput;
+ m_audioOutput = NULL;
+ }
+#endif
+ m_player->Close();
+
+ DP0("S60AudioPlayerSession::doClose ---");
+}
+
+/*!
+
+ Changes the current playback volume to specified \a value.
+*/
+
+void S60AudioPlayerSession::doSetVolumeL(int volume)
+{
+ DP0("S60AudioPlayerSession::doSetVolumeL +++");
+
+ DP1("S60AudioPlayerSession::doSetVolumeL, Volume:", volume);
+
+ m_player->SetVolume(volume * m_player->MaxVolume() / 100);
+
+ DP0("S60AudioPlayerSession::doSetVolumeL ---");
+}
+
+/*!
+ Sets the current playback position to \a microSeconds from the start of the clip.
+*/
+
+void S60AudioPlayerSession::doSetPositionL(qint64 microSeconds)
+{
+ DP0("S60AudioPlayerSession::doSetPositionL +++");
+
+ DP1("S60AudioPlayerSession::doSetPositionL, Microseconds:", microSeconds);
+
+ m_player->SetPosition(TTimeIntervalMicroSeconds(microSeconds));
+
+ DP0("S60AudioPlayerSession::doSetPositionL ---");
+}
+
+/*!
+
+ Updates meta data entries in the current audio clip.
+*/
+
+void S60AudioPlayerSession::updateMetaDataEntriesL()
+{
+ DP0("S60AudioPlayerSession::updateMetaDataEntriesL +++");
+
+ metaDataEntries().clear();
+ int numberOfMetaDataEntries = 0;
+
+ //User::LeaveIfError(m_player->GetNumberOfMetaDataEntries(numberOfMetaDataEntries));
+ m_player->GetNumberOfMetaDataEntries(numberOfMetaDataEntries);
+
+ for (int i = 0; i < numberOfMetaDataEntries; i++) {
+ CMMFMetaDataEntry *entry = NULL;
+ entry = m_player->GetMetaDataEntryL(i);
+ metaDataEntries().insert(QString::fromUtf16(entry->Name().Ptr(), entry->Name().Length()), QString::fromUtf16(entry->Value().Ptr(), entry->Value().Length()));
+ delete entry;
+ }
+ emit metaDataChanged();
+
+ DP0("S60AudioPlayerSession::updateMetaDataEntriesL ---");
+}
+
+/*!
+ Sets the playbackRate with \a rate.
+*/
+
+void S60AudioPlayerSession::setPlaybackRate(qreal rate)
+{
+ DP0("S60AudioPlayerSession::setPlaybackRate +++");
+ DP1("S60AudioPlayerSession::setPlaybackRate, Rate:", rate);
+ /*Since AudioPlayerUtility doesn't support set playback rate hence
+ * setPlaybackRate emits playbackRateChanged signal for 1.0x ie normal playback.
+ * For all other playBackRates it sets and emits error signal.
+ */
+ if (rate == 1.0) {
+ emit playbackRateChanged(rate);
+ return;
+ } else {
+ int err = KErrNotSupported;
+ setAndEmitError(err);
+ }
+ DP0("S60AudioPlayerSession::setPlaybackRate ---");
+}
+
+/*!
+
+ Returns the percentage of the audio clip loaded.
+*/
+
+int S60AudioPlayerSession::doGetBufferStatusL() const
+{
+ DP0("S60AudioPlayerSession::doGetBufferStatusL +++");
+
+ int progress = 0;
+ m_player->GetAudioLoadingProgressL(progress);
+
+ DP0("S60AudioPlayerSession::doGetBufferStatusL ---");
+
+ return progress;
+}
+
+/*!
+
+ Defines required client behaviour when an attempt to open and initialise an audio sample has completed,
+ successfully or not.
+
+ \a aError if KErrNone the sample is ready to play or else system wide error.
+
+ \a aDuration The duration of the audio sample.
+*/
+
+#ifdef S60_DRM_SUPPORTED
+void S60AudioPlayerSession::MdapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration)
+#else
+void S60AudioPlayerSession::MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration)
+#endif
+{
+ DP0("S60AudioPlayerSession::MdapcInitComplete +++");
+
+ DP1("S60AudioPlayerSession::MdapcInitComplete - aError", aError);
+
+ Q_UNUSED(aDuration);
+ setError(aError);
+ if (KErrNone != aError)
+ return;
+#ifdef HAS_AUDIOROUTING
+ TRAPD(err,
+ m_audioOutput = CAudioOutput::NewL(*m_player);
+ m_audioOutput->RegisterObserverL(*this);
+ );
+ setActiveEndpoint(m_audioEndpoint);
+ setError(err);
+#endif //HAS_AUDIOROUTING
+ if (KErrNone == aError)
+ loaded();
+
+ DP0("S60AudioPlayerSession::MdapcInitComplete ---");
+}
+
+/*!
+ Defines required client behaviour when an attempt to playback an audio sample has completed,
+ successfully or not.
+
+ \a aError if KErrNone the playback completed or else system wide error.
+*/
+
+
+#ifdef S60_DRM_SUPPORTED
+void S60AudioPlayerSession::MdapcPlayComplete(TInt aError)
+#else
+void S60AudioPlayerSession::MapcPlayComplete(TInt aError)
+#endif
+{
+ DP0("S60AudioPlayerSession::MdapcPlayComplete +++");
+
+ DP1("S60AudioPlayerSession::MdapcPlayComplete", aError);
+
+ if (KErrNone == aError)
+ endOfMedia();
+ else
+ setError(aError);
+
+ DP0("S60AudioPlayerSession::MdapcPlayComplete ---");
+}
+
+/*!
+ Defiens which Audio End point to use.
+
+ \a audioEndpoint audioEndpoint name.
+*/
+
+void S60AudioPlayerSession::doSetAudioEndpoint(const QString& audioEndpoint)
+{
+ DP0("S60AudioPlayerSession::doSetAudioEndpoint +++");
+
+ DP1("S60AudioPlayerSession::doSetAudioEndpoint - ", audioEndpoint);
+
+ m_audioEndpoint = audioEndpoint;
+
+ DP0("S60AudioPlayerSession::doSetAudioEndpoint ---");
+}
+
+/*!
+
+ Returns audioEndpoint name.
+*/
+
+QString S60AudioPlayerSession::activeEndpoint() const
+{
+ DP0("S60AudioPlayerSession::activeEndpoint +++");
+
+ QString outputName = QString("Default");
+#ifdef HAS_AUDIOROUTING
+ if (m_audioOutput) {
+ CAudioOutput::TAudioOutputPreference output = m_audioOutput->AudioOutput();
+ outputName = qStringFromTAudioOutputPreference(output);
+ }
+#endif
+ DP1("S60AudioPlayerSession::activeEndpoint is :", outputName);
+
+ DP0("S60AudioPlayerSession::activeEndpoint ---");
+ return outputName;
+}
+
+/*!
+ * Returns default Audio End point in use.
+*/
+
+QString S60AudioPlayerSession::defaultEndpoint() const
+{
+ DP0("S60AudioPlayerSession::defaultEndpoint +++");
+
+ QString outputName = QString("Default");
+#ifdef HAS_AUDIOROUTING
+ if (m_audioOutput) {
+ CAudioOutput::TAudioOutputPreference output = m_audioOutput->DefaultAudioOutput();
+ outputName = qStringFromTAudioOutputPreference(output);
+ }
+#endif
+ DP1("S60AudioPlayerSession::defaultEndpoint is :", outputName);
+
+ DP0("S60AudioPlayerSession::defaultEndpoint ---");
+ return outputName;
+}
+
+/*!
+ Sets active end \a name as an Audio End point.
+*/
+
+void S60AudioPlayerSession::setActiveEndpoint(const QString& name)
+{
+ DP0("S60AudioPlayerSession::setActiveEndpoint +++");
+
+ DP1("S60AudioPlayerSession::setActiveEndpoint - ", name);
+
+#ifdef HAS_AUDIOROUTING
+ CAudioOutput::TAudioOutputPreference output = CAudioOutput::ENoPreference;
+
+ if (name == QString("Default"))
+ output = CAudioOutput::ENoPreference;
+ else if (name == QString("All"))
+ output = CAudioOutput::EAll;
+ else if (name == QString("None"))
+ output = CAudioOutput::ENoOutput;
+ else if (name == QString("Earphone"))
+ output = CAudioOutput::EPrivate;
+ else if (name == QString("Speaker"))
+ output = CAudioOutput::EPublic;
+
+ if (m_audioOutput) {
+ TRAPD(err, m_audioOutput->SetAudioOutputL(output));
+ setError(err);
+ }
+#endif
+
+ DP0("S60AudioPlayerSession::setActiveEndpoint ---");
+}
+
+/*!
+ The default audio output has been changed.
+
+ \a aAudioOutput Audio Output object.
+
+ \a aNewDefault is CAudioOutput::TAudioOutputPreference.
+*/
+
+
+#ifdef HAS_AUDIOROUTING
+void S60AudioPlayerSession::DefaultAudioOutputChanged(CAudioOutput& aAudioOutput,
+ CAudioOutput::TAudioOutputPreference aNewDefault)
+{
+ DP0("S60AudioPlayerSession::DefaultAudioOutputChanged +++");
+
+ // Emit already implemented in setActiveEndpoint function
+ Q_UNUSED(aAudioOutput)
+ Q_UNUSED(aNewDefault)
+
+ DP0("S60AudioPlayerSession::DefaultAudioOutputChanged ---");
+}
+
+
+/*!
+ Converts CAudioOutput::TAudioOutputPreference enum to QString.
+
+ \a output is CAudioOutput::TAudioOutputPreference enum value.
+
+*/
+
+QString S60AudioPlayerSession::qStringFromTAudioOutputPreference(CAudioOutput::TAudioOutputPreference output) const
+{
+ DP0("S60AudioPlayerSession::qStringFromTAudioOutputPreference");
+
+ if (output == CAudioOutput::ENoPreference)
+ return QString("Default");
+ else if (output == CAudioOutput::EAll)
+ return QString("All");
+ else if (output == CAudioOutput::ENoOutput)
+ return QString("None");
+ else if (output == CAudioOutput::EPrivate)
+ return QString("Earphone");
+ else if (output == CAudioOutput::EPublic)
+ return QString("Speaker");
+ return QString("Default");
+}
+#endif
+
+/*!
+ Return True if its Seekable or else False.
+*/
+
+bool S60AudioPlayerSession::getIsSeekable() const
+{
+ DP0("S60AudioPlayerSession::getIsSeekable");
+
+ return ETrue;
+}
+
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60audioplayersession.h b/src/plugins/symbian/mmf/mediaplayer/s60audioplayersession.h
new file mode 100644
index 000000000..80228ef0a
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60audioplayersession.h
@@ -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$
+** 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 S60AUDIOPLAYERSESSION_H
+#define S60AUDIOPLAYERSESSION_H
+
+#include <QtCore/qobject.h>
+#include "s60mediaplayersession.h"
+
+#ifdef S60_DRM_SUPPORTED
+#include <drmaudiosampleplayer.h>
+typedef CDrmPlayerUtility CAudioPlayer;
+typedef MDrmAudioPlayerCallback MAudioPlayerObserver;
+#else
+#include <mdaaudiosampleplayer.h>
+typedef CMdaAudioPlayerUtility CAudioPlayer;
+typedef MMdaAudioPlayerCallback MAudioPlayerObserver;
+#endif
+
+#ifdef HAS_AUDIOROUTING
+#include <AudioOutput.h>
+#include <MAudioOutputObserver.h>
+#endif //HAS_AUDIOROUTING
+
+class S60AudioPlayerSession : public S60MediaPlayerSession
+ , public MAudioPlayerObserver
+ , public MAudioLoadingObserver
+#ifdef HAS_AUDIOROUTING
+ , public MAudioOutputObserver
+#endif
+{
+ Q_OBJECT
+public:
+ S60AudioPlayerSession(QObject *parent);
+ ~S60AudioPlayerSession();
+
+ //From S60MediaPlayerSession
+ bool isVideoAvailable();
+ bool isAudioAvailable();
+
+ // From MAudioLoadingObserver
+ void MaloLoadingStarted();
+ void MaloLoadingComplete();
+
+#ifdef HAS_AUDIOROUTING
+ // From MAudioOutputObserver
+ void DefaultAudioOutputChanged( CAudioOutput& aAudioOutput,
+ CAudioOutput::TAudioOutputPreference aNewDefault );
+#endif //HAS_AUDIOROUTING
+
+public:
+ // From S60MediaPlayerAudioEndpointSelector
+ QString activeEndpoint() const;
+ QString defaultEndpoint() const;
+ void setPlaybackRate(qreal rate);
+public Q_SLOTS:
+ void setActiveEndpoint(const QString& name);
+
+protected:
+ //From S60MediaPlayerSession
+ void doLoadL(const TDesC &path);
+ void doLoadUrlL(const TDesC &path){Q_UNUSED(path)/*empty implementation*/}
+ void doPlay();
+ void doStop();
+ void doClose();
+ void doPauseL();
+ void doSetVolumeL(int volume);
+ qint64 doGetPositionL() const;
+ void doSetPositionL(qint64 microSeconds);
+ void updateMetaDataEntriesL();
+ int doGetBufferStatusL() const;
+ qint64 doGetDurationL() const;
+ void doSetAudioEndpoint(const QString& audioEndpoint);
+ bool getIsSeekable() const;
+private:
+#ifdef S60_DRM_SUPPORTED
+ // From MMdaAudioPlayerCallback
+ void MdapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration);
+ void MdapcPlayComplete(TInt aError);
+#else
+ // From MDrmAudioPlayerCallback
+ void MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration);
+ void MapcPlayComplete(TInt aError);
+#endif
+
+#ifdef HAS_AUDIOROUTING
+ QString qStringFromTAudioOutputPreference(CAudioOutput::TAudioOutputPreference output) const;
+#endif //HAS_AUDIOROUTING
+
+private:
+ CAudioPlayer *m_player;
+#ifdef HAS_AUDIOROUTING
+ CAudioOutput *m_audioOutput;
+#endif //HAS_AUDIOROUTING
+ QString m_audioEndpoint;
+};
+
+#endif
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediametadataprovider.cpp b/src/plugins/symbian/mmf/mediaplayer/s60mediametadataprovider.cpp
new file mode 100644
index 000000000..85bfe65a3
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediametadataprovider.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** 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$
+** 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 "DebugMacros.h"
+
+#include "s60mediametadataprovider.h"
+#include "s60mediaplayercontrol.h"
+#include "s60mediaplayersession.h"
+#include <QtCore/qdebug.h>
+
+/*!
+ * Typecasts the \a control object to S60MediaPlayerControl object.
+*/
+S60MediaMetaDataProvider::S60MediaMetaDataProvider(QObject *control, QObject *parent)
+ : QMetaDataReaderControl(parent)
+ , m_control(NULL)
+{
+ DP0("S60MediaMetaDataProvider::S60MediaMetaDataProvider +++");
+
+ m_control = qobject_cast<S60MediaPlayerControl*>(control);
+
+ DP0("S60MediaMetaDataProvider::S60MediaMetaDataProvider ---");
+}
+
+/*!
+ * Destructor
+*/
+
+S60MediaMetaDataProvider::~S60MediaMetaDataProvider()
+{
+ DP0("S60MediaMetaDataProvider::~S60MediaMetaDataProvider +++");
+ DP0("S60MediaMetaDataProvider::~S60MediaMetaDataProvider ---");
+}
+
+/*!
+ * Returns TRUE if MetaData is Available or else FALSE.
+*/
+
+bool S60MediaMetaDataProvider::isMetaDataAvailable() const
+{
+ DP0("S60MediaMetaDataProvider::isMetaDataAvailable");
+
+ if (m_control->session())
+ return m_control->session()->isMetadataAvailable();
+ return false;
+}
+
+/*!
+ * Always returns FLASE.
+*/
+bool S60MediaMetaDataProvider::isWritable() const
+{
+ DP0("S60MediaMetaDataProvider::isWritable");
+
+ return false;
+}
+
+/*!
+ * Returns when \a key meta data is found in metaData.
+*/
+
+QVariant S60MediaMetaDataProvider::metaData(QtMultimediaKit::MetaData key) const
+{
+ DP0("S60MediaMetaDataProvider::metaData");
+
+ if (m_control->session())
+ return m_control->session()->metaData(key);
+ return QVariant();
+}
+
+/*!
+ * Returns available metaData.
+*/
+
+QList<QtMultimediaKit::MetaData> S60MediaMetaDataProvider::availableMetaData() const
+{
+ DP0("S60MediaMetaDataProvider::availableMetaData");
+
+ if (m_control->session())
+ return m_control->session()->availableMetaData();
+ return QList<QtMultimediaKit::MetaData>();
+}
+
+/*!
+ * Returns when \a key string is found in extended metaData.
+*/
+
+QVariant S60MediaMetaDataProvider::extendedMetaData(const QString &key) const
+{
+ DP0("S60MediaMetaDataProvider::extendedMetaData");
+
+ if (m_control->session())
+ return m_control->session()->metaData(key);
+ return QVariant();
+}
+
+/*!
+ * Returns available Extended MetaData.
+*/
+
+QStringList S60MediaMetaDataProvider::availableExtendedMetaData() const
+{
+ DP0("S60MediaMetaDataProvider::availableExtendedMetaData");
+
+ if (m_control->session())
+ return m_control->session()->availableExtendedMetaData();
+ return QStringList();
+}
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediametadataprovider.h b/src/plugins/symbian/mmf/mediaplayer/s60mediametadataprovider.h
new file mode 100644
index 000000000..eb995080d
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediametadataprovider.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60MEDIAMETADATAPROVIDER_H
+#define S60MEDIAMETADATAPROVIDER_H
+
+#include <qmetadatareadercontrol.h>
+#include "s60mediaplayercontrol.h"
+
+QT_USE_NAMESPACE
+
+class S60MediaPlayerControl;
+
+class S60MediaMetaDataProvider : public QMetaDataReaderControl
+{
+ Q_OBJECT
+
+public:
+ S60MediaMetaDataProvider(QObject *control, QObject *parent = 0);
+ ~S60MediaMetaDataProvider();
+
+ bool isMetaDataAvailable() const;
+ bool isWritable() const;
+
+ QVariant metaData(QtMultimediaKit::MetaData key) const;
+ QList<QtMultimediaKit::MetaData> availableMetaData() const;
+ QVariant extendedMetaData(const QString &key) const ;
+ QStringList availableExtendedMetaData() const;
+
+private:
+ S60MediaPlayerControl *m_control;
+};
+
+#endif // S60VIDEOMETADATAPROVIDER_H
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60medianetworkaccesscontrol.cpp b/src/plugins/symbian/mmf/mediaplayer/s60medianetworkaccesscontrol.cpp
new file mode 100644
index 000000000..dad69a691
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60medianetworkaccesscontrol.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** 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$
+** 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 "s60medianetworkaccesscontrol.h"
+
+#define KBuffersize 512
+
+S60MediaNetworkAccessControl::S60MediaNetworkAccessControl(QObject *parent)
+ : QMediaNetworkAccessControl(parent)
+ , m_iapId(KUseDefaultIap)
+ , m_currentIndex(0)
+{
+}
+
+void S60MediaNetworkAccessControl::accessPointChanged(int id)
+{
+ if (!m_IapIdList.isEmpty())
+ m_NetworkObject = m_NetworkObjectList.at(m_IapIdList.indexOf(id));
+ emit configurationChanged(m_NetworkObject);
+}
+
+S60MediaNetworkAccessControl::~S60MediaNetworkAccessControl()
+{
+ m_NetworkObjectList.clear();
+ m_IapIdList.clear();
+}
+
+void S60MediaNetworkAccessControl::resetIndex()
+{
+ m_currentIndex = 0;
+}
+
+void S60MediaNetworkAccessControl::setConfigurations(const QList<QNetworkConfiguration> &configurations)
+{
+ if (!configurations.isEmpty()) {
+ m_currentIndex =0;
+ TRAPD(error, retriveAccesspointIDL(configurations));
+ if (error != KErrNone) {
+ m_NetworkObjectList.clear();
+ m_IapIdList.clear();
+ }
+ }
+}
+
+TBool S60MediaNetworkAccessControl::isLastAccessPoint()
+{
+ if (m_currentIndex == m_NetworkObjectList.size())
+ return TRUE;
+ else
+ return FALSE;
+}
+
+int S60MediaNetworkAccessControl::accessPointId()
+{
+ if (m_IapIdList.isEmpty())
+ return m_iapId;
+
+ m_iapId = m_IapIdList.at(m_currentIndex);
+
+ if (isLastAccessPoint())
+ m_currentIndex = 0;
+ else
+ m_currentIndex ++;
+
+ return m_iapId;
+}
+
+QNetworkConfiguration S60MediaNetworkAccessControl::currentConfiguration() const
+{
+ return m_NetworkObject;
+}
+
+void S60MediaNetworkAccessControl::retriveAccesspointIDL(const QList<QNetworkConfiguration> &configurationList)
+{
+ m_NetworkObjectList.clear();
+ m_IapIdList.clear();
+ TBuf<KBuffersize> iapName;
+ TUint32 iapId;
+ TInt err;
+
+ // open the IAP communications database
+ CCommsDatabase* commDB = CCommsDatabase::NewL();
+ CleanupStack::PushL(commDB);
+
+ // Open the IAP table
+ CCommsDbTableView* view = commDB->OpenTableLC(TPtrC(IAP));
+
+ for (int i=0;i<=configurationList.size()- 1;i++) {
+ QString accesspointname = configurationList.at(i).name();
+ TBuf<KBuffersize> accesspointbuffer(accesspointname.utf16());
+ // Point to the first entry
+ if (view->GotoFirstRecord() == KErrNone) {
+ do {
+ view->ReadTextL(TPtrC(COMMDB_NAME), iapName);
+ view->ReadUintL(TPtrC(COMMDB_ID), iapId);
+ if (accesspointbuffer == iapName) {
+ m_NetworkObjectList<<configurationList.at(i);
+ m_IapIdList<<iapId;
+ }
+ // Store name and ID to where you want to
+ } while (err = view->GotoNextRecord(), err == KErrNone);
+ }
+ }
+ CleanupStack::PopAndDestroy(); // view
+ CleanupStack::PopAndDestroy(); // commDB
+}
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60medianetworkaccesscontrol.h b/src/plugins/symbian/mmf/mediaplayer/s60medianetworkaccesscontrol.h
new file mode 100644
index 000000000..aea4dcab5
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60medianetworkaccesscontrol.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60MEDIANETWORKACCESSCONTROL_H_
+#define S60MEDIANETWORKACCESSCONTROL_H_
+
+
+#include <QtCore/qobject.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qstring.h>
+#include <qmetaobject.h>
+#include <QtNetwork/qnetworkconfiguration.h>
+#include <commdbconnpref.h>
+#include <commdb.h>
+#include <mmf/common/mmfcontrollerframeworkbase.h>
+#include <qmedianetworkaccesscontrol.h>
+#include "s60mediaplayercontrol.h"
+
+QT_BEGIN_NAMESPACE
+class QMediaPlayerControl;
+class QMediaNetworkAccessControl;
+class QNetworkConfiguration;
+QT_END_NAMESPACE
+
+class S60MediaNetworkAccessControl : public QMediaNetworkAccessControl
+{
+ Q_OBJECT
+
+public:
+
+ S60MediaNetworkAccessControl(QObject *parent = 0);
+ ~S60MediaNetworkAccessControl();
+
+ virtual void setConfigurations(const QList<QNetworkConfiguration> &configurations);
+ virtual QNetworkConfiguration currentConfiguration() const;
+ int accessPointId();
+ TBool isLastAccessPoint();
+ void resetIndex();
+
+public Q_SLOTS:
+ void accessPointChanged(int);
+
+private:
+ void retriveAccesspointIDL(const QList<QNetworkConfiguration> &);
+ QList<int> m_IapIdList;
+ QList<QNetworkConfiguration> m_NetworkObjectList;
+ QNetworkConfiguration m_NetworkObject;
+ int m_iapId;
+ int m_currentIndex;
+};
+#endif /* S60MEDIANETWORKACCESSCONTROL_H_ */
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediaplayeraudioendpointselector.cpp b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayeraudioendpointselector.cpp
new file mode 100644
index 000000000..3ad64ef3b
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayeraudioendpointselector.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** 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$
+** 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 "DebugMacros.h"
+
+#include "s60mediaplayercontrol.h"
+#include "s60mediaplayersession.h"
+#include "s60mediaplayeraudioendpointselector.h"
+
+#include <QtGui/QIcon>
+#include <QtCore/QDebug>
+
+/*!
+ Constructs a new audio endpoint selector with the given \a parent.
+*/
+
+S60MediaPlayerAudioEndpointSelector::S60MediaPlayerAudioEndpointSelector(QObject *control, QObject *parent)
+ :QAudioEndpointSelector(parent)
+ , m_control(0)
+{
+ DP0("S60MediaPlayerAudioEndpointSelector::S60MediaPlayerAudioEndpointSelector +++");
+
+ m_control = qobject_cast<S60MediaPlayerControl*>(control);
+ m_audioEndpointNames.append("Default");
+ m_audioEndpointNames.append("All");
+ m_audioEndpointNames.append("None");
+ m_audioEndpointNames.append("Earphone");
+ m_audioEndpointNames.append("Speaker");
+
+ DP0("S60MediaPlayerAudioEndpointSelector::S60MediaPlayerAudioEndpointSelector ---");
+}
+
+/*!
+ Destroys an audio endpoint selector.
+*/
+
+S60MediaPlayerAudioEndpointSelector::~S60MediaPlayerAudioEndpointSelector()
+{
+ DP0("S60MediaPlayerAudioEndpointSelector::~S60MediaPlayerAudioEndpointSelector +++");
+ DP0("S60MediaPlayerAudioEndpointSelector::~S60MediaPlayerAudioEndpointSelector ---");
+}
+
+/*!
+ \return a list of available audio endpoints.
+*/
+
+QList<QString> S60MediaPlayerAudioEndpointSelector::availableEndpoints() const
+{
+ DP0("S60MediaPlayerAudioEndpointSelector::availableEndpoints");
+
+ return m_audioEndpointNames;
+}
+
+/*!
+ \return the description of the endpoint name.
+*/
+
+QString S60MediaPlayerAudioEndpointSelector::endpointDescription(const QString& name) const
+{
+ DP0("S60MediaPlayerAudioEndpointSelector::endpointDescription");
+
+ if (name == QString("Default")) //ENoPreference
+ return QString("Used to indicate that the playing audio can be routed to"
+ "any speaker. This is the default value for audio.");
+ else if (name == QString("All")) //EAll
+ return QString("Used to indicate that the playing audio should be routed to all speakers.");
+ else if (name == QString("None")) //ENoOutput
+ return QString("Used to indicate that the playing audio should not be routed to any output.");
+ else if (name == QString("Earphone")) //EPrivate
+ return QString("Used to indicate that the playing audio should be routed to"
+ "the default private speaker. A private speaker is one that can only"
+ "be heard by one person.");
+ else if (name == QString("Speaker")) //EPublic
+ return QString("Used to indicate that the playing audio should be routed to"
+ "the default public speaker. A public speaker is one that can "
+ "be heard by multiple people.");
+
+ return QString();
+}
+
+/*!
+ \return the name of the currently selected audio endpoint.
+*/
+
+QString S60MediaPlayerAudioEndpointSelector::activeEndpoint() const
+{
+ DP0("S60MediaPlayerAudioEndpointSelector::activeEndpoint");
+
+ if (m_control->session()) {
+ DP1("S60MediaPlayerAudioEndpointSelector::activeEndpoint - ",
+ m_control->session()->activeEndpoint());
+ return m_control->session()->activeEndpoint();
+ }
+ else {
+ DP1("S60MediaPlayerAudioEndpointSelector::activeEndpoint - ",
+ m_control->mediaControlSettings().audioEndpoint());
+ return m_control->mediaControlSettings().audioEndpoint();
+ }
+}
+
+/*!
+ \return the name of the default audio endpoint.
+*/
+
+QString S60MediaPlayerAudioEndpointSelector::defaultEndpoint() const
+{
+ DP0("S60MediaPlayerAudioEndpointSelector::defaultEndpoint");
+
+ if (m_control->session()) {
+ DP1("S60MediaPlayerAudioEndpointSelector::defaultEndpoint - ",
+ m_control->session()->defaultEndpoint());
+ return m_control->session()->defaultEndpoint();
+ }
+ else {
+ DP1("S60MediaPlayerAudioEndpointSelector::defaultEndpoint - ",
+ m_control->mediaControlSettings().audioEndpoint());
+ return m_control->mediaControlSettings().audioEndpoint();
+ }
+}
+
+/*!
+ Set the audio endpoint to \a name.
+*/
+
+void S60MediaPlayerAudioEndpointSelector::setActiveEndpoint(const QString& name)
+{
+ DP0("S60MediaPlayerAudioEndpointSelector::setActiveEndpoin +++");
+
+ DP1("S60MediaPlayerAudioEndpointSelector::setActiveEndpoint - ", name);
+
+ QString oldEndpoint = m_control->mediaControlSettings().audioEndpoint();
+
+ if (name != oldEndpoint && (name == QString("Default") || name == QString("All") ||
+ name == QString("None") || name == QString("Earphone") || name == QString("Speaker"))) {
+
+ if (m_control->session()) {
+ m_control->session()->setActiveEndpoint(name);
+ emit activeEndpointChanged(name);
+ }
+ m_control->setAudioEndpoint(name);
+ }
+
+ DP0("S60MediaPlayerAudioEndpointSelector::setActiveEndpoin ---");
+}
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediaplayeraudioendpointselector.h b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayeraudioendpointselector.h
new file mode 100644
index 000000000..eff49d47a
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayeraudioendpointselector.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60MEDIAPLAYERAUDIOENDPOINTSELECTOR_H
+#define S60MEDIAPLAYERAUDIOENDPOINTSELECTOR_H
+
+#include <QStringList>
+
+#include <qaudioendpointselector.h>
+
+QT_USE_NAMESPACE
+
+class S60MediaPlayerControl;
+class S60MediaPlayerSession;
+
+class S60MediaPlayerAudioEndpointSelector : public QAudioEndpointSelector
+{
+
+Q_OBJECT
+
+public:
+ S60MediaPlayerAudioEndpointSelector(QObject *control, QObject *parent = 0);
+ ~S60MediaPlayerAudioEndpointSelector();
+
+ QList<QString> availableEndpoints() const ;
+ QString endpointDescription(const QString& name) const;
+ QString defaultEndpoint() const;
+ QString activeEndpoint() const;
+
+public Q_SLOTS:
+ void setActiveEndpoint(const QString& name);
+
+private:
+ S60MediaPlayerControl* m_control;
+ QString m_audioInput;
+ QList<QString> m_audioEndpointNames;
+};
+
+#endif // S60MEDIAPLAYERAUDIOENDPOINTSELECTOR_H
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediaplayercontrol.cpp b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayercontrol.cpp
new file mode 100644
index 000000000..2eeceedd8
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayercontrol.cpp
@@ -0,0 +1,518 @@
+
+/****************************************************************************
+**
+** 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$
+** 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 "DebugMacros.h"
+
+#include "s60mediaplayercontrol.h"
+#include "s60mediaplayersession.h"
+
+#include <QtCore/qdir.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qdebug.h>
+
+/*!
+ Constructs a new media player control with the given \a parent.
+*/
+
+S60MediaPlayerControl::S60MediaPlayerControl(MS60MediaPlayerResolver& mediaPlayerResolver, QObject *parent)
+ : QMediaPlayerControl(parent),
+ m_mediaPlayerResolver(mediaPlayerResolver),
+ m_session(NULL),
+ m_stream(NULL)
+{
+ DP0("S60MediaPlayerControl::S60MediaPlayerControl +++");
+
+ DP0("S60MediaPlayerControl::S60MediaPlayerControl ---");
+
+}
+
+/*!
+ Destroys a media player control.
+*/
+
+S60MediaPlayerControl::~S60MediaPlayerControl()
+{
+ DP0("S60MediaPlayerControl::~S60MediaPlayerControl +++");
+ DP0("S60MediaPlayerControl::~S60MediaPlayerControl ---");
+}
+
+/*!
+ \return the current playback position in milliseconds.
+*/
+
+qint64 S60MediaPlayerControl::position() const
+{
+ // DP0("S60MediaPlayerControl::position");
+
+ if (m_session)
+ return m_session->position();
+ return 0;
+}
+
+/*!
+ \return the duration of the current media in milliseconds.
+*/
+
+qint64 S60MediaPlayerControl::duration() const
+{
+ // DP0("S60MediaPlayerControl::duration");
+
+ if (m_session)
+ return m_session->duration();
+ return -1;
+}
+
+/*!
+ \return the state of a player control.
+*/
+
+QMediaPlayer::State S60MediaPlayerControl::state() const
+{
+ DP0("S60MediaPlayerControl::state");
+
+ if (m_session)
+ return m_session->state();
+ return QMediaPlayer::StoppedState;
+}
+
+/*!
+ \return the status of the current media.
+*/
+
+QMediaPlayer::MediaStatus S60MediaPlayerControl::mediaStatus() const
+{
+ DP0("QMediaPlayer::mediaStatus");
+
+ if (m_session)
+ return m_session->mediaStatus();
+ return m_mediaSettings.mediaStatus();
+}
+
+/*!
+ \return the buffering progress of the current media. Progress is measured in the percentage
+ of the buffer filled.
+*/
+
+int S60MediaPlayerControl::bufferStatus() const
+{
+ // DP0("S60MediaPlayerControl::bufferStatus");
+
+ if (m_session)
+ return m_session->bufferStatus();
+ return 0;
+}
+
+/*!
+ \return the audio volume of a player control.
+*/
+
+int S60MediaPlayerControl::volume() const
+{
+ DP0("S60MediaPlayerControl::volume");
+
+ if (m_session)
+ return m_session->volume();
+ return m_mediaSettings.volume();
+}
+
+/*!
+ \return the mute state of a player control.
+*/
+
+bool S60MediaPlayerControl::isMuted() const
+{
+ DP0("S60MediaPlayerControl::isMuted");
+
+ if (m_session)
+ return m_session->isMuted();
+ return m_mediaSettings.isMuted();
+}
+
+/*!
+ Identifies if the current media is seekable.
+
+ \return true if it possible to seek within the current media, and false otherwise.
+*/
+
+bool S60MediaPlayerControl::isSeekable() const
+{
+ DP0("S60MediaPlayerControl::isSeekable");
+
+ if (m_session)
+ return m_session->isSeekable();
+ return false;
+}
+
+/*!
+ \return a range of times in milliseconds that can be played back.
+
+ Usually for local files this is a continuous interval equal to [0..duration()]
+ or an empty time range if seeking is not supported, but for network sources
+ it refers to the buffered parts of the media.
+*/
+
+QMediaTimeRange S60MediaPlayerControl::availablePlaybackRanges() const
+{
+ DP0("S60MediaPlayerControl::availablePlaybackRanges");
+
+ QMediaTimeRange ranges;
+
+ if(m_session && m_session->isSeekable())
+ ranges.addInterval(0, m_session->duration());
+
+ return ranges;
+}
+
+/*!
+ \return the rate of playback.
+*/
+
+qreal S60MediaPlayerControl::playbackRate() const
+{
+ DP0("S60MediaPlayerControl::playbackRate");
+
+ return m_mediaSettings.playbackRate();
+}
+
+/*!
+ Sets the \a rate of playback.
+*/
+
+void S60MediaPlayerControl::setPlaybackRate(qreal rate)
+{
+ DP0("S60MediaPlayerControl::setPlaybackRate +++");
+
+ DP1("S60MediaPlayerControl::setPlaybackRate - ", rate);
+
+ //getting the current playbackrate
+ qreal currentPBrate = m_mediaSettings.playbackRate();
+ //checking if we need to change the Playback rate
+ if (!qFuzzyCompare(currentPBrate,rate))
+ {
+ if(m_session)
+ m_session->setPlaybackRate(rate);
+
+ m_mediaSettings.setPlaybackRate(rate);
+ }
+
+ DP0("S60MediaPlayerControl::setPlaybackRate ---");
+}
+
+/*!
+ Sets the playback \a pos of the current media. This will initiate a seek and it may take
+ some time for playback to reach the position set.
+*/
+
+void S60MediaPlayerControl::setPosition(qint64 pos)
+{
+ DP0("S60MediaPlayerControl::setPosition +++");
+
+ DP1("S60MediaPlayerControl::setPosition, Position:", pos);
+
+ if (m_session)
+ m_session->setPosition(pos);
+
+ DP0("S60MediaPlayerControl::setPosition ---");
+}
+
+/*!
+ Starts playback of the current media.
+
+ If successful the player control will immediately enter the \l {QMediaPlayer::PlayingState}
+ {playing} state.
+*/
+
+void S60MediaPlayerControl::play()
+{
+ DP0("S60MediaPlayerControl::play +++");
+
+ if (m_session)
+ m_session->play();
+
+ DP0("S60MediaPlayerControl::play ---");
+}
+
+/*!
+ Pauses playback of the current media.
+
+ If sucessful the player control will immediately enter the \l {QMediaPlayer::PausedState}
+ {paused} state.
+*/
+
+void S60MediaPlayerControl::pause()
+{
+ DP0("S60MediaPlayerControl::pause +++");
+
+ if (m_session)
+ m_session->pause();
+
+ DP0("S60MediaPlayerControl::pause ---");
+}
+
+/*!
+ Stops playback of the current media.
+
+ If successful the player control will immediately enter the \l {QMediaPlayer::StoppedState}
+ {stopped} state.
+*/
+
+void S60MediaPlayerControl::stop()
+{
+ DP0("S60MediaPlayerControl::stop +++");
+
+ if (m_session)
+ m_session->stop();
+
+ DP0("S60MediaPlayerControl::stop ---");
+}
+
+/*!
+ Sets the audio \a volume of a player control.
+*/
+
+void S60MediaPlayerControl::setVolume(int volume)
+{
+ DP0("S60MediaPlayerControl::setVolume +++");
+
+ DP1("S60MediaPlayerControl::setVolume", volume);
+
+ int boundVolume = qBound(0, volume, 100);
+ if (boundVolume == m_mediaSettings.volume())
+ return;
+
+ m_mediaSettings.setVolume(boundVolume);
+
+ if (m_session)
+ m_session->setVolume(boundVolume);
+
+ DP0("S60MediaPlayerControl::setVolume ---");
+}
+
+/*!
+ Sets the \a muted state of a player control.
+*/
+
+void S60MediaPlayerControl::setMuted(bool muted)
+{
+ DP0("S60MediaPlayerControl::setMuted +++");
+
+ DP1("S60MediaPlayerControl::setMuted - ", muted);
+
+ if (m_mediaSettings.isMuted() == muted)
+ return;
+
+ m_mediaSettings.setMuted(muted);
+
+ if (m_session)
+ m_session->setMuted(muted);
+
+ DP0("S60MediaPlayerControl::setMuted ---");
+}
+
+/*!
+ * \return the current media source.
+*/
+
+QMediaContent S60MediaPlayerControl::media() const
+{
+ DP0("S60MediaPlayerControl::media");
+
+ return m_currentResource;
+}
+
+/*!
+ \return the current media stream. This is only a valid if a stream was passed to setMedia().
+
+ \sa setMedia()
+*/
+
+const QIODevice *S60MediaPlayerControl::mediaStream() const
+{
+ DP0("S60MediaPlayerControl::mediaStream");
+
+ return m_stream;
+}
+
+/*!
+ Sets the current \a source media source. If a \a stream is supplied; data will be read from that
+ instead of attempting to resolve the media source. The media source may still be used to
+ supply media information such as mime type.
+
+ Setting the media to a null QMediaContent will cause the control to discard all
+ information relating to the current media source and to cease all I/O operations related
+ to that media.
+*/
+
+void S60MediaPlayerControl::setMedia(const QMediaContent &source, QIODevice *stream)
+{
+ DP0("S60MediaPlayerControl::setMedia +++");
+
+ Q_UNUSED(stream)
+
+ if ((m_session && m_currentResource == source) && m_session->isStreaming())
+ {
+ m_session->load(source);
+ return;
+ }
+
+ // we don't want to set & load media again when it is already loaded
+ if (m_session && m_currentResource == source)
+ return;
+
+ // store to variable as session is created based on the content type.
+ m_currentResource = source;
+ S60MediaPlayerSession *newSession = m_mediaPlayerResolver.PlayerSession();
+ m_mediaSettings.setMediaStatus(QMediaPlayer::UnknownMediaStatus);
+
+ if (m_session)
+ m_session->reset();
+ else {
+ emit mediaStatusChanged(QMediaPlayer::UnknownMediaStatus);
+ emit error(QMediaPlayer::NoError, QString());
+ }
+
+ m_session = newSession;
+
+ if (m_session)
+ m_session->load(source);
+ else {
+ QMediaPlayer::MediaStatus status = (source.isNull()) ? QMediaPlayer::NoMedia : QMediaPlayer::InvalidMedia;
+ m_mediaSettings.setMediaStatus(status);
+ emit stateChanged(QMediaPlayer::StoppedState);
+ emit error((source.isNull()) ? QMediaPlayer::NoError : QMediaPlayer::ResourceError,
+ (source.isNull()) ? "" : tr("Media couldn't be resolved"));
+ emit mediaStatusChanged(status);
+ }
+ emit mediaChanged(m_currentResource);
+
+ DP0("S60MediaPlayerControl::setMedia ---");
+}
+
+/*!
+ * \return media player session.
+*/
+S60MediaPlayerSession* S60MediaPlayerControl::session()
+{
+ DP0("S60MediaPlayerControl::session");
+
+ return m_session;
+}
+
+/*!
+ * Sets \a output as a VideoOutput.
+*/
+
+void S60MediaPlayerControl::setVideoOutput(QObject *output)
+{
+ DP0("S60MediaPlayerControl::setVideoOutput +++");
+
+ m_mediaPlayerResolver.VideoPlayerSession()->setVideoRenderer(output);
+
+ DP0("S60MediaPlayerControl::setVideoOutput ---");
+}
+
+/*!
+ * \return TRUE if Audio available or else FALSE.
+*/
+
+bool S60MediaPlayerControl::isAudioAvailable() const
+{
+ DP0("S60MediaPlayerControl::isAudioAvailable");
+
+ if (m_session)
+ return m_session->isAudioAvailable();
+ return false;
+}
+
+/*!
+ * \return TRUE if Video available or else FALSE.
+*/
+
+bool S60MediaPlayerControl::isVideoAvailable() const
+{
+ DP0("S60MediaPlayerControl::isVideoAvailable");
+
+ if (m_session)
+ return m_session->isVideoAvailable();
+ return false;
+}
+
+/*!
+ * \return media settings.
+ *
+ * Media Settings include volume, muted, playbackRate, mediaStatus, audioEndpoint.
+*/
+const S60MediaSettings& S60MediaPlayerControl::mediaControlSettings() const
+{
+ DP0("S60MediaPlayerControl::mediaControlSettings");
+ return m_mediaSettings;
+}
+
+/*!
+ * Set the audio endpoint to \a name.
+*/
+
+void S60MediaPlayerControl::setAudioEndpoint(const QString& name)
+{
+ DP0("S60MediaPlayerControl::setAudioEndpoint +++");
+
+ DP1("S60MediaPlayerControl::setAudioEndpoint - ", name);
+
+ m_mediaSettings.setAudioEndpoint(name);
+
+ DP0("S60MediaPlayerControl::setAudioEndpoint ---");
+}
+
+/*!
+ * Sets media type \a type as Unknown, Video, Audio, Data.
+*/
+
+void S60MediaPlayerControl::setMediaType(S60MediaSettings::TMediaType type)
+{
+ DP0("S60MediaPlayerControl::setMediaType +++");
+
+ DP1("S60MediaPlayerControl::setMediaType - ", type);
+
+ m_mediaSettings.setMediaType(type);
+
+ DP0("S60MediaPlayerControl::setMediaType ---");
+}
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediaplayercontrol.h b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayercontrol.h
new file mode 100644
index 000000000..caf6631a8
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayercontrol.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60MEDIAPLAYERCONTROL_H
+#define S60MEDIAPLAYERCONTROL_H
+
+#include <QtCore/qobject.h>
+
+#include <qmediaplayercontrol.h>
+
+#include "ms60mediaplayerresolver.h"
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+class QMediaPlayer;
+class QMediaTimeRange;
+class QMediaContent;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class S60MediaPlayerSession;
+class S60MediaPlayerService;
+
+class S60MediaSettings
+{
+
+public:
+ S60MediaSettings()
+ : m_volume(30)
+ , m_muted(false)
+ , m_playbackRate(0)
+ , m_mediaStatus(QMediaPlayer::NoMedia)
+ , m_audioEndpoint(QString("Default"))
+ {
+ }
+
+ enum TMediaType {Unknown, Video, Audio, Data};
+
+ void setVolume(int volume) { m_volume = volume; }
+ void setMuted(bool muted) { m_muted = muted; }
+ void setPlaybackRate(qreal rate) { m_playbackRate = rate; }
+ void setMediaStatus(QMediaPlayer::MediaStatus status) {m_mediaStatus=status;}
+ void setAudioEndpoint(const QString& audioEndpoint) { m_audioEndpoint = audioEndpoint; }
+ void setMediaType(S60MediaSettings::TMediaType type) { m_mediaType = type; }
+
+ int volume() const { return m_volume; }
+ bool isMuted() const { return m_muted; }
+ qreal playbackRate() const { return m_playbackRate; }
+ QMediaPlayer::MediaStatus mediaStatus() const {return m_mediaStatus;}
+ QString audioEndpoint() const { return m_audioEndpoint; }
+ S60MediaSettings::TMediaType mediaType() const { return m_mediaType; }
+
+private:
+ int m_volume;
+ bool m_muted;
+ qreal m_playbackRate;
+ QMediaPlayer::MediaStatus m_mediaStatus;
+ QString m_audioEndpoint;
+ S60MediaSettings::TMediaType m_mediaType;
+};
+
+class S60MediaPlayerControl : public QMediaPlayerControl
+{
+ Q_OBJECT
+
+public:
+ S60MediaPlayerControl(MS60MediaPlayerResolver& mediaPlayerResolver, QObject *parent = 0);
+ ~S60MediaPlayerControl();
+
+ // from QMediaPlayerControl
+ virtual QMediaPlayer::State state() const;
+ virtual QMediaPlayer::MediaStatus mediaStatus() const;
+ virtual qint64 duration() const;
+ virtual qint64 position() const;
+ virtual void setPosition(qint64 pos);
+ virtual int volume() const;
+ virtual void setVolume(int volume);
+ virtual bool isMuted() const;
+ virtual void setMuted(bool muted);
+ virtual int bufferStatus() const;
+ virtual bool isAudioAvailable() const;
+ virtual bool isVideoAvailable() const;
+ virtual bool isSeekable() const;
+ virtual QMediaTimeRange availablePlaybackRanges() const;
+ virtual qreal playbackRate() const;
+ virtual void setPlaybackRate(qreal rate);
+ virtual QMediaContent media() const;
+ virtual const QIODevice *mediaStream() const;
+ virtual void setMedia(const QMediaContent&, QIODevice *);
+ virtual void play();
+ virtual void pause();
+ virtual void stop();
+
+ // Own methods
+ S60MediaPlayerSession* session();
+ void setVideoOutput(QObject *output);
+ const S60MediaSettings& mediaControlSettings() const;
+ void setAudioEndpoint(const QString& name);
+ void setMediaType(S60MediaSettings::TMediaType type);
+
+private:
+ MS60MediaPlayerResolver &m_mediaPlayerResolver;
+ S60MediaPlayerSession *m_session;
+ QMediaContent m_currentResource;
+ QIODevice *m_stream;
+ S60MediaSettings m_mediaSettings;
+};
+
+#endif
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediaplayerservice.cpp b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayerservice.cpp
new file mode 100644
index 000000000..a1aabef90
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayerservice.cpp
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** 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$
+** 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 "DebugMacros.h"
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/qwidget.h>
+
+#include "s60mediaplayerservice.h"
+#include "s60mediaplayercontrol.h"
+#include "s60videoplayersession.h"
+#include "s60audioplayersession.h"
+#include "s60mediametadataprovider.h"
+#include "s60mediarecognizer.h"
+#include "s60videowidgetcontrol.h"
+#include "s60videowindowcontrol.h"
+#ifdef HAS_VIDEORENDERERCONTROL_IN_VIDEOPLAYER
+#include "s60videorenderer.h"
+#endif
+#include "s60mediaplayeraudioendpointselector.h"
+#include "s60medianetworkaccesscontrol.h"
+#include "s60mediastreamcontrol.h"
+
+#include <qmediaplaylistnavigator.h>
+#include <qmediaplaylist.h>
+
+/*!
+ Construct a media service with the given \a parent.
+*/
+
+S60MediaPlayerService::S60MediaPlayerService(QObject *parent)
+ : QMediaService(parent)
+ , m_control(NULL)
+ , m_videoPlayerSession(NULL)
+ , m_audioPlayerSession(NULL)
+ , m_metaData(NULL)
+ , m_audioEndpointSelector(NULL)
+ , m_streamControl(NULL)
+ , m_networkAccessControl(NULL)
+ , m_videoOutput(NULL)
+{
+ DP0("S60MediaPlayerService::S60MediaPlayerService +++");
+
+ m_control = new S60MediaPlayerControl(*this, this);
+ m_metaData = new S60MediaMetaDataProvider(m_control, this);
+ m_audioEndpointSelector = new S60MediaPlayerAudioEndpointSelector(m_control, this);
+ m_streamControl = new S60MediaStreamControl(m_control, this);
+ m_networkAccessControl = new S60MediaNetworkAccessControl(this);
+
+ DP0("S60MediaPlayerService::S60MediaPlayerService ---");
+}
+
+/*!
+ Destroys a media service.
+*/
+
+S60MediaPlayerService::~S60MediaPlayerService()
+{
+ DP0("S60MediaPlayerService::~S60MediaPlayerService +++");
+ DP0("S60MediaPlayerService::~S60MediaPlayerService ---");
+}
+
+/*!
+ \return a pointer to the media control, which matches the controller \a name.
+
+ If the service does not implement the control, or if it is unavailable a
+ null pointer is returned instead.
+
+ Controls must be returned to the service when no longer needed using the
+ releaseControl() function.
+*/
+
+QMediaControl *S60MediaPlayerService::requestControl(const char *name)
+{
+ DP0("S60MediaPlayerService::requestControl");
+
+ if (qstrcmp(name, QMediaPlayerControl_iid) == 0)
+ return m_control;
+
+ if (qstrcmp(name, QMediaNetworkAccessControl_iid) == 0)
+ return m_networkAccessControl;
+
+ if (qstrcmp(name, QMetaDataReaderControl_iid) == 0)
+ return m_metaData;
+
+ if (qstrcmp(name, QAudioEndpointSelector_iid) == 0)
+ return m_audioEndpointSelector;
+
+ if (qstrcmp(name, QMediaStreamsControl_iid) == 0)
+ return m_streamControl;
+
+ if (!m_videoOutput) {
+ if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
+ m_videoOutput = new S60VideoWidgetControl(this);
+ }
+#ifdef HAS_VIDEORENDERERCONTROL_IN_VIDEOPLAYER
+ else if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+ m_videoOutput = new S60VideoRenderer(this);
+ }
+#endif /* HAS_VIDEORENDERERCONTROL_IN_VIDEOPLAYER */
+ else if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
+ m_videoOutput = new S60VideoWindowControl(this);
+ }
+
+ if (m_videoOutput) {
+ m_control->setVideoOutput(m_videoOutput);
+ return m_videoOutput;
+ }
+ }else {
+ if (qstrcmp(name, QVideoWidgetControl_iid) == 0 ||
+#ifdef HAS_VIDEORENDERERCONTROL_IN_VIDEOPLAYER
+ qstrcmp(name, QVideoRendererControl_iid) == 0 ||
+#endif /* HAS_VIDEORENDERERCONTROL_IN_VIDEOPLAYER */
+ qstrcmp(name, QVideoWindowControl_iid) == 0){
+ return m_videoOutput;
+ }
+ }
+ return 0;
+}
+
+/*!
+ Releases a \a control back to the service.
+*/
+
+void S60MediaPlayerService::releaseControl(QMediaControl *control)
+{
+ DP0("S60MediaPlayerService::releaseControl ++");
+
+ if (control == m_videoOutput) {
+ m_videoOutput = 0;
+ m_control->setVideoOutput(m_videoOutput);
+ }
+
+ DP0("S60MediaPlayerService::releaseControl --");
+}
+
+/*!
+ * \return media player session(audio playersesion/video playersession)
+ * by recognizing whether media is audio or video and sets it on media type.
+*/
+S60MediaPlayerSession* S60MediaPlayerService::PlayerSession()
+{
+ DP0("S60MediaPlayerService::PlayerSession");
+
+ QUrl url = m_control->media().canonicalUrl();
+
+ if (url.isEmpty() == true) {
+ return NULL;
+ }
+
+ QScopedPointer<S60MediaRecognizer> mediaRecognizer(new S60MediaRecognizer);
+ S60MediaRecognizer::MediaType mediaType = mediaRecognizer->mediaType(url);
+ mediaRecognizer.reset();
+
+ switch (mediaType) {
+ case S60MediaRecognizer::Video:
+ case S60MediaRecognizer::Url: {
+ m_control->setMediaType(S60MediaSettings::Video);
+ return VideoPlayerSession();
+ }
+ case S60MediaRecognizer::Audio: {
+ m_control->setMediaType(S60MediaSettings::Audio);
+ return AudioPlayerSession();
+ }
+ default:
+ m_control->setMediaType(S60MediaSettings::Unknown);
+ break;
+ }
+
+ return NULL;
+}
+
+/*!
+ * \return media playersession (videoplayersession).
+ * constructs the videoplayersession object and connects all the respective signals and slots.
+ * and initialises all the media settings.
+*/
+
+S60MediaPlayerSession* S60MediaPlayerService::VideoPlayerSession()
+{
+ DP0("S60MediaPlayerService::VideoPlayerSession +++");
+
+ if (!m_videoPlayerSession) {
+ m_videoPlayerSession = new S60VideoPlayerSession(this, m_networkAccessControl);
+
+ connect(m_videoPlayerSession, SIGNAL(positionChanged(qint64)),
+ m_control, SIGNAL(positionChanged(qint64)));
+ connect(m_videoPlayerSession, SIGNAL(playbackRateChanged(qreal)),
+ m_control, SIGNAL(playbackRateChanged(qreal)));
+ connect(m_videoPlayerSession, SIGNAL(volumeChanged(int)),
+ m_control, SIGNAL(volumeChanged(int)));
+ connect(m_videoPlayerSession, SIGNAL(mutedChanged(bool)),
+ m_control, SIGNAL(mutedChanged(bool)));
+ connect(m_videoPlayerSession, SIGNAL(durationChanged(qint64)),
+ m_control, SIGNAL(durationChanged(qint64)));
+ connect(m_videoPlayerSession, SIGNAL(stateChanged(QMediaPlayer::State)),
+ m_control, SIGNAL(stateChanged(QMediaPlayer::State)));
+ connect(m_videoPlayerSession, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
+ m_control, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ connect(m_videoPlayerSession,SIGNAL(bufferStatusChanged(int)),
+ m_control, SIGNAL(bufferStatusChanged(int)));
+ connect(m_videoPlayerSession, SIGNAL(videoAvailableChanged(bool)),
+ m_control, SIGNAL(videoAvailableChanged(bool)));
+ connect(m_videoPlayerSession, SIGNAL(audioAvailableChanged(bool)),
+ m_control, SIGNAL(audioAvailableChanged(bool)));
+ connect(m_videoPlayerSession, SIGNAL(seekableChanged(bool)),
+ m_control, SIGNAL(seekableChanged(bool)));
+ connect(m_videoPlayerSession, SIGNAL(availablePlaybackRangesChanged(const QMediaTimeRange&)),
+ m_control, SIGNAL(availablePlaybackRangesChanged(const QMediaTimeRange&)));
+ connect(m_videoPlayerSession, SIGNAL(error(int, const QString &)),
+ m_control, SIGNAL(error(int, const QString &)));
+ connect(m_videoPlayerSession, SIGNAL(metaDataChanged()),
+ m_metaData, SIGNAL(metaDataChanged()));
+ connect(m_videoPlayerSession, SIGNAL(activeEndpointChanged(const QString&)),
+ m_audioEndpointSelector, SIGNAL(activeEndpointChanged(const QString&)));
+ connect(m_videoPlayerSession, SIGNAL(mediaChanged()),
+ m_streamControl, SLOT(handleStreamsChanged()));
+ connect(m_videoPlayerSession, SIGNAL(accessPointChanged(int)),
+ m_networkAccessControl, SLOT(accessPointChanged(int)));
+
+ }
+
+ m_videoPlayerSession->setVolume(m_control->mediaControlSettings().volume());
+ m_videoPlayerSession->setMuted(m_control->mediaControlSettings().isMuted());
+ m_videoPlayerSession->setAudioEndpoint(m_control->mediaControlSettings().audioEndpoint());
+
+ DP0("S60MediaPlayerService::VideoPlayerSession ---");
+
+ return m_videoPlayerSession;
+}
+
+/*!
+ * \return media playersession (audioplayersession).
+ * constructs the audioplayersession object and connects all the respective signals and slots.
+ * and initialises all the media settings.
+*/
+
+S60MediaPlayerSession* S60MediaPlayerService::AudioPlayerSession()
+{
+ DP0("S60MediaPlayerService::AudioPlayerSession +++");
+
+ if (!m_audioPlayerSession) {
+ m_audioPlayerSession = new S60AudioPlayerSession(this);
+
+ connect(m_audioPlayerSession, SIGNAL(positionChanged(qint64)),
+ m_control, SIGNAL(positionChanged(qint64)));
+ connect(m_audioPlayerSession, SIGNAL(playbackRateChanged(qreal)),
+ m_control, SIGNAL(playbackRateChanged(qreal)));
+ connect(m_audioPlayerSession, SIGNAL(volumeChanged(int)),
+ m_control, SIGNAL(volumeChanged(int)));
+ connect(m_audioPlayerSession, SIGNAL(mutedChanged(bool)),
+ m_control, SIGNAL(mutedChanged(bool)));
+ connect(m_audioPlayerSession, SIGNAL(durationChanged(qint64)),
+ m_control, SIGNAL(durationChanged(qint64)));
+ connect(m_audioPlayerSession, SIGNAL(stateChanged(QMediaPlayer::State)),
+ m_control, SIGNAL(stateChanged(QMediaPlayer::State)));
+ connect(m_audioPlayerSession, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
+ m_control, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ connect(m_audioPlayerSession,SIGNAL(bufferStatusChanged(int)),
+ m_control, SIGNAL(bufferStatusChanged(int)));
+ connect(m_audioPlayerSession, SIGNAL(videoAvailableChanged(bool)),
+ m_control, SIGNAL(videoAvailableChanged(bool)));
+ connect(m_audioPlayerSession, SIGNAL(audioAvailableChanged(bool)),
+ m_control, SIGNAL(audioAvailableChanged(bool)));
+ connect(m_audioPlayerSession, SIGNAL(seekableChanged(bool)),
+ m_control, SIGNAL(seekableChanged(bool)));
+ connect(m_audioPlayerSession, SIGNAL(availablePlaybackRangesChanged(const QMediaTimeRange&)),
+ m_control, SIGNAL(availablePlaybackRangesChanged(const QMediaTimeRange&)));
+ connect(m_audioPlayerSession, SIGNAL(error(int, const QString &)),
+ m_control, SIGNAL(error(int, const QString &)));
+ connect(m_audioPlayerSession, SIGNAL(metaDataChanged()),
+ m_metaData, SIGNAL(metaDataChanged()));
+ connect(m_audioPlayerSession, SIGNAL(activeEndpointChanged(const QString&)),
+ m_audioEndpointSelector, SIGNAL(activeEndpointChanged(const QString&)));
+ connect(m_audioPlayerSession, SIGNAL(mediaChanged()),
+ m_streamControl, SLOT(handleStreamsChanged()));
+
+ }
+
+ m_audioPlayerSession->setVolume(m_control->mediaControlSettings().volume());
+ m_audioPlayerSession->setMuted(m_control->mediaControlSettings().isMuted());
+ m_audioPlayerSession->setAudioEndpoint(m_control->mediaControlSettings().audioEndpoint());
+
+ DP0("S60MediaPlayerService::AudioPlayerSession ---");
+
+ return m_audioPlayerSession;
+}
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediaplayerservice.h b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayerservice.h
new file mode 100644
index 000000000..d45ad45cc
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayerservice.h
@@ -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$
+** 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 S60VIDEOPLAYERSERVICE_H
+#define S60VIDEOPLAYERSERVICE_H
+
+#include <QtCore/qobject.h>
+#include <qmediaservice.h>
+
+#include "ms60mediaplayerresolver.h"
+#include "s60mediaplayeraudioendpointselector.h"
+
+QT_BEGIN_NAMESPACE
+class QMediaMetaData;
+class QMediaPlayerControl;
+class QMediaPlaylist;
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class S60VideoPlayerSession;
+class S60AudioPlayerSession;
+class S60MediaPlayerControl;
+class S60MediaMetaDataProvider;
+class S60MediaStreamControl;
+class S60MediaRecognizer;
+
+class QMediaPlaylistNavigator;
+class S60MediaNetworkAccessControl;
+
+class S60MediaPlayerService : public QMediaService, public MS60MediaPlayerResolver
+{
+ Q_OBJECT
+
+public:
+
+ S60MediaPlayerService(QObject *parent = 0);
+ ~S60MediaPlayerService();
+
+ QMediaControl *requestControl(const char *name);
+ void releaseControl(QMediaControl *control);
+
+protected: // From MS60MediaPlayerResolver
+ S60MediaPlayerSession* PlayerSession();
+ S60MediaPlayerSession* VideoPlayerSession();
+ S60MediaPlayerSession* AudioPlayerSession();
+
+private:
+ S60MediaPlayerControl *m_control;
+ S60VideoPlayerSession *m_videoPlayerSession;
+ S60AudioPlayerSession *m_audioPlayerSession;
+ S60MediaMetaDataProvider *m_metaData;
+ S60MediaPlayerAudioEndpointSelector *m_audioEndpointSelector;
+ S60MediaStreamControl *m_streamControl;
+ S60MediaNetworkAccessControl *m_networkAccessControl;
+ QMediaControl *m_videoOutput;
+};
+
+#endif
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediaplayersession.cpp b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayersession.cpp
new file mode 100644
index 000000000..49a840a2d
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayersession.cpp
@@ -0,0 +1,1054 @@
+/****************************************************************************
+**
+** 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$
+** 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 "DebugMacros.h"
+
+#include "s60mediaplayersession.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qtimer.h>
+#include <mmf/common/mmferrors.h>
+#include <qmediatimerange.h>
+
+/*!
+ Construct a media playersession with the given \a parent.
+*/
+
+S60MediaPlayerSession::S60MediaPlayerSession(QObject *parent)
+ : QObject(parent)
+ , m_stream(false)
+ , m_playbackRate(0)
+ , m_muted(false)
+ , m_volume(0)
+ , m_state(QMediaPlayer::StoppedState)
+ , m_mediaStatus(QMediaPlayer::NoMedia)
+ , m_progressTimer(new QTimer(this))
+ , m_stalledTimer(new QTimer(this))
+ , m_error(KErrNone)
+ , m_play_requested(false)
+ , m_seekable(true)
+{
+ DP0("S60MediaPlayerSession::S60MediaPlayerSession +++");
+
+ connect(m_progressTimer, SIGNAL(timeout()), this, SLOT(tick()));
+ connect(m_stalledTimer, SIGNAL(timeout()), this, SLOT(stalled()));
+
+ DP0("S60MediaPlayerSession::S60MediaPlayerSession ---");
+}
+
+/*!
+ Destroys a media playersession.
+*/
+
+S60MediaPlayerSession::~S60MediaPlayerSession()
+{
+ DP0("S60MediaPlayerSession::~S60MediaPlayerSession +++");
+ DP0("S60MediaPlayerSession::~S60MediaPlayerSession ---");
+}
+
+/*!
+ * \return the audio volume of a player session.
+*/
+int S60MediaPlayerSession::volume() const
+{
+ DP1("S60MediaPlayerSession::volume", m_volume);
+
+ return m_volume;
+}
+
+/*!
+ Sets the audio \a volume of a player session.
+*/
+
+void S60MediaPlayerSession::setVolume(int volume)
+{
+ DP0("S60MediaPlayerSession::setVolume +++");
+
+ DP1("S60MediaPlayerSession::setVolume - ", volume);
+
+ if (m_volume == volume)
+ return;
+
+ m_volume = volume;
+ emit volumeChanged(m_volume);
+
+ // Dont set symbian players volume until media loaded.
+ // Leaves with KerrNotReady although documentation says otherwise.
+ if (!m_muted &&
+ ( mediaStatus() == QMediaPlayer::LoadedMedia
+ || (mediaStatus() == QMediaPlayer::StalledMedia && state() != QMediaPlayer::StoppedState)
+ || mediaStatus() == QMediaPlayer::BufferingMedia
+ || mediaStatus() == QMediaPlayer::BufferedMedia
+ || mediaStatus() == QMediaPlayer::EndOfMedia)) {
+ TRAPD(err, doSetVolumeL(m_volume));
+ setError(err);
+ }
+ DP0("S60MediaPlayerSession::setVolume ---");
+}
+
+/*!
+ \return the mute state of a player session.
+*/
+
+bool S60MediaPlayerSession::isMuted() const
+{
+ DP1("S60MediaPlayerSession::isMuted", m_muted);
+
+ return m_muted;
+}
+
+/*!
+ Identifies if the current media is seekable.
+
+ \return true if it possible to seek within the current media, and false otherwise.
+*/
+
+bool S60MediaPlayerSession::isSeekable() const
+{
+ DP1("S60MediaPlayerSession::isSeekable", m_seekable);
+
+ return m_seekable;
+}
+
+/*!
+ Sets the \a status of the current media.
+*/
+
+void S60MediaPlayerSession::setMediaStatus(QMediaPlayer::MediaStatus status)
+{
+ DP0("S60MediaPlayerSession::setMediaStatus +++");
+
+ if (m_mediaStatus == status)
+ return;
+
+ m_mediaStatus = status;
+
+ emit mediaStatusChanged(m_mediaStatus);
+
+ if (m_play_requested && m_mediaStatus == QMediaPlayer::LoadedMedia)
+ play();
+
+ DP0("S60MediaPlayerSession::setMediaStatus ---");
+}
+
+/*!
+ Sets the \a state on media player.
+*/
+
+void S60MediaPlayerSession::setState(QMediaPlayer::State state)
+{
+ DP0("S60MediaPlayerSession::setState +++");
+
+ if (m_state == state)
+ return;
+
+ m_state = state;
+ emit stateChanged(m_state);
+
+ DP0("S60MediaPlayerSession::setState ---");
+}
+
+/*!
+ \return the state of a player session.
+*/
+
+QMediaPlayer::State S60MediaPlayerSession::state() const
+{
+ DP1("S60MediaPlayerSession::state", m_state);
+
+ return m_state;
+}
+
+/*!
+ \return the status of the current media.
+*/
+
+QMediaPlayer::MediaStatus S60MediaPlayerSession::mediaStatus() const
+{
+ DP1("S60MediaPlayerSession::mediaStatus", m_mediaStatus);
+
+ return m_mediaStatus;
+}
+
+/*!
+ * Loads the \a url for playback.
+ * If \a url is local file then it loads audio playersesion if its audio file.
+ * If it is a local video file then loads the video playersession.
+*/
+
+void S60MediaPlayerSession::load(const QMediaContent source)
+{
+ DP0("S60MediaPlayerSession::load +++");
+
+ m_source = source;
+ setMediaStatus(QMediaPlayer::LoadingMedia);
+ startStalledTimer();
+ m_stream = (source.canonicalUrl().scheme() == "file")?false:true;
+ m_UrlPath = source.canonicalUrl();
+ TRAPD(err,
+ if (m_stream)
+ doLoadUrlL(QString2TPtrC(source.canonicalUrl().toString()));
+ else
+ doLoadL(QString2TPtrC(QDir::toNativeSeparators(source.canonicalUrl().toLocalFile()))));
+ setError(err);
+
+ DP0("S60MediaPlayerSession::load ---");
+}
+
+TBool S60MediaPlayerSession::isStreaming()
+{
+ return m_stream;
+}
+
+/*!
+ Start or resume playing the current source.
+*/
+void S60MediaPlayerSession::play()
+{
+ DP0("S60MediaPlayerSession::play +++");
+
+ if ( (state() == QMediaPlayer::PlayingState && m_play_requested == false)
+ || mediaStatus() == QMediaPlayer::UnknownMediaStatus
+ || mediaStatus() == QMediaPlayer::NoMedia
+ || mediaStatus() == QMediaPlayer::InvalidMedia)
+ return;
+
+ setState(QMediaPlayer::PlayingState);
+
+ if (mediaStatus() == QMediaPlayer::LoadingMedia ||
+ (mediaStatus() == QMediaPlayer::StalledMedia &&
+ state() == QMediaPlayer::StoppedState))
+ {
+ m_play_requested = true;
+ return;
+ }
+
+ m_play_requested = false;
+ m_duration = duration();
+ setVolume(m_volume);
+ setMuted(m_muted);
+ startProgressTimer();
+ doPlay();
+
+ DP0("S60MediaPlayerSession::play ---");
+}
+
+/*!
+ Pause playing the current source.
+*/
+
+void S60MediaPlayerSession::pause()
+{
+ DP0("S60MediaPlayerSession::pause +++");
+
+ if (state() != QMediaPlayer::PlayingState)
+ return;
+
+ if (mediaStatus() == QMediaPlayer::NoMedia ||
+ mediaStatus() == QMediaPlayer::InvalidMedia)
+ return;
+
+ setState(QMediaPlayer::PausedState);
+ stopProgressTimer();
+ TRAP_IGNORE(doPauseL());
+ m_play_requested = false;
+
+ DP0("S60MediaPlayerSession::pause ---");
+}
+
+/*!
+ Stop playing, and reset the play position to the beginning.
+*/
+
+void S60MediaPlayerSession::stop()
+{
+ DP0("S60MediaPlayerSession::stop +++");
+
+ if (state() == QMediaPlayer::StoppedState)
+ return;
+
+ m_play_requested = false;
+ m_state = QMediaPlayer::StoppedState;
+ if (mediaStatus() == QMediaPlayer::BufferingMedia ||
+ mediaStatus() == QMediaPlayer::BufferedMedia ||
+ mediaStatus() == QMediaPlayer::StalledMedia)
+ setMediaStatus(QMediaPlayer::LoadedMedia);
+ if (mediaStatus() == QMediaPlayer::LoadingMedia)
+ setMediaStatus(QMediaPlayer::UnknownMediaStatus);
+ stopProgressTimer();
+ stopStalledTimer();
+ doStop();
+ emit positionChanged(0);
+ emit stateChanged(m_state);
+
+ DP0("S60MediaPlayerSession::stop ---");
+}
+
+/*!
+ * Stops the playback and closes the controllers.
+ * And resets all the flags and status, state to default values.
+*/
+
+void S60MediaPlayerSession::reset()
+{
+ DP0("S60MediaPlayerSession::reset +++");
+
+ m_play_requested = false;
+ setError(KErrNone, QString(), true);
+ stopProgressTimer();
+ stopStalledTimer();
+ doStop();
+ doClose();
+ setState(QMediaPlayer::StoppedState);
+ setMediaStatus(QMediaPlayer::UnknownMediaStatus);
+ setPosition(0);
+
+ DP0("S60MediaPlayerSession::reset ---");
+}
+
+/*!
+ * Sets \a renderer as video renderer.
+*/
+
+void S60MediaPlayerSession::setVideoRenderer(QObject *renderer)
+{
+ DP0("S60MediaPlayerSession::setVideoRenderer +++");
+
+ Q_UNUSED(renderer);
+
+ DP0("S60MediaPlayerSession::setVideoRenderer ---");
+}
+
+/*!
+ * the percentage of the temporary buffer filled before playback begins.
+
+ When the player object is buffering; this property holds the percentage of
+ the temporary buffer that is filled. The buffer will need to reach 100%
+ filled before playback can resume, at which time the MediaStatus will be
+ BufferedMedia.
+
+ \sa mediaStatus()
+*/
+
+int S60MediaPlayerSession::bufferStatus()
+{
+ DP0("S60MediaPlayerSession::bufferStatus");
+
+ if (state() ==QMediaPlayer::StoppedState)
+ return 0;
+
+ if( mediaStatus() == QMediaPlayer::LoadingMedia
+ || mediaStatus() == QMediaPlayer::UnknownMediaStatus
+ || mediaStatus() == QMediaPlayer::NoMedia
+ || mediaStatus() == QMediaPlayer::InvalidMedia)
+ return 0;
+
+ int progress = 0;
+ TRAPD(err, progress = doGetBufferStatusL());
+ // If buffer status query not supported by codec return 100
+ // do not set error
+ if(err == KErrNotSupported)
+ return 100;
+
+ setError(err);
+ return progress;
+}
+
+/*!
+ * return TRUE if Meta data is available in current media source.
+*/
+
+bool S60MediaPlayerSession::isMetadataAvailable() const
+{
+ DP0("S60MediaPlayerSession::isMetadataAvailable");
+
+ return !m_metaDataMap.isEmpty();
+}
+
+/*!
+ * \return the \a key meta data.
+*/
+QVariant S60MediaPlayerSession::metaData(const QString &key) const
+{
+ DP0("S60MediaPlayerSession::metaData (const QString &key) const");
+
+ return m_metaDataMap.value(key);
+}
+
+/*!
+ * \return the \a key meta data as QString.
+*/
+
+QVariant S60MediaPlayerSession::metaData(QtMultimediaKit::MetaData key) const
+{
+ DP0("S60MediaPlayerSession::metaData (QtMultimediaKit::MetaData key) const");
+
+ return metaData(metaDataKeyAsString(key));
+}
+
+/*!
+ * \return List of all available meta data from current media source.
+*/
+
+QList<QtMultimediaKit::MetaData> S60MediaPlayerSession::availableMetaData() const
+{
+ DP0("S60MediaPlayerSession::availableMetaData +++");
+
+ QList<QtMultimediaKit::MetaData> metaDataTags;
+ if (isMetadataAvailable()) {
+ for (int i = QtMultimediaKit::Title; i <= QtMultimediaKit::ThumbnailImage; i++) {
+ QString metaDataItem = metaDataKeyAsString((QtMultimediaKit::MetaData)i);
+ if (!metaDataItem.isEmpty()) {
+ if (!metaData(metaDataItem).isNull()) {
+ metaDataTags.append((QtMultimediaKit::MetaData)i);
+ }
+ }
+ }
+ }
+
+ DP0("S60MediaPlayerSession::availableMetaData ---");
+
+ return metaDataTags;
+}
+
+/*!
+ * \return all available extended meta data of current media source.
+*/
+
+QStringList S60MediaPlayerSession::availableExtendedMetaData() const
+{
+ DP0("S60MediaPlayerSession::availableExtendedMetaData");
+
+ return m_metaDataMap.keys();
+}
+
+/*!
+ * \return meta data \a key as QString.
+*/
+
+QString S60MediaPlayerSession::metaDataKeyAsString(QtMultimediaKit::MetaData key) const
+{
+ DP1("S60MediaPlayerSession::metaDataKeyAsString", key);
+
+ switch(key) {
+ case QtMultimediaKit::Title: return "title";
+ case QtMultimediaKit::AlbumArtist: return "artist";
+ case QtMultimediaKit::Comment: return "comment";
+ case QtMultimediaKit::Genre: return "genre";
+ case QtMultimediaKit::Year: return "year";
+ case QtMultimediaKit::Copyright: return "copyright";
+ case QtMultimediaKit::AlbumTitle: return "album";
+ case QtMultimediaKit::Composer: return "composer";
+ case QtMultimediaKit::TrackNumber: return "albumtrack";
+ case QtMultimediaKit::AudioBitRate: return "audiobitrate";
+ case QtMultimediaKit::VideoBitRate: return "videobitrate";
+ case QtMultimediaKit::Duration: return "duration";
+ case QtMultimediaKit::MediaType: return "contenttype";
+ case QtMultimediaKit::CoverArtImage: return "attachedpicture";
+ case QtMultimediaKit::SubTitle: // TODO: Find the matching metadata keys
+ case QtMultimediaKit::Description:
+ case QtMultimediaKit::Category:
+ case QtMultimediaKit::Date:
+ case QtMultimediaKit::UserRating:
+ case QtMultimediaKit::Keywords:
+ case QtMultimediaKit::Language:
+ case QtMultimediaKit::Publisher:
+ case QtMultimediaKit::ParentalRating:
+ case QtMultimediaKit::RatingOrganisation:
+ case QtMultimediaKit::Size:
+ case QtMultimediaKit::AudioCodec:
+ case QtMultimediaKit::AverageLevel:
+ case QtMultimediaKit::ChannelCount:
+ case QtMultimediaKit::PeakValue:
+ case QtMultimediaKit::SampleRate:
+ case QtMultimediaKit::Author:
+ case QtMultimediaKit::ContributingArtist:
+ case QtMultimediaKit::Conductor:
+ case QtMultimediaKit::Lyrics:
+ case QtMultimediaKit::Mood:
+ case QtMultimediaKit::TrackCount:
+ case QtMultimediaKit::CoverArtUrlSmall:
+ case QtMultimediaKit::CoverArtUrlLarge:
+ case QtMultimediaKit::Resolution:
+ case QtMultimediaKit::PixelAspectRatio:
+ case QtMultimediaKit::VideoFrameRate:
+ case QtMultimediaKit::VideoCodec:
+ case QtMultimediaKit::PosterUrl:
+ case QtMultimediaKit::ChapterNumber:
+ case QtMultimediaKit::Director:
+ case QtMultimediaKit::LeadPerformer:
+ case QtMultimediaKit::Writer:
+ case QtMultimediaKit::CameraManufacturer:
+ case QtMultimediaKit::CameraModel:
+ case QtMultimediaKit::Event:
+ case QtMultimediaKit::Subject:
+ default:
+ break;
+ }
+
+ return QString();
+}
+
+/*!
+ Sets the \a muted state of a player session.
+*/
+
+void S60MediaPlayerSession::setMuted(bool muted)
+{
+ DP0("S60MediaPlayerSession::setMuted +++");
+ DP1("S60MediaPlayerSession::setMuted - ", muted);
+
+ m_muted = muted;
+ emit mutedChanged(m_muted);
+
+ if( m_mediaStatus == QMediaPlayer::LoadedMedia
+ || (m_mediaStatus == QMediaPlayer::StalledMedia && state() != QMediaPlayer::StoppedState)
+ || m_mediaStatus == QMediaPlayer::BufferingMedia
+ || m_mediaStatus == QMediaPlayer::BufferedMedia
+ || m_mediaStatus == QMediaPlayer::EndOfMedia) {
+ TRAPD(err, doSetVolumeL((m_muted)?0:m_volume));
+ setError(err);
+ }
+ DP0("S60MediaPlayerSession::setMuted ---");
+}
+
+/*!
+ \return the duration of the current media in milliseconds.
+*/
+
+qint64 S60MediaPlayerSession::duration() const
+{
+ // DP0("S60MediaPlayerSession::duration");
+
+ if( mediaStatus() == QMediaPlayer::LoadingMedia
+ || mediaStatus() == QMediaPlayer::UnknownMediaStatus
+ || mediaStatus() == QMediaPlayer::NoMedia
+ || (mediaStatus() == QMediaPlayer::StalledMedia && state() == QMediaPlayer::StoppedState)
+ || mediaStatus() == QMediaPlayer::InvalidMedia)
+ return -1;
+
+ qint64 pos = 0;
+ TRAP_IGNORE(pos = doGetDurationL());
+ return pos;
+}
+
+/*!
+ \return the current playback position in milliseconds.
+*/
+
+qint64 S60MediaPlayerSession::position() const
+{
+ // DP0("S60MediaPlayerSession::position");
+
+ if( mediaStatus() == QMediaPlayer::LoadingMedia
+ || mediaStatus() == QMediaPlayer::UnknownMediaStatus
+ || mediaStatus() == QMediaPlayer::NoMedia
+ || (mediaStatus() == QMediaPlayer::StalledMedia && state() == QMediaPlayer::StoppedState)
+ || mediaStatus() == QMediaPlayer::InvalidMedia)
+ return 0;
+
+ qint64 pos = 0;
+ TRAP_IGNORE(pos = doGetPositionL());
+ if (!m_play_requested && pos ==0
+ && mediaStatus() != QMediaPlayer::LoadedMedia)
+ return m_duration;
+ return pos;
+}
+
+/*!
+ Sets the playback \a pos of the current media. This will initiate a seek and it may take
+ some time for playback to reach the position set.
+*/
+
+void S60MediaPlayerSession::setPosition(qint64 pos)
+{
+ DP0("S60MediaPlayerSession::setPosition +++");
+
+ DP1("S60MediaPlayerSession::setPosition - ", pos);
+
+ if (position() == pos)
+ return;
+
+ QMediaPlayer::State originalState = state();
+
+ if (originalState == QMediaPlayer::PlayingState)
+ pause();
+
+ TRAPD(err, doSetPositionL(pos * 1000));
+ setError(err);
+
+ if (err == KErrNone) {
+ if (mediaStatus() == QMediaPlayer::EndOfMedia)
+ setMediaStatus(QMediaPlayer::LoadedMedia);
+ }
+ else if (err == KErrNotSupported) {
+ m_seekable = false;
+ emit seekableChanged(m_seekable);
+ }
+
+ if (originalState == QMediaPlayer::PlayingState)
+ play();
+
+ emit positionChanged(position());
+
+ DP0("S60MediaPlayerSession::setPosition ---");
+}
+
+/*!
+ * Set the audio endpoint to \a audioEndpoint.
+*/
+
+void S60MediaPlayerSession::setAudioEndpoint(const QString& audioEndpoint)
+{
+ DP0("S60MediaPlayerSession::setAudioEndpoint +++");
+
+ DP1("S60MediaPlayerSession::setAudioEndpoint - ", audioEndpoint);
+
+ doSetAudioEndpoint(audioEndpoint);
+
+ DP0("S60MediaPlayerSession::setAudioEndpoint ---");
+}
+
+/*!
+ * Loading of media source is completed.
+ * And ready for playback. Updates all the media status, state, settings etc.
+ * And emits the signals.
+*/
+
+void S60MediaPlayerSession::loaded()
+{
+ DP0("S60MediaPlayerSession::loaded +++");
+
+ stopStalledTimer();
+ if (m_error == KErrNone || m_error == KErrMMPartialPlayback) {
+ setMediaStatus(QMediaPlayer::LoadedMedia);
+ TRAPD(err, updateMetaDataEntriesL());
+ setError(err);
+ emit durationChanged(duration());
+ emit positionChanged(0);
+ emit videoAvailableChanged(isVideoAvailable());
+ emit audioAvailableChanged(isAudioAvailable());
+ emit mediaChanged();
+
+ m_seekable = getIsSeekable();
+ }
+
+ DP0("S60MediaPlayerSession::loaded ---");
+}
+
+/*!
+ * Playback is completed as medai source reached end of media.
+*/
+void S60MediaPlayerSession::endOfMedia()
+{
+ DP0("S60MediaPlayerSession::endOfMedia +++");
+
+ m_state = QMediaPlayer::StoppedState;
+ setMediaStatus(QMediaPlayer::EndOfMedia);
+ //there is a chance that user might have called play from EOF callback
+ //if we are already in playing state, do not send state change callback
+ if(m_state == QMediaPlayer::StoppedState)
+ emit stateChanged(QMediaPlayer::StoppedState);
+ emit positionChanged(m_duration);
+
+ DP0("S60MediaPlayerSession::endOfMedia ---");
+}
+
+/*!
+ * The percentage of the temporary buffer filling before playback begins.
+
+ When the player object is buffering; this property holds the percentage of
+ the temporary buffer that is filled. The buffer will need to reach 100%
+ filled before playback can resume, at which time the MediaStatus will be
+ BufferedMedia.
+
+ \sa mediaStatus()
+*/
+
+void S60MediaPlayerSession::buffering()
+{
+ DP0("S60MediaPlayerSession::buffering +++");
+
+ startStalledTimer();
+ setMediaStatus(QMediaPlayer::BufferingMedia);
+
+//Buffering cannot happen in stopped state. Hence update the state
+ if (state() == QMediaPlayer::StoppedState)
+ setState(QMediaPlayer::PausedState);
+
+ DP0("S60MediaPlayerSession::buffering ---");
+}
+
+/*!
+ * Buffer is filled with data and to for continuing/start playback.
+*/
+
+void S60MediaPlayerSession::buffered()
+{
+ DP0("S60MediaPlayerSession::buffered +++");
+
+ stopStalledTimer();
+ setMediaStatus(QMediaPlayer::BufferedMedia);
+
+ DP0("S60MediaPlayerSession::buffered ---");
+}
+
+/*!
+ * Sets media status as stalled as waiting for the buffer to be filled to start playback.
+*/
+
+void S60MediaPlayerSession::stalled()
+{
+ DP0("S60MediaPlayerSession::stalled +++");
+
+ setMediaStatus(QMediaPlayer::StalledMedia);
+
+ DP0("S60MediaPlayerSession::stalled ---");
+}
+
+/*!
+ * \return all the meta data entries in the current media source.
+*/
+
+QMap<QString, QVariant>& S60MediaPlayerSession::metaDataEntries()
+{
+ DP0("S60MediaPlayerSession::metaDataEntries");
+
+ return m_metaDataMap;
+}
+
+/*!
+ * \return Error by converting Symbian specific error to Multimedia error.
+*/
+
+QMediaPlayer::Error S60MediaPlayerSession::fromSymbianErrorToMultimediaError(int error)
+{
+ DP0("S60MediaPlayerSession::fromSymbianErrorToMultimediaError");
+
+ DP1("S60MediaPlayerSession::fromSymbianErrorToMultimediaError - ", error);
+
+ switch(error) {
+ case KErrNoMemory:
+ case KErrNotFound:
+ case KErrBadHandle:
+ case KErrAbort:
+ case KErrNotSupported:
+ case KErrCorrupt:
+ case KErrGeneral:
+ case KErrArgument:
+ case KErrPathNotFound:
+ case KErrDied:
+ case KErrServerTerminated:
+ case KErrServerBusy:
+ case KErrCompletion:
+ case KErrBadPower:
+ case KErrMMInvalidProtocol:
+ case KErrMMInvalidURL:
+ return QMediaPlayer::ResourceError;
+
+ case KErrMMPartialPlayback:
+ return QMediaPlayer::FormatError;
+
+ case KErrMMAudioDevice:
+ case KErrMMVideoDevice:
+ case KErrMMDecoder:
+ case KErrUnknown:
+ return QMediaPlayer::ServiceMissingError;
+
+ case KErrMMNotEnoughBandwidth:
+ case KErrMMSocketServiceNotFound:
+ case KErrMMNetworkRead:
+ case KErrMMNetworkWrite:
+ case KErrMMServerSocket:
+ case KErrMMServerNotSupported:
+ case KErrMMUDPReceive:
+ case KErrMMMulticast:
+ case KErrMMProxyServer:
+ case KErrMMProxyServerNotSupported:
+ case KErrMMProxyServerConnect:
+ case KErrCouldNotConnect:
+ return QMediaPlayer::NetworkError;
+
+ case KErrNotReady:
+ case KErrInUse:
+ case KErrAccessDenied:
+ case KErrLocked:
+ case KErrMMDRMNotAuthorized:
+ case KErrPermissionDenied:
+ case KErrCancel:
+ case KErrAlreadyExists:
+ return QMediaPlayer::AccessDeniedError;
+
+ case KErrNone:
+ return QMediaPlayer::NoError;
+
+ default:
+ return QMediaPlayer::ResourceError;
+ }
+}
+
+/*!
+ * \return error.
+ */
+
+int S60MediaPlayerSession::error() const
+{
+ DP1("S60MediaPlayerSession::error", m_error);
+
+ return m_error;
+}
+
+/*!
+ * Sets the error.
+ * * If playback complete/prepare complete ..., etc with successful then sets error as ZERO
+ * else Multimedia error.
+*/
+
+void S60MediaPlayerSession::setError(int error, const QString &errorString, bool forceReset)
+{
+ DP0("S60MediaPlayerSession::setError +++");
+
+ DP5("S60MediaPlayerSession::setError - error:", error,"errorString:", errorString, "forceReset:", forceReset);
+
+ if( forceReset ) {
+ m_error = KErrNone;
+ emit this->error(QMediaPlayer::NoError, QString());
+ return;
+ }
+
+ // If error does not change and m_error is reseted without forceReset flag
+ if (error == m_error ||
+ (m_error != KErrNone && error == KErrNone))
+ return;
+
+ m_error = error;
+ QMediaPlayer::Error mediaError = fromSymbianErrorToMultimediaError(m_error);
+ QString symbianError = QString(errorString);
+
+ if (mediaError != QMediaPlayer::NoError) {
+ // TODO: fix to user friendly string at some point
+ // These error string are only dev usable
+ symbianError.append("Symbian:");
+ symbianError.append(QString::number(m_error));
+ }
+
+ emit this->error(mediaError, symbianError);
+
+ if (m_error == KErrInUse) {
+ pause();
+ } else if (mediaError != QMediaPlayer::NoError) {
+ m_play_requested = false;
+ setMediaStatus(QMediaPlayer::InvalidMedia);
+ stop();
+ }
+}
+
+void S60MediaPlayerSession::setAndEmitError(int error)
+{
+ m_error = error;
+ QMediaPlayer::Error rateError = fromSymbianErrorToMultimediaError(error);
+ QString symbianError;
+ symbianError.append("Symbian:");
+ symbianError.append(QString::number(error));
+ emit this->error(rateError, symbianError);
+
+ DP0("S60MediaPlayerSession::setError ---");
+}
+
+/*!
+ * emits the signal if there is a changes in position and buffering status.
+ */
+
+void S60MediaPlayerSession::tick()
+{
+ DP0("S60MediaPlayerSession::tick +++");
+
+ emit positionChanged(position());
+
+ if (bufferStatus() < 100)
+ emit bufferStatusChanged(bufferStatus());
+
+ DP0("S60MediaPlayerSession::tick ---");
+}
+
+/*!
+ * Starts the timer once the media source starts buffering.
+*/
+
+void S60MediaPlayerSession::startProgressTimer()
+{
+ DP0("S60MediaPlayerSession::startProgressTimer +++");
+
+ m_progressTimer->start(500);
+
+ DP0("S60MediaPlayerSession::startProgressTimer ---");
+}
+
+/*!
+ * Stops the timer once the media source finished buffering.
+*/
+
+void S60MediaPlayerSession::stopProgressTimer()
+{
+ DP0("S60MediaPlayerSession::stopProgressTimer +++");
+
+ m_progressTimer->stop();
+
+ DP0("S60MediaPlayerSession::stopProgressTimer ---");
+}
+
+/*!
+ * Starts the timer while waiting for some events to happen like source buffering or call backs etc.
+ * So that if the events doesn't occur before stalled timer stops, it'll set the error/media status etc.
+*/
+
+void S60MediaPlayerSession::startStalledTimer()
+{
+ DP0("S60MediaPlayerSession::startStalledTimer +++");
+
+ m_stalledTimer->start(30000);
+
+ DP0("S60MediaPlayerSession::startStalledTimer ---");
+}
+
+/*!
+ * Stops the timer when some events occurred while waiting for them.
+ * media source started buffering or call back is received etc.
+*/
+
+void S60MediaPlayerSession::stopStalledTimer()
+{
+ DP0("S60MediaPlayerSession::stopStalledTimer +++");
+
+ m_stalledTimer->stop();
+
+ DP0("S60MediaPlayerSession::stopStalledTimer ---");
+}
+
+/*!
+ * \return Converted Symbian specific Descriptor to QString.
+*/
+
+QString S60MediaPlayerSession::TDesC2QString(const TDesC& aDescriptor)
+{
+ DP0("S60MediaPlayerSession::TDesC2QString");
+
+ return QString::fromUtf16(aDescriptor.Ptr(), aDescriptor.Length());
+}
+
+/*!
+ * \return Converted QString to non-modifiable pointer Descriptor.
+*/
+
+TPtrC S60MediaPlayerSession::QString2TPtrC( const QString& string )
+{
+ DP0("S60MediaPlayerSession::QString2TPtrC");
+
+ // Returned TPtrC is valid as long as the given parameter is valid and unmodified
+ return TPtrC16(static_cast<const TUint16*>(string.utf16()), string.length());
+}
+
+/*!
+ * \return Converted Symbian TRect object to QRect object.
+*/
+
+QRect S60MediaPlayerSession::TRect2QRect(const TRect& tr)
+{
+ DP0("S60MediaPlayerSession::TRect2QRect");
+
+ return QRect(tr.iTl.iX, tr.iTl.iY, tr.Width(), tr.Height());
+}
+
+/*!
+ * \return converted QRect object to Symbian specific TRec object.
+ */
+
+TRect S60MediaPlayerSession::QRect2TRect(const QRect& qr)
+{
+ DP0("S60MediaPlayerSession::QRect2TRect");
+
+ return TRect(TPoint(qr.left(), qr.top()), TSize(qr.width(), qr.height()));
+}
+
+/*!
+ \fn bool S60MediaPlayerSession::isVideoAvailable();
+
+
+ Returns TRUE if Video is available.
+*/
+
+/*!
+ \fn bool S60MediaPlayerSession::isAudioAvailable();
+
+
+ Returns TRUE if Audio is available.
+*/
+
+/*!
+ \fn void S60MediaPlayerSession::setPlaybackRate (qreal rate);
+
+
+ Sets \a rate play back rate on media source. getIsSeekable
+*/
+
+/*!
+ \fn bool S60MediaPlayerSession::getIsSeekable () const;
+
+
+ \return TRUE if Seekable possible on current media source else FALSE.
+*/
+
+/*!
+ \fn QString S60MediaPlayerSession::activeEndpoint () const;
+
+
+ \return active end point name..
+*/
+
+/*!
+ \fn QString S60MediaPlayerSession::defaultEndpoint () const;
+
+
+ \return default end point name.
+*/
+
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediaplayersession.h b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayersession.h
new file mode 100644
index 000000000..e6889d101
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediaplayersession.h
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60MEDIAPLAYERSESSION_H
+#define S60MEDIAPLAYERSESSION_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qpair.h>
+#include <qmediaplayer.h>
+#include <e32cmn.h> // for TDesC
+#include <QRect>
+#include "s60mediaplayerservice.h"
+
+
+_LIT( KSeekable, "Seekable" );
+_LIT( KFalse, "0");
+
+QT_BEGIN_NAMESPACE
+class QMediaTimeRange;
+QT_END_NAMESPACE
+
+class QTimer;
+
+class S60MediaPlayerSession : public QObject
+{
+ Q_OBJECT
+
+public:
+ S60MediaPlayerSession(QObject *parent);
+ virtual ~S60MediaPlayerSession();
+
+ // for player control interface to use
+ QMediaPlayer::State state() const;
+ QMediaPlayer::MediaStatus mediaStatus() const;
+ qint64 duration() const;
+ qint64 position() const;
+ void setPosition(qint64 pos);
+ int volume() const;
+ void setVolume(int volume);
+ bool isMuted() const;
+ void setMuted(bool muted);
+ virtual bool isVideoAvailable() = 0;
+ virtual bool isAudioAvailable() = 0;
+ bool isSeekable() const;
+ void play();
+ void pause();
+ void stop();
+ void reset();
+ bool isMetadataAvailable() const;
+ QVariant metaData(const QString &key) const;
+ QVariant metaData(QtMultimediaKit::MetaData key) const;
+ QList<QtMultimediaKit::MetaData> availableMetaData() const;
+ QStringList availableExtendedMetaData() const;
+ QString metaDataKeyAsString(QtMultimediaKit::MetaData key) const;
+ void load(const QMediaContent source);
+ int bufferStatus();
+ virtual void setVideoRenderer(QObject *renderer);
+ void setMediaStatus(QMediaPlayer::MediaStatus);
+ void setState(QMediaPlayer::State state);
+ void setAudioEndpoint(const QString& audioEndpoint);
+ virtual void setPlaybackRate(qreal rate) = 0;
+ virtual bool getIsSeekable() const { return ETrue; }
+ TBool isStreaming();
+
+protected:
+ virtual void doLoadL(const TDesC &path) = 0;
+ virtual void doLoadUrlL(const TDesC &path) = 0;
+ virtual void doPlay() = 0;
+ virtual void doStop() = 0;
+ virtual void doClose() = 0;
+ virtual void doPauseL() = 0;
+ virtual void doSetVolumeL(int volume) = 0;
+ virtual void doSetPositionL(qint64 microSeconds) = 0;
+ virtual qint64 doGetPositionL() const = 0;
+ virtual void updateMetaDataEntriesL() = 0;
+ virtual int doGetBufferStatusL() const = 0;
+ virtual qint64 doGetDurationL() const = 0;
+ virtual void doSetAudioEndpoint(const QString& audioEndpoint) = 0;
+
+public:
+ // From S60MediaPlayerAudioEndpointSelector
+ virtual QString activeEndpoint() const = 0;
+ virtual QString defaultEndpoint() const = 0;
+public Q_SLOTS:
+ virtual void setActiveEndpoint(const QString& name) = 0;
+
+protected:
+ int error() const;
+ void setError(int error, const QString &errorString = QString(), bool forceReset = false);
+ void setAndEmitError(int error);
+ void loaded();
+ void buffering();
+ void buffered();
+ void endOfMedia();
+ QMap<QString, QVariant>& metaDataEntries();
+ QMediaPlayer::Error fromSymbianErrorToMultimediaError(int error);
+ void startProgressTimer();
+ void stopProgressTimer();
+ void startStalledTimer();
+ void stopStalledTimer();
+ QString TDesC2QString(const TDesC& aDescriptor);
+ TPtrC QString2TPtrC( const QString& string );
+ QRect TRect2QRect(const TRect& tr);
+ TRect QRect2TRect(const QRect& qr);
+
+protected slots:
+ void tick();
+ void stalled();
+
+signals:
+ void durationChanged(qint64 duration);
+ void positionChanged(qint64 position);
+ void stateChanged(QMediaPlayer::State state);
+ void mediaStatusChanged(QMediaPlayer::MediaStatus mediaStatus);
+ void videoAvailableChanged(bool videoAvailable);
+ void audioAvailableChanged(bool audioAvailable);
+ void bufferStatusChanged(int percentFilled);
+ void seekableChanged(bool);
+ void availablePlaybackRangesChanged(const QMediaTimeRange&);
+ void metaDataChanged();
+ void error(int error, const QString &errorString);
+ void activeEndpointChanged(const QString &name);
+ void mediaChanged();
+ void playbackRateChanged(qreal rate);
+ void volumeChanged(int volume);
+ void mutedChanged(bool muted);
+
+protected:
+ QUrl m_UrlPath;
+ bool m_stream;
+ QMediaContent m_source;
+
+private:
+ qreal m_playbackRate;
+ QMap<QString, QVariant> m_metaDataMap;
+ bool m_muted;
+ int m_volume;
+ QMediaPlayer::State m_state;
+ QMediaPlayer::MediaStatus m_mediaStatus;
+ QTimer *m_progressTimer;
+ QTimer *m_stalledTimer;
+ int m_error;
+ bool m_play_requested;
+ bool m_seekable;
+ qint64 m_duration;
+};
+
+#endif
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediarecognizer.cpp b/src/plugins/symbian/mmf/mediaplayer/s60mediarecognizer.cpp
new file mode 100644
index 000000000..48b565c34
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediarecognizer.cpp
@@ -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$
+** 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 "DebugMacros.h"
+
+#include "s60mediarecognizer.h"
+#include <e32def.h>
+#include <e32cmn.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qdebug.h>
+
+#include <apgcli.h>
+
+static const TInt KMimeTypePrefixLength = 6; // "audio/" or "video/"
+
+_LIT(KMimeTypePrefixAudio, "audio/");
+_LIT(KMimeTypePrefixVideo, "video/");
+_LIT(KMimeTypeRingingTone, "application/vnd.nokia.ringing-tone");
+
+/*!
+ Construct a media Recognizer with the given \a parent.
+*/
+
+S60MediaRecognizer::S60MediaRecognizer(QObject *parent) : QObject(parent)
+{
+ DP0("S60MediaRecognizer::S60MediaRecognizer +++");
+ DP0("S60MediaRecognizer::S60MediaRecognizer ---");
+}
+
+/*!
+ Destroys a media Recognizer.
+*/
+
+S60MediaRecognizer::~S60MediaRecognizer()
+{
+ DP0("S60MediaRecognizer::~S60MediaRecognizer +++");
+
+ m_file.Close();
+ m_fileServer.Close();
+ m_recognizer.Close();
+
+ DP0("S60MediaRecognizer::~S60MediaRecognizer ---");
+}
+
+/*!
+ * \return media type of \a url.
+ * \a url may be a streaming link or a local file.
+ * If \a url is local file then identifies the media type and returns it.
+*/
+
+S60MediaRecognizer::MediaType S60MediaRecognizer::mediaType(const QUrl &url)
+{
+ DP0("S60MediaRecognizer::mediaType");
+
+ bool isStream = (url.scheme() == "file")?false:true;
+
+ if (isStream)
+ return Url;
+ else
+ return identifyMediaType(QDir::cleanPath(url.toLocalFile()));
+}
+
+/*!
+ * \return Media type of \a file name by recognizing its mimetype whether its audio or video.
+*/
+
+S60MediaRecognizer::MediaType S60MediaRecognizer::identifyMediaType(const QString& fileName)
+{
+ DP0("S60MediaRecognizer::identifyMediaType +++");
+
+ DP1("S60MediaRecognizer::identifyMediaType - ", fileName);
+
+ S60MediaRecognizer::MediaType result = Video; // default to videoplayer
+ bool recognizerOpened = false;
+
+ TInt err = m_recognizer.Connect();
+ if (err == KErrNone) {
+ recognizerOpened = true;
+ }
+
+ err = m_fileServer.Connect();
+ if (err == KErrNone) {
+ recognizerOpened = true;
+ }
+
+ // This is needed for sharing file handles for the recognizer
+ err = m_fileServer.ShareProtected();
+ if (err == KErrNone) {
+ recognizerOpened = true;
+ }
+
+ if (recognizerOpened) {
+ m_file.Close();
+ err = m_file.Open(m_fileServer, QString2TPtrC(QDir::toNativeSeparators(fileName)), EFileRead |
+ EFileShareReadersOnly);
+
+ if (err == KErrNone) {
+ TDataRecognitionResult recognizerResult;
+ err = m_recognizer.RecognizeData(m_file, recognizerResult);
+ if (err == KErrNone) {
+ const TPtrC mimeType = recognizerResult.iDataType.Des();
+
+ if (mimeType.Left(KMimeTypePrefixLength).Compare(KMimeTypePrefixAudio) == 0 ||
+ mimeType.Compare(KMimeTypeRingingTone) == 0) {
+ result = Audio;
+ } else if (mimeType.Left(KMimeTypePrefixLength).Compare(KMimeTypePrefixVideo) == 0) {
+ result = Video;
+ }
+ }
+ }
+ }
+
+ DP0("S60MediaRecognizer::identifyMediaType ---");
+
+ return result;
+}
+
+/*!
+ * \return Symbian modifiable pointer descriptor from a QString \a string.
+ */
+
+TPtrC S60MediaRecognizer::QString2TPtrC( const QString& string )
+{
+ DP1("S60MediaRecognizer::QString2TPtrC - ", string);
+
+ // Returned TPtrC is valid as long as the given parameter is valid and unmodified
+ return TPtrC16(static_cast<const TUint16*>(string.utf16()), string.length());
+}
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediarecognizer.h b/src/plugins/symbian/mmf/mediaplayer/s60mediarecognizer.h
new file mode 100644
index 000000000..bdd0caabe
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediarecognizer.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60MEDIARECOGNIZER_H_
+#define S60MEDIARECOGNIZER_H_
+
+#include <QtCore/qobject.h>
+
+#include <apgcli.h>
+#include <f32file.h>
+
+class QUrl;
+
+class S60MediaRecognizer : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum MediaType {
+ Audio,
+ Video,
+ Url,
+ NotSupported = -1
+ };
+
+ S60MediaRecognizer(QObject *parent = 0);
+ ~S60MediaRecognizer();
+
+ S60MediaRecognizer::MediaType mediaType(const QUrl &url);
+ S60MediaRecognizer::MediaType identifyMediaType(const QString& fileName);
+
+protected:
+ TPtrC QString2TPtrC( const QString& string );
+
+private:
+ RApaLsSession m_recognizer;
+ RFile m_file;
+ RFs m_fileServer;
+};
+
+#endif /* S60MEDIARECOGNIZER_H_ */
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediastreamcontrol.cpp b/src/plugins/symbian/mmf/mediaplayer/s60mediastreamcontrol.cpp
new file mode 100644
index 000000000..9a2ce5c02
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediastreamcontrol.cpp
@@ -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$
+** 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 "DebugMacros.h"
+
+#include "s60mediastreamcontrol.h"
+#include "s60mediaplayersession.h"
+#include "s60mediaplayercontrol.h"
+#include <qmediastreamscontrol.h>
+
+#include <QtCore/qdir.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qdebug.h>
+
+/*!
+ Constructs a new media streams control with the given \a control.
+*/
+
+S60MediaStreamControl::S60MediaStreamControl(QObject *control, QObject *parent)
+ : QMediaStreamsControl(parent)
+ , m_control(NULL)
+ , m_mediaType(S60MediaSettings::Unknown)
+{
+ DP0("S60MediaStreamControl::S60MediaStreamControl +++");
+
+ m_control = qobject_cast<S60MediaPlayerControl*>(control);
+ m_mediaType = m_control->mediaControlSettings().mediaType();
+
+ DP0("S60MediaStreamControl::S60MediaStreamControl ---");
+}
+
+/*!
+ Destroys a media streams control.
+*/
+
+S60MediaStreamControl::~S60MediaStreamControl()
+{
+ DP0("S60MediaStreamControl::~S60MediaStreamControl +++");
+ DP0("S60MediaStreamControl::~S60MediaStreamControl ---");
+}
+
+/*!
+ \return the number of media streams.
+*/
+
+int S60MediaStreamControl::streamCount()
+{
+ DP0("S60MediaStreamControl::streamCount");
+
+ int streamCount = 0;
+ if (m_control->isAudioAvailable())
+ streamCount++;
+ if (m_control->isVideoAvailable())
+ streamCount++;
+ DP1("S60MediaStreamControl::streamCount", streamCount);
+
+ return streamCount;
+}
+
+/*!
+ \return the type of a media \a streamNumber.
+*/
+
+QMediaStreamsControl::StreamType S60MediaStreamControl::streamType(int streamNumber)
+{
+ DP0("S60MediaStreamControl::streamType +++");
+
+ DP1("S60MediaStreamControl::streamType - ", streamNumber);
+
+ Q_UNUSED(streamNumber);
+
+ QMediaStreamsControl::StreamType type = QMediaStreamsControl::UnknownStream;
+
+ if (m_control->mediaControlSettings().mediaType() == S60MediaSettings::Video)
+ type = QMediaStreamsControl::VideoStream;
+ else
+ type = QMediaStreamsControl::AudioStream;
+
+ DP0("S60MediaStreamControl::streamType ---");
+
+ return type;
+}
+
+/*!
+ \return the meta-data value of \a key for a given \a streamNumber.
+
+ Useful metadata keya are QtMultimediaKit::Title, QtMultimediaKit::Description and QtMultimediaKit::Language.
+*/
+
+QVariant S60MediaStreamControl::metaData(int streamNumber, QtMultimediaKit::MetaData key)
+{
+ DP0("S60MediaStreamControl::metaData");
+
+ Q_UNUSED(streamNumber);
+
+ if (m_control->session()) {
+ if (m_control->session()->isMetadataAvailable())
+ return m_control->session()->metaData(key);
+ }
+ return QVariant();
+}
+
+/*!
+ \return true if the media \a streamNumber is active else false.
+*/
+
+bool S60MediaStreamControl::isActive(int streamNumber)
+{
+ DP0("S60MediaStreamControl::isActive +++");
+
+ DP1("S60MediaStreamControl::isActive - ", streamNumber);
+
+ if (m_control->mediaControlSettings().mediaType() == S60MediaSettings::Video) {
+ switch (streamNumber) {
+ case 1:
+ return m_control->isVideoAvailable();
+ case 2:
+ return m_control->isAudioAvailable();
+ default:
+ break;
+ }
+ }
+
+ DP0("S60MediaStreamControl::isActive ---");
+
+ return m_control->isAudioAvailable();
+}
+
+/*!
+ Sets the active \a streamNumber of a media \a state.
+
+ Symbian MMF does not support enabling or disabling specific media streams.
+
+ Setting the active state of a media stream to true will activate it. If any other stream
+ of the same type was previously active it will be deactivated. Setting the active state fo a
+ media stream to false will deactivate it.
+*/
+
+void S60MediaStreamControl::setActive(int streamNumber, bool state)
+{
+ DP0("S60MediaStreamControl::setActive +++");
+
+ DP2("S60MediaStreamControl::setActive - ", streamNumber, state);
+
+ Q_UNUSED(streamNumber);
+ Q_UNUSED(state);
+ // Symbian MMF does not support enabling or disabling specific media streams
+
+ DP0("S60MediaStreamControl::setActive ---");
+}
+
+/*!
+ The signal is emitted when the available streams list is changed.
+*/
+
+void S60MediaStreamControl::handleStreamsChanged()
+{
+ DP0("S60MediaStreamControl::handleStreamsChanged +++");
+
+ emit streamsChanged();
+
+ DP0("S60MediaStreamControl::handleStreamsChanged ---");
+}
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60mediastreamcontrol.h b/src/plugins/symbian/mmf/mediaplayer/s60mediastreamcontrol.h
new file mode 100644
index 000000000..702ebc7b2
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60mediastreamcontrol.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60MEDIASTREAMCONTROL_H
+#define S60MEDIASTREAMCONTROL_H
+
+#include <QVariant>
+
+#include "s60mediaplayercontrol.h"
+
+#include <qmediastreamscontrol.h>
+#include <qtmedianamespace.h>
+
+QT_USE_NAMESPACE
+
+class S60MediaPlayerControl;
+class S60MediaSettings;
+
+class S60MediaStreamControl : public QMediaStreamsControl
+{
+ Q_OBJECT
+public:
+ S60MediaStreamControl(QObject *session, QObject *parent = 0);
+ ~S60MediaStreamControl();
+
+ // from QMediaStreamsControl
+ int streamCount();
+ QMediaStreamsControl::StreamType streamType(int streamNumber);
+ QVariant metaData(int streamNumber, QtMultimediaKit::MetaData key);
+ bool isActive(int streamNumber);
+ void setActive(int streamNumber, bool state);
+
+public Q_SLOTS:
+ void handleStreamsChanged();
+
+private:
+ S60MediaPlayerControl *m_control;
+ S60MediaSettings::TMediaType m_mediaType;
+};
+
+#endif //S60MEDIASTREAMCONTROL_H
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60videooutputinterface.h b/src/plugins/symbian/mmf/mediaplayer/s60videooutputinterface.h
new file mode 100644
index 000000000..f5388dbbc
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60videooutputinterface.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60VIDEOOUTPUTINTERFACE_H
+#define S60VIDEOOUTPUTINTERFACE_H
+
+#include <QtCore/qglobal.h>
+#include <QtGui/qwindowdefs.h>
+#include <coecntrl.h>
+
+class S60VideoOutputInterface
+{
+public:
+ RWindow *videoWindowHandle() const { return videoWinId() ? static_cast<RWindow *>(videoWinId()->DrawableWindow()) : 0 ; }
+ virtual WId videoWinId() const = 0;
+ // If VIDEOOUTPUT_GRAPHICS_SURFACES is defined, the return value is the video
+ // rectangle relative to the video window. If not, the return value is the
+ // absolute screen rectangle.
+ virtual QRect videoDisplayRect() const = 0;
+ virtual Qt::AspectRatioMode videoAspectRatio() const = 0;
+};
+
+#endif // S60VIDEOOUTPUTINTERFACE_H
+
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60videoplayersession.cpp b/src/plugins/symbian/mmf/mediaplayer/s60videoplayersession.cpp
new file mode 100644
index 000000000..49d511ca2
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60videoplayersession.cpp
@@ -0,0 +1,1124 @@
+/****************************************************************************
+**
+** 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$
+** 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 "DebugMacros.h"
+
+#include "s60videoplayersession.h"
+#include "s60mediaplayerservice.h"
+#include "s60videowidgetcontrol.h"
+#include "s60videowidgetdisplay.h"
+#include "s60videowindowcontrol.h"
+#include "s60videowindowdisplay.h"
+
+#include <QtCore/QTimer>
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QSymbianEvent>
+#include <QtGui/QWidget>
+
+#include <coecntrl.h>
+#include <coemain.h> // For CCoeEnv
+#include <w32std.h>
+#include <mmf/common/mmferrors.h>
+#include <mmf/common/mmfcontrollerframeworkbase.h>
+#include <MMFROPCustomCommandConstants.h>
+#ifdef HTTP_COOKIES_ENABLED
+#include <MMFSessionInfoCustomCommandConstants.h>
+#endif
+
+const QString DefaultAudioEndpoint = QLatin1String("Default");
+const TUid KHelixUID = {0x101F8514};
+
+//Hard-coding the command to support older versions.
+const TInt KMMFROPControllerEnablePausedLoadingStatus = 7;
+
+TVideoRotation videoRotation(qreal angle)
+{
+ // Convert to clockwise
+ angle = 360.0f - angle;
+ while (angle >= 360.0f)
+ angle -= 360.0f;
+ TVideoRotation result = EVideoRotationNone;
+ if (angle >= 45.0f && angle < 135.0f)
+ result = EVideoRotationClockwise90;
+ else if (angle >= 135.0f && angle < 225.0f)
+ result = EVideoRotationClockwise180;
+ else if (angle >= 225.0f && angle < 315.0f)
+ result = EVideoRotationClockwise270;
+ return result;
+}
+
+S60VideoPlayerEventHandler *S60VideoPlayerEventHandler::m_instance = 0;
+QCoreApplication::EventFilter S60VideoPlayerEventHandler::m_eventFilter = 0;
+QList<ApplicationFocusObserver *> S60VideoPlayerEventHandler::m_applicationFocusObservers;
+
+S60VideoPlayerEventHandler *S60VideoPlayerEventHandler::instance()
+{
+ if (!m_instance)
+ m_instance = new S60VideoPlayerEventHandler();
+ return m_instance;
+}
+
+S60VideoPlayerEventHandler::S60VideoPlayerEventHandler()
+{
+ m_eventFilter = QCoreApplication::instance()->setEventFilter(filterEvent);
+}
+
+S60VideoPlayerEventHandler::~S60VideoPlayerEventHandler()
+{
+ QCoreApplication::instance()->setEventFilter(m_eventFilter);
+}
+
+void S60VideoPlayerEventHandler::addApplicationFocusObserver(ApplicationFocusObserver *observer)
+{
+ m_applicationFocusObservers.append(observer);
+}
+
+void S60VideoPlayerEventHandler::removeApplicationFocusObserver(ApplicationFocusObserver *observer)
+{
+ m_applicationFocusObservers.removeAt(m_applicationFocusObservers.indexOf(observer));
+ if (m_applicationFocusObservers.count() == 0) {
+ delete m_instance;
+ m_instance = 0;
+ }
+}
+
+bool S60VideoPlayerEventHandler::filterEvent(void *message, long *result)
+{
+ if (const QSymbianEvent *symbianEvent = reinterpret_cast<const QSymbianEvent*>(message)) {
+ switch (symbianEvent->type()) {
+ case QSymbianEvent::WindowServerEvent:
+ {
+ const TWsEvent *wsEvent = symbianEvent->windowServerEvent();
+ if (EEventFocusLost == wsEvent->Type() || EEventFocusGained == wsEvent->Type()) {
+ for (QList<ApplicationFocusObserver *>::const_iterator it = m_applicationFocusObservers.constBegin();
+ it != m_applicationFocusObservers.constEnd(); ++it) {
+ if (EEventFocusLost == wsEvent->Type())
+ (*it)->applicationLostFocus();
+ else if (EEventFocusGained == wsEvent->Type())
+ (*it)->applicationGainedFocus();
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ bool ret = false;
+ if (m_eventFilter)
+ ret = m_eventFilter(message, result);
+ return ret;
+}
+
+/*!
+ Constructs the CVideoPlayerUtility2 object with given \a service and \a object.
+ And Registers for Video Loading Notifications.
+*/
+S60VideoPlayerSession::S60VideoPlayerSession(QMediaService *service, S60MediaNetworkAccessControl *object)
+ : S60MediaPlayerSession(service)
+ , m_accessPointId(0)
+ , m_wsSession(&CCoeEnv::Static()->WsSession())
+ , m_screenDevice(CCoeEnv::Static()->ScreenDevice())
+ , m_service(service)
+ , m_player(0)
+#ifndef VIDEOOUTPUT_GRAPHICS_SURFACES
+ , m_dsaActive(false)
+ , m_dsaStopped(false)
+#endif
+ , m_videoOutputControl(0)
+ , m_videoOutputDisplay(0)
+ , m_displayWindow(0)
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ , m_audioOutput(0)
+#endif
+ , m_audioEndpoint(DefaultAudioEndpoint)
+ , m_pendingChanges(0)
+ , m_backendInitiatedPause(false)
+#ifdef HTTP_COOKIES_ENABLED
+ , m_destinationPckg(KUidInterfaceMMFControllerSessionInfo)
+#endif
+{
+ DP0("S60VideoPlayerSession::S60VideoPlayerSession +++");
+
+ m_networkAccessControl = object;
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ QT_TRAP_THROWING(m_player = CVideoPlayerUtility2::NewL(
+ *this,
+ 0,
+ EMdaPriorityPreferenceNone
+ ));
+ m_player->RegisterForVideoLoadingNotification(*this);
+#else
+ RWindow *window = 0;
+ QRect extentRect;
+ QWidget *widget = QApplication::activeWindow();
+ if (!widget)
+ widget = QApplication::allWidgets().at(0);
+ Q_ASSERT(widget);
+ WId wid = widget->effectiveWinId();
+ if (!wid)
+ wid = widget->winId();
+ window = static_cast<RWindow *>(wid->DrawableWindow());
+ extentRect = QRect(widget->mapToGlobal(widget->pos()), widget->size());
+ TRect clipRect = QRect2TRect(extentRect);
+ const TRect desktopRect = QRect2TRect(QApplication::desktop()->screenGeometry());
+ clipRect.Intersection(desktopRect);
+ QT_TRAP_THROWING(m_player = CVideoPlayerUtility::NewL(
+ *this,
+ 0,
+ EMdaPriorityPreferenceNone,
+ *m_wsSession,
+ *m_screenDevice,
+ *window,
+ QRect2TRect(extentRect),
+ clipRect));
+ m_dsaActive = true;
+ m_player->RegisterForVideoLoadingNotification(*this);
+#endif // VIDEOOUTPUT_GRAPHICS_SURFACES
+ S60VideoPlayerEventHandler::instance()->addApplicationFocusObserver(this);
+ DP0("S60VideoPlayerSession::S60VideoPlayerSession ---");
+}
+
+/*!
+ Destroys the CVideoPlayerUtility2 object.
+
+ And Unregister the observer.
+*/
+
+S60VideoPlayerSession::~S60VideoPlayerSession()
+{
+ DP0("S60VideoPlayerSession::~S60VideoPlayerSession +++");
+ S60VideoPlayerEventHandler::instance()->removeApplicationFocusObserver(this);
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ if (m_audioOutput)
+ m_audioOutput->UnregisterObserver(*this);
+ delete m_audioOutput;
+#endif
+ m_player->Close();
+ delete m_player;
+
+ DP0("S60VideoPlayerSession::~S60VideoPlayerSession ---");
+}
+
+void S60VideoPlayerSession::applicationGainedFocus()
+{
+ if (m_backendInitiatedPause) {
+ m_backendInitiatedPause = false;
+ play();
+ }
+ if (QMediaPlayer::PausedState == state()) {
+ TRAPD(err, m_player->RefreshFrameL());
+ setError(err);
+ }
+}
+
+void S60VideoPlayerSession::applicationLostFocus()
+{
+ if (QMediaPlayer::PlayingState == state()) {
+ m_backendInitiatedPause = true;
+ pause();
+ }
+}
+
+/*!
+
+ Opens the a file from \a path.
+*/
+
+void S60VideoPlayerSession::doLoadL(const TDesC &path)
+{
+ DP0("S60VideoPlayerSession::doLoadL +++");
+
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ // m_audioOutput needs to be reinitialized after MapcInitComplete
+ if (m_audioOutput)
+ m_audioOutput->UnregisterObserver(*this);
+ delete m_audioOutput;
+ m_audioOutput = NULL;
+#endif
+ m_player->OpenFileL(path, KHelixUID);
+
+ DP0("S60VideoPlayerSession::doLoadL ---");
+}
+
+/*!
+ Sets the playbackRate with \a rate.
+*/
+
+void S60VideoPlayerSession::setPlaybackRate(qreal rate)
+{
+ DP0("S60VideoPlayerSession::setPlaybackRate +++");
+
+ DP1("S60VideoPlayerSession::setPlaybackRate - ", rate);
+
+ /*
+ * setPlaybackRate is not supported in S60 3.1 and 3.2
+ * This flag will be defined for 3.1 and 3.2
+ */
+#ifndef PLAY_RATE_NOT_SUPPORTED
+ //setPlayVelocity requires rate in the form of
+ //50 = 0.5x ;100 = 1.x ; 200 = 2.x ; 300 = 3.x
+ //so multiplying rate with 100
+ TRAPD(err, m_player->SetPlayVelocityL((TInt)(rate*100)));
+ if (KErrNone == err)
+ emit playbackRateChanged(rate);
+ else
+ setError(err);
+#endif
+
+ DP0("S60VideoPlayerSession::setPlaybackRate ---");
+}
+
+/*!
+
+ Opens the a Url from \a path for streaming the source.
+*/
+
+void S60VideoPlayerSession::doLoadUrlL(const TDesC &path)
+{
+ DP0("S60VideoPlayerSession::doLoadUrlL +++");
+
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ // m_audioOutput needs to be reinitialized after MapcInitComplete
+ if (m_audioOutput)
+ m_audioOutput->UnregisterObserver(*this);
+ delete m_audioOutput;
+ m_audioOutput = NULL;
+#endif
+ m_accessPointId = m_networkAccessControl->accessPointId();
+ m_player->OpenUrlL(path, m_accessPointId, KNullDesC8, KHelixUID);
+
+ DP0("S60VideoPlayerSession::doLoadUrlL ---");
+}
+
+/*!
+
+ Returns the percentage of the video clip loaded.
+*/
+
+int S60VideoPlayerSession::doGetBufferStatusL() const
+{
+ // DP0("S60VideoPlayerSession::doGetBufferStatusL +++");
+
+ int progress = 0;
+ m_player->GetVideoLoadingProgressL(progress);
+
+ // DP0("S60VideoPlayerSession::doGetBufferStatusL ---");
+
+ return progress;
+}
+
+/*!
+ Returns the duration of the video sample in microseconds.
+*/
+
+qint64 S60VideoPlayerSession::doGetDurationL() const
+{
+ // DP0("S60VideoPlayerSession::doGetDurationL");
+
+ return m_player->DurationL().Int64() / qint64(1000);
+}
+
+/*!
+ * Sets the \a videooutput for video rendering.
+*/
+
+void S60VideoPlayerSession::setVideoRenderer(QObject *videoOutput)
+{
+ DP0("S60VideoPlayerSession::setVideoRenderer +++");
+ if (videoOutput != m_videoOutputControl) {
+ if (m_videoOutputDisplay) {
+ disconnect(m_videoOutputDisplay);
+ m_videoOutputDisplay->disconnect(this);
+ m_videoOutputDisplay = 0;
+ }
+ if (videoOutput) {
+ if (S60VideoWidgetControl *control = qobject_cast<S60VideoWidgetControl *>(videoOutput))
+ m_videoOutputDisplay = control->display();
+ if (!m_videoOutputDisplay)
+ return;
+ m_videoOutputDisplay->setNativeSize(m_nativeSize);
+ connect(this, SIGNAL(nativeSizeChanged(QSize)), m_videoOutputDisplay, SLOT(setNativeSize(QSize)));
+ connect(m_videoOutputDisplay, SIGNAL(windowHandleChanged(RWindow *)), this, SLOT(windowHandleChanged()));
+ connect(m_videoOutputDisplay, SIGNAL(displayRectChanged(QRect, QRect)), this, SLOT(displayRectChanged()));
+ connect(m_videoOutputDisplay, SIGNAL(aspectRatioModeChanged(Qt::AspectRatioMode)), this, SLOT(aspectRatioChanged()));
+ connect(m_videoOutputDisplay, SIGNAL(rotationChanged(qreal)), this, SLOT(rotationChanged()));
+#ifndef VIDEOOUTPUT_GRAPHICS_SURFACES
+ connect(m_videoOutputDisplay, SIGNAL(beginVideoWindowNativePaint()), this, SLOT(suspendDirectScreenAccess()));
+ connect(m_videoOutputDisplay, SIGNAL(endVideoWindowNativePaint()), this, SLOT(resumeDirectScreenAccess()));
+#endif
+ }
+ m_videoOutputControl = videoOutput;
+ windowHandleChanged();
+ }
+
+ DP0("S60VideoPlayerSession::setVideoRenderer ---");
+}
+
+/*!
+ * Apply the pending changes for window.
+*/
+void S60VideoPlayerSession::applyPendingChanges(bool force)
+{
+ DP0("S60VideoPlayerSession::applyPendingChanges +++");
+
+ if ( force
+ || QMediaPlayer::LoadedMedia == mediaStatus()
+ || QMediaPlayer::StalledMedia == mediaStatus()
+ || QMediaPlayer::BufferingMedia == mediaStatus()
+ || QMediaPlayer::BufferedMedia == mediaStatus()
+ || QMediaPlayer::EndOfMedia == mediaStatus()) {
+ int error = KErrNone;
+ RWindow *const window = m_videoOutputDisplay ? m_videoOutputDisplay->windowHandle() : 0;
+ const QRect extentRect = m_videoOutputDisplay ? m_videoOutputDisplay->extentRect() : QRect();
+ const QRect clipRect = m_videoOutputDisplay ? m_videoOutputDisplay->clipRect() : QRect();
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ if (m_pendingChanges & WindowHandle) {
+ if (m_displayWindow) {
+ m_player->RemoveDisplayWindow(*m_displayWindow);
+ m_displayWindow = 0;
+ }
+ if (window) {
+ TRAP(error, m_player->AddDisplayWindowL(*m_wsSession, *m_screenDevice,
+ *window,
+ QRect2TRect(extentRect),
+ QRect2TRect(clipRect)));
+ if (KErrNone == error)
+ m_displayWindow = window;
+ }
+ m_pendingChanges = ScaleFactors;
+ }
+ if (KErrNone == error && (m_pendingChanges & DisplayRect) && m_displayWindow) {
+ TRAP(error, m_player->SetVideoExtentL(*m_displayWindow, QRect2TRect(extentRect)));
+ if (KErrNone == error)
+ TRAP(error, m_player->SetWindowClipRectL(*m_displayWindow, QRect2TRect(clipRect)));
+ m_pendingChanges ^= DisplayRect;
+ m_pendingChanges |= ScaleFactors;
+ }
+#else
+ if (m_pendingChanges & WindowHandle || m_pendingChanges & DisplayRect) {
+ if (window) {
+ TRAP(error, m_player->SetDisplayWindowL(*m_wsSession, *m_screenDevice,
+ *window,
+ QRect2TRect(extentRect),
+ QRect2TRect(clipRect)));
+ if (KErrNone == error)
+ m_displayWindow = window;
+ }
+ m_dsaActive = (KErrNone == error);
+ m_dsaStopped = false;
+ m_pendingChanges = ScaleFactors;
+ }
+
+#endif // VIDEOOUTPUT_GRAPHICS_SURFACES
+ if (KErrNone == error && (m_pendingChanges & ScaleFactors) && m_displayWindow && m_videoOutputDisplay) {
+ const TVideoRotation rotation = videoRotation(m_videoOutputDisplay->rotation());
+ const bool swap = (rotation == EVideoRotationClockwise90 || rotation == EVideoRotationClockwise270);
+ const QSize extentSize = swap ? QSize(extentRect.height(), extentRect.width()) : extentRect.size();
+ QSize scaled = m_nativeSize;
+ if (m_videoOutputDisplay->aspectRatioMode() == Qt::IgnoreAspectRatio)
+ scaled.scale(extentSize, Qt::IgnoreAspectRatio);
+ else if (m_videoOutputDisplay->aspectRatioMode() == Qt::KeepAspectRatio)
+ scaled.scale(extentSize, Qt::KeepAspectRatio);
+ else if (m_videoOutputDisplay->aspectRatioMode() == Qt::KeepAspectRatioByExpanding)
+ scaled.scale(extentSize, Qt::KeepAspectRatioByExpanding);
+ const qreal width = qreal(scaled.width()) / qreal(m_nativeSize.width()) * qreal(100);
+ const qreal height = qreal(scaled.height()) / qreal(m_nativeSize.height()) * qreal(100);
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ TRAP(error, m_player->SetScaleFactorL(*m_displayWindow, width, height));
+#else
+ static const TBool antialias = ETrue;
+ TRAP(error, m_player->SetScaleFactorL(width, height, antialias));
+#endif // VIDEOOUTPUT_GRAPHICS_SURFACES
+ m_pendingChanges ^= ScaleFactors;
+ }
+ if (KErrNone == error && (m_pendingChanges && Rotation) && m_displayWindow && m_videoOutputDisplay) {
+ const TVideoRotation rotation = videoRotation(m_videoOutputDisplay->rotation());
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ TRAP(error, m_player->SetRotationL(*m_displayWindow, rotation));
+#else
+ TRAP(error, m_player->SetRotationL(rotation));
+#endif // VIDEOOUTPUT_GRAPHICS_SURFACES
+ m_pendingChanges ^= Rotation;
+ }
+ setError(error);
+ }
+
+ DP0("S60VideoPlayerSession::applyPendingChanges ---");
+}
+
+/*!
+ * \return TRUE if video is available.
+*/
+
+bool S60VideoPlayerSession::isVideoAvailable()
+{
+ DP0("S60VideoPlayerSession::isVideoAvailable");
+
+#ifdef PRE_S60_50_PLATFORM
+ return true; // this is not supported in pre 5th platforms
+#else
+ if ( mediaStatus() == QMediaPlayer::LoadingMedia
+ || mediaStatus() == QMediaPlayer::UnknownMediaStatus
+ || mediaStatus() == QMediaPlayer::NoMedia
+ || (mediaStatus() == QMediaPlayer::StalledMedia && state() == QMediaPlayer::StoppedState)
+ || mediaStatus() == QMediaPlayer::InvalidMedia)
+ return false;
+
+ if (m_player) {
+ bool videoAvailable = false;
+ TRAPD(err, videoAvailable = m_player->VideoEnabledL());
+ setError(err);
+ return videoAvailable;
+ } else {
+ return false;
+ }
+#endif
+
+}
+
+/*!
+ * \return TRUE if Audio available.
+*/
+
+bool S60VideoPlayerSession::isAudioAvailable()
+{
+ DP0("S60VideoPlayerSession::isAudioAvailable");
+
+ if ( mediaStatus() == QMediaPlayer::LoadingMedia
+ || mediaStatus() == QMediaPlayer::UnknownMediaStatus
+ || mediaStatus() == QMediaPlayer::NoMedia
+ || (mediaStatus() == QMediaPlayer::StalledMedia && state() == QMediaPlayer::StoppedState)
+ || mediaStatus() == QMediaPlayer::InvalidMedia)
+ return false;
+
+ if (m_player) {
+ bool audioAvailable = false;
+ TRAPD(err, audioAvailable = m_player->AudioEnabledL());
+ setError(err);
+ return audioAvailable;
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Start or resume playing the current source.
+*/
+
+void S60VideoPlayerSession::doPlay()
+{
+ DP0("S60VideoPlayerSession::doPlay +++");
+
+ m_player->Play();
+
+ DP0("S60VideoPlayerSession::doPlay ---");
+}
+
+/*!
+ Pause playing the current source.
+*/
+
+void S60VideoPlayerSession::doPauseL()
+{
+ DP0("S60VideoPlayerSession::doPauseL +++");
+
+ m_player->PauseL();
+
+ DP0("S60VideoPlayerSession::doPauseL ---");
+}
+
+/*!
+
+ Stop playing, and reset the play position to the beginning.
+*/
+
+void S60VideoPlayerSession::doStop()
+{
+ DP0("S60VideoPlayerSession::doStop +++");
+
+ if (m_stream)
+ m_networkAccessControl->resetIndex();
+
+ m_player->Stop();
+
+ DP0("S60VideoPlayerSession::doStop ---");
+}
+
+/*!
+ Closes the current audio clip (allowing another clip to be opened)
+*/
+
+void S60VideoPlayerSession::doClose()
+{
+ DP0("S60VideoPlayerSession::doClose +++");
+
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ if (m_audioOutput) {
+ m_audioOutput->UnregisterObserver(*this);
+ delete m_audioOutput;
+ m_audioOutput = NULL;
+ }
+#endif
+
+ m_player->Close();
+
+// close will remove the window handle in media clint video.
+// So mark it in pending changes.
+ m_pendingChanges |= WindowHandle;
+
+ DP0("S60VideoPlayerSession::doClose ---");
+}
+
+/*!
+ * Returns the current playback position in microseconds from the start of the clip.
+
+*/
+
+qint64 S60VideoPlayerSession::doGetPositionL() const
+{
+ // DP0("S60VideoPlayerSession::doGetPositionL");
+
+ return m_player->PositionL().Int64() / qint64(1000);
+}
+
+/*!
+ Sets the current playback position to \a microSeconds from the start of the clip.
+*/
+
+void S60VideoPlayerSession::doSetPositionL(qint64 microSeconds)
+{
+ // DP0("S60VideoPlayerSession::doSetPositionL");
+
+ m_player->SetPositionL(TTimeIntervalMicroSeconds(microSeconds));
+}
+
+/*!
+
+ Changes the current playback volume to specified \a value.
+*/
+
+void S60VideoPlayerSession::doSetVolumeL(int volume)
+{
+ DP0("S60VideoPlayerSession::doSetVolumeL +++");
+
+ DP1("S60VideoPlayerSession::doSetVolumeL - ", volume);
+
+ m_player->SetVolumeL(volume * m_player->MaxVolume() / 100);
+
+ DP0("S60VideoPlayerSession::doSetVolumeL ---");
+}
+
+/*!
+ * Notification to the client that the opening of the video clip has completed.
+ * If successful then an \a aError will be ZERO else system wide error.
+*/
+
+void S60VideoPlayerSession::MvpuoOpenComplete(TInt aError)
+{
+ DP0("S60VideoPlayerSession::MvpuoOpenComplete +++");
+
+ DP1("S60VideoPlayerSession::MvpuoOpenComplete - aError:", aError);
+
+ setError(aError);
+#ifdef HTTP_COOKIES_ENABLED
+ if (KErrNone == aError) {
+ TInt err(KErrNone);
+ const QByteArray userAgentString("User-Agent");
+ TInt uasize = m_source.canonicalRequest().rawHeader(userAgentString).size();
+ TPtrC8 userAgent((const unsigned char*)(m_source.canonicalRequest().rawHeader(userAgentString).constData()), uasize);
+ if (userAgent.Length()) {
+ err = m_player->CustomCommandSync(m_destinationPckg, EMMFSetSessionInfo, _L8("User-Agent"), userAgent);
+ if (err != KErrNone) {
+ setError(err);
+ return;
+ }
+ }
+ const QByteArray refererString("Referer");
+ TInt refsize = m_source.canonicalRequest().rawHeader(refererString).size();
+ TPtrC8 referer((const unsigned char*)m_source.canonicalRequest().rawHeader(refererString).constData(),refsize);
+ if (referer.Length()) {
+ err = m_player->CustomCommandSync(m_destinationPckg, EMMFSetSessionInfo, _L8("Referer"), referer);
+ if (err != KErrNone) {
+ setError(err);
+ return;
+ }
+ }
+ const QByteArray cookieString("Cookie");
+ TInt cksize = m_source.canonicalRequest().rawHeader(cookieString).size();
+ TPtrC8 cookie((const unsigned char*)m_source.canonicalRequest().rawHeader(cookieString).constData(),cksize);
+ if (cookie.Length()) {
+ err = m_player->CustomCommandSync(m_destinationPckg, EMMFSetSessionInfo, _L8("Cookie"), cookie);
+ if (err != KErrNone) {
+ setError(err);
+ return;
+ }
+ }
+ m_player->Prepare();
+ }
+#else
+ if (KErrNone == aError)
+ m_player->Prepare();
+#endif
+ const TMMFMessageDestinationPckg dest( KUidInterfaceMMFROPController );
+ TRAP_IGNORE(m_player->CustomCommandSync(dest, KMMFROPControllerEnablePausedLoadingStatus, KNullDesC8, KNullDesC8));
+
+ DP0("S60VideoPlayerSession::MvpuoOpenComplete ---");
+}
+
+/*!
+ * Notification to the client that the opening of the video clip has been preapred.
+ * If successful then an \a aError will be ZERO else system wide error.
+*/
+
+void S60VideoPlayerSession::MvpuoPrepareComplete(TInt aError)
+{
+ DP0("S60VideoPlayerSession::MvpuoPrepareComplete +++");
+
+ DP1("S60VideoPlayerSession::MvpuoPrepareComplete - aError:", aError);
+
+ if (KErrNone == aError && m_stream) {
+ emit accessPointChanged(m_accessPointId);
+ }
+ if (KErrCouldNotConnect == aError && !(m_networkAccessControl->isLastAccessPoint())) {
+ load(m_source);
+ return;
+ }
+ TInt error = aError;
+ if (KErrNone == error || KErrMMPartialPlayback == error) {
+ TSize originalSize;
+ TRAP(error, m_player->VideoFrameSizeL(originalSize));
+ if (KErrNone == error) {
+ m_nativeSize = QSize(originalSize.iWidth, originalSize.iHeight);
+ emit nativeSizeChanged(m_nativeSize);
+ m_pendingChanges |= ScaleFactors;
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ Q_ASSERT(!m_audioOutput);
+ TRAP(error, m_audioOutput = CAudioOutput::NewL(*m_player));
+ if (KErrNone == error) {
+ TRAP(error, m_audioOutput->RegisterObserverL(*this));
+ if (KErrNone == error)
+ setActiveEndpoint(m_audioEndpoint);
+ }
+#endif
+ }
+ if (KErrNone == error) {
+ applyPendingChanges(true); // force apply even though state is not Loaded
+ if (KErrNone == this->error()) // applyPendingChanges() can call setError()
+ loaded();
+ }
+ } else {
+ setError(error);
+ }
+
+ DP0("S60VideoPlayerSession::MvpuoPrepareComplete ---");
+}
+
+/*!
+ * Notification that frame requested by a call to GetFrameL is ready.
+*/
+
+void S60VideoPlayerSession::MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError)
+{
+ DP0("S60VideoPlayerSession::MvpuoFrameReady +++");
+
+ Q_UNUSED(aFrame);
+ Q_UNUSED(aError);
+
+ DP0("S60VideoPlayerSession::MvpuoFrameReady ---");
+}
+
+/*!
+ * Notification that video playback has completed.
+ * If successful then \a aError will be ZERO else system wide error.
+ * This not called if playback is explicitly stopped by calling stop.
+*/
+
+void S60VideoPlayerSession::MvpuoPlayComplete(TInt aError)
+{
+ DP0("S60VideoPlayerSession::MvpuoPlayComplete +++");
+
+ DP1("S60VideoPlayerSession::MvpuoPlayComplete - aError", aError);
+
+ if (m_stream)
+ m_networkAccessControl->resetIndex();
+
+ if (aError != KErrNone) {
+ setError(aError);
+ doClose();
+ } else {
+ endOfMedia();
+ }
+
+ DP0("S60VideoPlayerSession::MvpuoPlayComplete ---");
+}
+
+
+/*!
+ * General \a event notification from controller.
+ * These events are specified by the supplier of the controller.
+*/
+
+void S60VideoPlayerSession::MvpuoEvent(const TMMFEvent &aEvent)
+{
+ DP0("S60VideoPlayerSession::MvpuoEvent +++");
+
+ Q_UNUSED(aEvent);
+
+ DP0("S60VideoPlayerSession::MvpuoEvent ---");
+}
+
+/*!
+
+ Updates meta data entries in the current video clip.
+*/
+
+void S60VideoPlayerSession::updateMetaDataEntriesL()
+{
+ DP0("S60VideoPlayerSession::updateMetaDataEntriesL +++");
+
+ metaDataEntries().clear();
+ int numberOfMetaDataEntries = 0;
+ numberOfMetaDataEntries = m_player->NumberOfMetaDataEntriesL();
+ for (int i = 0; i < numberOfMetaDataEntries; i++) {
+ CMMFMetaDataEntry *entry = NULL;
+ entry = m_player->MetaDataEntryL(i);
+ metaDataEntries().insert(TDesC2QString(entry->Name()), TDesC2QString(entry->Value()));
+ delete entry;
+ }
+ emit metaDataChanged();
+
+ DP0("S60VideoPlayerSession::updateMetaDataEntriesL ---");
+}
+
+/*!
+ * Apply the window changes when window handle changes.
+*/
+
+void S60VideoPlayerSession::windowHandleChanged()
+{
+ DP0("S60VideoPlayerSession::windowHandleChanged +++");
+
+ m_pendingChanges |= WindowHandle;
+ applyPendingChanges();
+
+ DP0("S60VideoPlayerSession::windowHandleChanged ---");
+}
+
+/*!
+ * Apply the window changes when display Rect changes.
+*/
+
+void S60VideoPlayerSession::displayRectChanged()
+{
+ DP0("S60VideoPlayerSession::displayRectChanged +++");
+
+ m_pendingChanges |= DisplayRect;
+ applyPendingChanges();
+
+ DP0("S60VideoPlayerSession::displayRectChanged ---");
+}
+
+/*!
+ * Apply the window changes when aspect Ratio changes.
+*/
+
+void S60VideoPlayerSession::aspectRatioChanged()
+{
+ DP0("S60VideoPlayerSession::aspectRatioChanged +++");
+
+ m_pendingChanges |= ScaleFactors;
+ applyPendingChanges();
+
+ DP0("S60VideoPlayerSession::aspectRatioChanged ---");
+}
+
+void S60VideoPlayerSession::rotationChanged()
+{
+ m_pendingChanges |= ScaleFactors;
+ m_pendingChanges |= Rotation;
+ applyPendingChanges();
+}
+
+#ifndef VIDEOOUTPUT_GRAPHICS_SURFACES
+void S60VideoPlayerSession::suspendDirectScreenAccess()
+{
+ DP0("S60VideoPlayerSession::suspendDirectScreenAccess +++");
+
+ m_dsaStopped = stopDirectScreenAccess();
+
+ DP0("S60VideoPlayerSession::suspendDirectScreenAccess ---");
+}
+
+void S60VideoPlayerSession::resumeDirectScreenAccess()
+{
+ DP0("S60VideoPlayerSession::resumeDirectScreenAccess +++");
+
+ if (!m_dsaStopped)
+ return;
+ startDirectScreenAccess();
+ m_dsaStopped = false;
+
+ DP0("S60VideoPlayerSession::resumeDirectScreenAccess ---");
+}
+
+void S60VideoPlayerSession::startDirectScreenAccess()
+{
+ DP0("S60VideoPlayerSession::startDirectScreenAccess +++");
+
+ if (m_dsaActive)
+ return;
+ TRAPD(err, m_player->StartDirectScreenAccessL());
+ if (err == KErrNone)
+ m_dsaActive = true;
+ setError(err);
+
+ DP0("S60VideoPlayerSession::startDirectScreenAccess ---");
+}
+
+bool S60VideoPlayerSession::stopDirectScreenAccess()
+{
+ DP0("S60VideoPlayerSession::stopDirectScreenAccess");
+
+ if (!m_dsaActive)
+ return false;
+ TRAPD(err, m_player->StopDirectScreenAccessL());
+ if (err == KErrNone)
+ m_dsaActive = false;
+ setError(err);
+ return true;
+}
+#endif
+
+/*!
+ * The percentage of the temporary buffer filling before playback begins.
+*/
+
+void S60VideoPlayerSession::MvloLoadingStarted()
+{
+ DP0("S60VideoPlayerSession::MvloLoadingStarted +++");
+
+ buffering();
+
+ DP0("S60VideoPlayerSession::MvloLoadingStarted ---");
+}
+
+/*!
+ * Buffer is filled with data and to for continuing/start playback.
+*/
+
+void S60VideoPlayerSession::MvloLoadingComplete()
+{
+ DP0("S60VideoPlayerSession::MvloLoadingComplete +++");
+
+ buffered();
+
+ DP0("S60VideoPlayerSession::MvloLoadingComplete ---");
+}
+
+/*!
+ Defiens which Audio End point to use.
+
+ \a audioEndpoint audioEndpoint name.
+*/
+
+void S60VideoPlayerSession::doSetAudioEndpoint(const QString& audioEndpoint)
+{
+ DP0("S60VideoPlayerSession::doSetAudioEndpoint +++");
+
+ DP1("S60VideoPlayerSession::doSetAudioEndpoint - ", audioEndpoint);
+
+ m_audioEndpoint = audioEndpoint;
+
+ DP0("S60VideoPlayerSession::doSetAudioEndpoint ---");
+}
+
+/*!
+
+ Returns audioEndpoint name.
+*/
+
+QString S60VideoPlayerSession::activeEndpoint() const
+{
+ DP0("S60VideoPlayerSession::activeEndpoint +++");
+
+ QString outputName = m_audioEndpoint;
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ if (m_audioOutput) {
+ CAudioOutput::TAudioOutputPreference output = m_audioOutput->AudioOutput();
+ outputName = qStringFromTAudioOutputPreference(output);
+ }
+#endif
+
+ DP1("S60VideoPlayerSession::activeEndpoint- outputName:", outputName);
+ DP0("S60VideoPlayerSession::activeEndpoint ---");
+ return outputName;
+}
+
+/*!
+ * Returns default Audio End point in use.
+*/
+
+QString S60VideoPlayerSession::defaultEndpoint() const
+{
+ DP0("S60VideoPlayerSession::defaultEndpoint +++");
+
+ QString outputName = DefaultAudioEndpoint;
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ if (m_audioOutput) {
+ CAudioOutput::TAudioOutputPreference output = m_audioOutput->DefaultAudioOutput();
+ outputName = qStringFromTAudioOutputPreference(output);
+ }
+#endif
+
+ DP1("S60VideoPlayerSession::defaultEndpoint, outputName:", outputName);
+ DP0("S60VideoPlayerSession::defaultEndpoint ---");
+
+ return outputName;
+}
+
+/*!
+ Sets active end \a name as an Audio End point.
+*/
+
+void S60VideoPlayerSession::setActiveEndpoint(const QString& name)
+{
+ DP0("S60VideoPlayerSession::setActiveEndpoint +++");
+
+ DP1("S60VideoPlayerSession::setActiveEndpoint - ", name);
+
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ CAudioOutput::TAudioOutputPreference output = CAudioOutput::ENoPreference;
+ if (name == DefaultAudioEndpoint)
+ output = CAudioOutput::ENoPreference;
+ else if (name == QString("All"))
+ output = CAudioOutput::EAll;
+ else if (name == QString("None"))
+ output = CAudioOutput::ENoOutput;
+ else if (name == QString("Earphone"))
+ output = CAudioOutput::EPrivate;
+ else if (name == QString("Speaker"))
+ output = CAudioOutput::EPublic;
+ if (m_audioOutput) {
+ TRAPD(err, m_audioOutput->SetAudioOutputL(output));
+ setError(err);
+ }
+#endif
+
+ DP0("S60VideoPlayerSession::setActiveEndpoint ---");
+}
+
+/*!
+ The default Audio output has been changed.
+
+ \a aAudioOutput Audio Output object.
+
+ \a aNewDefault is CAudioOutput::TAudioOutputPreference.
+*/
+
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+void S60VideoPlayerSession::DefaultAudioOutputChanged( CAudioOutput& aAudioOutput,
+ CAudioOutput::TAudioOutputPreference aNewDefault)
+{
+ DP0("S60VideoPlayerSession::DefaultAudioOutputChanged +++");
+
+ // Emit already implemented in setActiveEndpoint function
+ Q_UNUSED(aAudioOutput)
+ Q_UNUSED(aNewDefault)
+
+ DP0("S60VideoPlayerSession::DefaultAudioOutputChanged ---");
+}
+
+/*!
+ * \return CAudioOutput::ENoOutput by converting it to QString.
+*/
+
+QString S60VideoPlayerSession::qStringFromTAudioOutputPreference(CAudioOutput::TAudioOutputPreference output) const
+{
+ DP0("S60VideoPlayerSession::qStringFromTAudioOutputPreference");
+
+ if (output == CAudioOutput::ENoPreference)
+ return QString("Default");
+ else if (output == CAudioOutput::EAll)
+ return QString("All");
+ else if (output == CAudioOutput::ENoOutput)
+ return QString("None");
+ else if (output == CAudioOutput::EPrivate)
+ return QString("Earphone");
+ else if (output == CAudioOutput::EPublic)
+ return QString("Speaker");
+ return QString("Default");
+}
+#endif //HAS_AUDIOROUTING_IN_VIDEOPLAYER)
+
+/*!
+ * \return TRUE if video is Seekable else FALSE.
+*/
+
+bool S60VideoPlayerSession::getIsSeekable() const
+{
+ DP0("S60VideoPlayerSession::getIsSeekable +++");
+
+ bool seekable = ETrue;
+ int numberOfMetaDataEntries = 0;
+
+ TRAPD(err, numberOfMetaDataEntries = m_player->NumberOfMetaDataEntriesL());
+ if (err)
+ return seekable;
+
+ for (int i = 0; i < numberOfMetaDataEntries; i++) {
+ CMMFMetaDataEntry *entry = NULL;
+ TRAP(err, entry = m_player->MetaDataEntryL(i));
+
+ if (err)
+ return seekable;
+
+ if (!entry->Name().Compare(KSeekable)) {
+ if (!entry->Value().Compare(KFalse))
+ seekable = EFalse;
+ break;
+ }
+ }
+ DP0("S60VideoPlayerSession::getIsSeekable ---");
+
+ return seekable;
+}
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60videoplayersession.h b/src/plugins/symbian/mmf/mediaplayer/s60videoplayersession.h
new file mode 100644
index 000000000..f73683af8
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60videoplayersession.h
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** 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 S60VIDEOPLAYERSESSION_H
+#define S60VIDEOPLAYERSESSION_H
+
+#include "s60mediaplayersession.h"
+#include "s60mediaplayeraudioendpointselector.h"
+#include "s60medianetworkaccesscontrol.h"
+#include "s60videodisplay.h"
+
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+#include <videoplayer2.h>
+#else
+#include <videoplayer.h>
+#endif // VIDEOOUTPUT_GRAPHICS_SURFACES
+
+#include <QtCore/QCoreApplication>
+#include <QtGui/qwidget.h>
+#include <qvideowidget.h>
+
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+#include <AudioOutput.h>
+#include <MAudioOutputObserver.h>
+#endif // HAS_AUDIOROUTING_IN_VIDEOPLAYER
+
+class QTimer;
+class S60MediaNetworkAccessControl;
+class S60VideoDisplay;
+
+// Helper classes to pass Symbian events from WServ to the S60VideoPlayerSession
+// so it can control video player on certain events if required
+
+class ApplicationFocusObserver
+{
+public:
+ virtual void applicationGainedFocus() = 0;
+ virtual void applicationLostFocus() = 0;
+};
+
+class S60VideoPlayerEventHandler : public QObject
+{
+public:
+ static S60VideoPlayerEventHandler *instance();
+ static bool filterEvent(void *message, long *result);
+ void addApplicationFocusObserver(ApplicationFocusObserver* observer);
+ void removeApplicationFocusObserver(ApplicationFocusObserver* observer);
+private:
+ S60VideoPlayerEventHandler();
+ ~S60VideoPlayerEventHandler();
+private:
+ static S60VideoPlayerEventHandler *m_instance;
+ static QList<ApplicationFocusObserver *> m_applicationFocusObservers;
+ static QCoreApplication::EventFilter m_eventFilter;
+};
+
+class S60VideoPlayerSession : public S60MediaPlayerSession
+ , public MVideoPlayerUtilityObserver
+ , public MVideoLoadingObserver
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ , public MAudioOutputObserver
+#endif // HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ , public ApplicationFocusObserver
+{
+ Q_OBJECT
+public:
+ S60VideoPlayerSession(QMediaService *service, S60MediaNetworkAccessControl *object);
+ ~S60VideoPlayerSession();
+
+ // From S60MediaPlayerSession
+ bool isVideoAvailable();
+ bool isAudioAvailable();
+ void setVideoRenderer(QObject *renderer);
+
+ // From MVideoLoadingObserver
+ void MvloLoadingStarted();
+ void MvloLoadingComplete();
+ void setPlaybackRate(qreal rate);
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ // From MAudioOutputObserver
+ void DefaultAudioOutputChanged(CAudioOutput& aAudioOutput,
+ CAudioOutput::TAudioOutputPreference aNewDefault);
+#endif
+
+ // From S60MediaPlayerAudioEndpointSelector
+ QString activeEndpoint() const;
+ QString defaultEndpoint() const;
+
+ // ApplicationFocusObserver
+ void applicationGainedFocus();
+ void applicationLostFocus();
+
+signals:
+ void nativeSizeChanged(QSize);
+
+public Q_SLOTS:
+ void setActiveEndpoint(const QString& name);
+
+signals:
+ void accessPointChanged(int);
+
+protected:
+ // From S60MediaPlayerSession
+ void doLoadL(const TDesC &path);
+ void doLoadUrlL(const TDesC &path);
+ void doPlay();
+ void doStop();
+ void doClose();
+ void doPauseL();
+ void doSetVolumeL(int volume);
+ qint64 doGetPositionL() const;
+ void doSetPositionL(qint64 microSeconds);
+ void updateMetaDataEntriesL();
+ int doGetBufferStatusL() const;
+ qint64 doGetDurationL() const;
+ void doSetAudioEndpoint(const QString& audioEndpoint);
+ bool getIsSeekable() const;
+
+private slots:
+ void windowHandleChanged();
+ void displayRectChanged();
+ void aspectRatioChanged();
+ void rotationChanged();
+#ifndef VIDEOOUTPUT_GRAPHICS_SURFACES
+ void suspendDirectScreenAccess();
+ void resumeDirectScreenAccess();
+#endif
+
+private:
+ void applyPendingChanges(bool force = false);
+#ifndef VIDEOOUTPUT_GRAPHICS_SURFACES
+ void startDirectScreenAccess();
+ bool stopDirectScreenAccess();
+#endif
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ QString qStringFromTAudioOutputPreference(CAudioOutput::TAudioOutputPreference output) const;
+#endif
+
+ // From MVideoPlayerUtilityObserver
+ void MvpuoOpenComplete(TInt aError);
+ void MvpuoPrepareComplete(TInt aError);
+ void MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError);
+ void MvpuoPlayComplete(TInt aError);
+ void MvpuoEvent(const TMMFEvent &aEvent);
+
+private:
+ int m_accessPointId;
+ S60MediaNetworkAccessControl* m_networkAccessControl;
+ RWsSession *const m_wsSession;
+ CWsScreenDevice *const m_screenDevice;
+ QMediaService *const m_service;
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ CVideoPlayerUtility2 *m_player;
+#else
+ CVideoPlayerUtility *m_player;
+ bool m_dsaActive;
+ bool m_dsaStopped;
+#endif // VIDEOOUTPUT_GRAPHICS_SURFACES
+ QObject *m_videoOutputControl;
+ S60VideoDisplay *m_videoOutputDisplay;
+ RWindow *m_displayWindow;
+ QSize m_nativeSize;
+#ifdef HTTP_COOKIES_ENABLED
+ TMMFMessageDestinationPckg m_destinationPckg;
+#endif
+#ifdef HAS_AUDIOROUTING_IN_VIDEOPLAYER
+ CAudioOutput *m_audioOutput;
+#endif
+ QString m_audioEndpoint;
+ enum Parameter {
+ WindowHandle = 0x1,
+ DisplayRect = 0x2,
+ ScaleFactors = 0x4,
+ Rotation = 0x8
+ };
+ QFlags<Parameter> m_pendingChanges;
+ bool m_backendInitiatedPause;
+};
+
+#endif
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60videorenderer.cpp b/src/plugins/symbian/mmf/mediaplayer/s60videorenderer.cpp
new file mode 100644
index 000000000..2de6896a0
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60videorenderer.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "DebugMacros.h"
+
+#include "s60videorenderer.h"
+
+#include <QtCore/qcoreevent.h>
+#include <QtGui/qapplication.h>
+
+/*!
+ Constructs a new video renderer media end point with the given \a parent.
+*/
+
+S60VideoRenderer::S60VideoRenderer(QObject *parent)
+ : QVideoRendererControl(parent)
+{
+ DP0("S60VideoRenderer::S60VideoRenderer +++");
+
+ DP0("S60VideoRenderer::S60VideoRenderer ---");
+
+}
+
+/*!
+ Destroys a video renderer media end point.
+*/
+
+S60VideoRenderer::~S60VideoRenderer()
+{
+ DP0("S60VideoRenderer::~S60VideoRenderer +++");
+ DP0("S60VideoRenderer::~S60VideoRenderer ---");
+}
+
+/*!
+ \return the surface a video producer renders to.
+*/
+
+QAbstractVideoSurface *S60VideoRenderer::surface() const
+{
+ DP0("S60VideoRenderer::surface");
+
+ return m_surface;
+}
+
+/*!
+ Sets the \a surface a video producer renders to.
+*/
+
+void S60VideoRenderer::setSurface(QAbstractVideoSurface *surface)
+{
+ DP0("S60VideoRenderer::setSurface +++");
+
+ m_surface = surface;
+
+ DP0("S60VideoRenderer::setSurface ---");
+}
+
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60videorenderer.h b/src/plugins/symbian/mmf/mediaplayer/s60videorenderer.h
new file mode 100644
index 000000000..6e90d42c3
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60videorenderer.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60VIDEORENDERER_H
+#define S60VIDEORENDERER_H
+
+#include <QtCore/qobject.h>
+#include <qvideorenderercontrol.h>
+
+QT_USE_NAMESPACE
+
+class S60VideoRenderer : public QVideoRendererControl
+{
+ Q_OBJECT
+
+public:
+ S60VideoRenderer(QObject *parent = 0);
+ virtual ~S60VideoRenderer();
+
+ QAbstractVideoSurface *surface() const;
+ void setSurface(QAbstractVideoSurface *surface);
+
+private:
+
+ QAbstractVideoSurface *m_surface;
+};
+
+#endif // S60VIDEORENDERER_H
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60videosurface.cpp b/src/plugins/symbian/mmf/mediaplayer/s60videosurface.cpp
new file mode 100644
index 000000000..563d33b40
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60videosurface.cpp
@@ -0,0 +1,372 @@
+/****************************************************************************
+**
+** 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$
+** 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 "DebugMacros.h"
+
+#include <qvideosurfaceformat.h>
+
+#include "s60videosurface.h"
+/*!
+ * Constructs a video surface with the given \a parent.
+*/
+
+S60VideoSurface::S60VideoSurface(QObject *parent)
+ : QAbstractVideoSurface(parent)
+ , m_winId(0)
+{
+ DP0("S60VideoSurface::S60VideoSurface +++");
+ DP0("S60VideoSurface::S60VideoSurface ---");
+}
+
+/*!
+ * Destroys video surface.
+*/
+
+S60VideoSurface::~S60VideoSurface()
+{
+ DP0("S60VideoSurface::~S60VideoSurface +++");
+ DP0("S60VideoSurface::~S60VideoSurface ---");
+}
+
+/*!
+ \return the ID of the window a video surface end point renders to.
+*/
+
+WId S60VideoSurface::winId() const
+{
+ DP0("S60VideoSurface::winId");
+
+ return m_winId;
+}
+
+/*!
+ Sets the \a id of the window a video surface end point renders to.
+*/
+
+void S60VideoSurface::setWinId(WId id)
+{
+ DP0("S60VideoSurface::setWinId +++");
+
+ m_winId = id;
+
+ DP0("S60VideoSurface::setWinId ---");
+}
+
+/*!
+ \return the sub-rect of a window where video is displayed.
+*/
+
+QRect S60VideoSurface::displayRect() const
+{
+ DP0("S60VideoSurface::displayRect");
+
+ return m_displayRect;
+}
+
+/*!
+ Sets the sub-\a rect of a window where video is displayed.
+*/
+
+void S60VideoSurface::setDisplayRect(const QRect &rect)
+{
+ DP0("S60VideoSurface::setDisplayRect +++");
+
+ m_displayRect = rect;
+
+ DP0("S60VideoSurface::setDisplayRect ---");
+}
+
+/*!
+ \return the brightness adjustment applied to a video surface.
+
+ Valid brightness values range between -100 and 100, the default is 0.
+*/
+
+int S60VideoSurface::brightness() const
+{
+ DP0("S60VideoSurface::brightness");
+
+ return 0;
+}
+
+/*!
+ Sets a \a brightness adjustment for a video surface.
+
+ Valid brightness values range between -100 and 100, the default is 0.
+*/
+
+void S60VideoSurface::setBrightness(int brightness)
+{
+ DP0("S60VideoSurface::setBrightness +++");
+
+ DP1("S60VideoSurface::setBrightness - brightness:", brightness);
+
+ Q_UNUSED(brightness);
+
+ DP0("S60VideoSurface::setBrightness ---");
+}
+
+/*!
+ \return the contrast adjustment applied to a video surface.
+
+ Valid contrast values range between -100 and 100, the default is 0.
+*/
+
+int S60VideoSurface::contrast() const
+{
+ DP0("S60VideoSurface::contrast");
+
+ return 0;
+}
+
+/*!
+ Sets the \a contrast adjustment for a video surface.
+
+ Valid contrast values range between -100 and 100, the default is 0.
+*/
+
+void S60VideoSurface::setContrast(int contrast)
+{
+ DP0("S60VideoSurface::setContrast +++");
+
+ DP1("S60VideoSurface::setContrast - ", contrast);
+
+ Q_UNUSED(contrast);
+
+ DP0("S60VideoSurface::setContrast ---");
+}
+
+/*!
+ \return the hue adjustment applied to a video surface.
+
+ Value hue values range between -100 and 100, the default is 0.
+*/
+
+int S60VideoSurface::hue() const
+{
+ DP0("S60VideoSurface::hue");
+
+ return 0;
+}
+
+/*!
+ Sets a \a hue adjustment for a video surface.
+
+ Valid hue values range between -100 and 100, the default is 0.
+*/
+
+void S60VideoSurface::setHue(int hue)
+{
+ DP0("S60VideoSurface::setHue +++");
+
+ DP1("S60VideoSurface::setHue - ", hue);
+
+ Q_UNUSED(hue);
+
+ DP0("S60VideoSurface::setHue ---");
+}
+
+/*!
+ \return the saturation adjustment applied to a video surface.
+
+ Value saturation values range between -100 and 100, the default is 0.
+*/
+
+int S60VideoSurface::saturation() const
+{
+ DP0("S60VideoSurface::saturation");
+
+ return 0;
+}
+
+/*!
+ Sets a \a saturation adjustment for a video surface.
+
+ Valid saturation values range between -100 and 100, the default is 0.
+*/
+
+void S60VideoSurface::setSaturation(int saturation)
+{
+ DP0("S60VideoSurface::setSaturation +++");
+
+ DP1("S60VideoSurface::setSaturation - ", saturation);
+
+ Q_UNUSED(saturation);
+
+ DP0("S60VideoSurface::setSaturation ---");
+}
+
+/*!
+ * \return ZERO. \a attribute, \a minimum, \a maximum are not used.
+*/
+int S60VideoSurface::getAttribute(const char *attribute, int minimum, int maximum) const
+{
+ DP0("S60VideoSurface::getAttribute +++");
+
+ Q_UNUSED(attribute);
+ Q_UNUSED(minimum);
+ Q_UNUSED(maximum);
+
+ DP0("S60VideoSurface::getAttribute ---");
+
+ return 0;
+}
+
+/*!
+ * Sets the \a attribute, \a minimum, \a maximum.
+ * But never used.
+*/
+
+void S60VideoSurface::setAttribute(const char *attribute, int value, int minimum, int maximum)
+{
+ DP0("S60VideoSurface::setAttribute +++");
+
+ Q_UNUSED(attribute);
+ Q_UNUSED(value);
+ Q_UNUSED(minimum);
+ Q_UNUSED(maximum);
+
+ DP0("S60VideoSurface::setAttribute ---");
+
+}
+
+/*!
+ * \return ZERO.
+ * \a value, \a fromLower, \a fromUpper, \a toLower, \a toUpper are never used.
+*/
+
+int S60VideoSurface::redistribute(
+ int value, int fromLower, int fromUpper, int toLower, int toUpper)
+{
+ DP0("S60VideoSurface::redistribute +++");
+
+ Q_UNUSED(value);
+ Q_UNUSED(fromLower);
+ Q_UNUSED(fromUpper);
+ Q_UNUSED(toLower);
+ Q_UNUSED(toUpper);
+
+ DP0("S60VideoSurface::redistribute ---");
+
+ return 0;
+}
+
+/*!
+ * \return List of video surface supported Pixel Formats.
+*/
+
+QList<QVideoFrame::PixelFormat> S60VideoSurface::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ DP0("S60VideoSurface::supportedPixelFormats +++");
+
+ Q_UNUSED(handleType);
+ QList<QVideoFrame::PixelFormat> list;
+
+ DP0("S60VideoSurface::supportedPixelFormats ---");
+
+ return list;
+}
+
+/*!
+ * \return always FALSE, as \a format never used.
+*/
+
+bool S60VideoSurface::start(const QVideoSurfaceFormat &format)
+{
+ DP0("S60VideoSurface::start");
+
+ Q_UNUSED(format);
+ return false;
+}
+
+/*!
+ * Stops video surface.
+*/
+void S60VideoSurface::stop()
+{
+ DP0("S60VideoSurface::stop +++");
+
+ DP0("S60VideoSurface::stop ---");
+
+}
+
+/*!
+ * \return always FALS, as \a format is never used.
+*/
+bool S60VideoSurface::present(const QVideoFrame &frame)
+{
+ DP0("S60VideoSurface::present");
+
+ Q_UNUSED(frame);
+ return false;
+}
+
+/*!
+ * \return always FALSE.
+*/
+
+bool S60VideoSurface::findPort()
+{
+ DP0("S60VideoSurface::findPort");
+
+ return false;
+}
+
+void S60VideoSurface::querySupportedFormats()
+{
+ DP0("S60VideoSurface::querySupportedFormats +++");
+
+ DP0("S60VideoSurface::querySupportedFormats ---");
+
+}
+
+/*!
+ * \return always FLASE, as \a format never used.
+*/
+
+bool S60VideoSurface::isFormatSupported(const QVideoSurfaceFormat &format) const
+{
+ DP0("S60VideoSurface::isFormatSupported");
+
+ Q_UNUSED(format);
+ return false;
+}
diff --git a/src/plugins/symbian/mmf/mediaplayer/s60videosurface.h b/src/plugins/symbian/mmf/mediaplayer/s60videosurface.h
new file mode 100644
index 000000000..9f13755b7
--- /dev/null
+++ b/src/plugins/symbian/mmf/mediaplayer/s60videosurface.h
@@ -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$
+** 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 S60VIDEOSURFACE_H
+#define S60VIDEOSURFACE_H
+
+#include <QtGui/qwidget.h>
+#include <qabstractvideosurface.h>
+
+class S60VideoSurface : public QAbstractVideoSurface
+{
+ Q_OBJECT
+public:
+ S60VideoSurface(QObject *parent = 0);
+ ~S60VideoSurface();
+
+ WId winId() const;
+ void setWinId(WId id);
+
+ QRect displayRect() const;
+ void setDisplayRect(const QRect &rect);
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
+
+ bool isFormatSupported(const QVideoSurfaceFormat &format) const;
+
+ bool start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ bool present(const QVideoFrame &frame);
+
+private:
+ WId m_winId;
+ //XvPortID m_portId;
+ //GC m_gc;
+ //XvImage *m_image;
+ QList<QVideoFrame::PixelFormat> m_supportedPixelFormats;
+ QVector<int> m_formatIds;
+ QRect m_viewport;
+ QRect m_displayRect;
+ QPair<int, int> m_brightnessRange;
+ QPair<int, int> m_contrastRange;
+ QPair<int, int> m_hueRange;
+ QPair<int, int> m_saturationRange;
+
+ bool findPort();
+ void querySupportedFormats();
+
+ int getAttribute(const char *attribute, int minimum, int maximum) const;
+ void setAttribute(const char *attribute, int value, int minimum, int maximum);
+
+ static int redistribute(int value, int fromLower, int fromUpper, int toLower, int toUpper);
+};
+
+#endif
diff --git a/src/plugins/symbian/mmf/mmf.pro b/src/plugins/symbian/mmf/mmf.pro
new file mode 100644
index 000000000..2bae03e59
--- /dev/null
+++ b/src/plugins/symbian/mmf/mmf.pro
@@ -0,0 +1,58 @@
+TEMPLATE = lib
+
+CONFIG += plugin
+TARGET = $$qtLibraryTarget(qtmultimediakit_mmfengine)
+PLUGIN_TYPE = mediaservice
+include (../../../../common.pri)
+qtAddLibrary(QtMultimediaKit)
+
+#includes here so that all defines are added here also
+include(mediaplayer/mediaplayer_s60.pri)
+include(radio/radio.pri)
+
+QT += network
+
+# we include mmf audiorecording only if we are not building openmaxal based backend
+!contains(openmaxal_symbian_enabled, yes) {
+ message("Enabling mmf mediarecording backend")
+ include(audiosource/audiosource_s60.pri)
+}
+
+DEPENDPATH += .
+INCLUDEPATH += . \
+ $${SOURCE_DIR}/include \
+ $${SOURCE_DIR}/src/multimedia \
+ $${SOURCE_DIR}/src/multimedia/audio \
+ $${SOURCE_DIR}/src/multimedia/video \
+ $${SOURCE_DIR}/plugins/multimedia/symbian/mmf/inc \
+ $${SOURCE_DIR}
+
+
+HEADERS += s60mediaserviceplugin.h \
+ s60formatsupported.h
+
+SOURCES += s60mediaserviceplugin.cpp \
+ s60formatsupported.cpp
+
+contains(S60_VERSION, 3.2)|contains(S60_VERSION, 3.1) {
+ DEFINES += PRE_S60_50_PLATFORM
+}
+contains(mmf_http_cookies_enabled, yes) {
+ DEFINES += HTTP_COOKIES_ENABLED
+}
+load(data_caging_paths)
+TARGET.EPOCALLOWDLLDATA = 1
+TARGET.UID3=0x2002AC76
+TARGET.CAPABILITY = ALL -TCB
+MMP_RULES += EXPORTUNFROZEN
+
+#make a sis package from plugin + api + stub (plugin)
+pluginDep.sources = $${TARGET}.dll
+pluginDep.path = $${QT_PLUGINS_BASE_DIR}/$${PLUGIN_TYPE}
+DEPLOYMENT += pluginDep
+
+#Media API spesific deployment
+QtMediaDeployment.sources = QtMultimediaKit.dll
+QtMediaDeployment.path = /sys/bin
+
+DEPLOYMENT += QtMediaDeployment
diff --git a/src/plugins/symbian/mmf/radio/radio.pri b/src/plugins/symbian/mmf/radio/radio.pri
new file mode 100644
index 000000000..a4703d126
--- /dev/null
+++ b/src/plugins/symbian/mmf/radio/radio.pri
@@ -0,0 +1,24 @@
+INCLUDEPATH += $$PWD
+
+contains(tunerlib_s60_enabled, yes) {
+
+ LIBS += -ltunerutility
+ DEFINES += TUNERLIBUSED
+ INCLUDEPATH += $${EPOCROOT}epoc32/include/mmf/common
+
+ HEADERS += $$PWD/s60radiotunercontrol_31.h
+ SOURCES += $$PWD/s60radiotunercontrol_31.cpp
+}
+
+contains(radioutility_s60_enabled, yes) {
+ LIBS += -lradio_utility
+ DEFINES += RADIOUTILITYLIBUSED
+
+ HEADERS += $$PWD/s60radiotunercontrol_since32.h
+ SOURCES += $$PWD/s60radiotunercontrol_since32.cpp
+}
+
+contains(tunerlib_s60_enabled, yes)|contains(radioutility_s60_enabled, yes) {
+ HEADERS += $$PWD/s60radiotunerservice.h
+ SOURCES += $$PWD/s60radiotunerservice.cpp
+}
diff --git a/src/plugins/symbian/mmf/radio/s60radiotunercontrol_31.cpp b/src/plugins/symbian/mmf/radio/s60radiotunercontrol_31.cpp
new file mode 100644
index 000000000..b7627e312
--- /dev/null
+++ b/src/plugins/symbian/mmf/radio/s60radiotunercontrol_31.cpp
@@ -0,0 +1,603 @@
+/****************************************************************************
+**
+** 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$
+** 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 "DebugMacros.h"
+
+#include "s60radiotunercontrol_31.h"
+#include "s60radiotunerservice.h"
+
+#include <QtCore/qdebug.h>
+#include <QFile>
+
+// from AudioPreference.h
+const TInt KAudioPriorityFMRadio = 79;
+const TUint KAudioPrefRadioAudioEvent = 0x03000001;
+
+S60RadioTunerControl::S60RadioTunerControl(QObject *parent)
+ : QRadioTunerControl(parent)
+ , m_error(0)
+ , m_tunerState(0)
+ , m_apiTunerState(QRadioTuner::StoppedState)
+ , m_audioInitializationComplete(false)
+ , m_radioError(QRadioTuner::NoError)
+ , m_muted(false)
+ , m_isStereo(true)
+ , m_stereoMode(QRadioTuner::Auto)
+ , m_signal(0)
+ , m_currentBand(QRadioTuner::FM)
+ , m_currentFreq(87500000)
+ , m_scanning(false)
+ , m_vol(50)
+{
+ DP0("S60RadioTunerControl::S60RadioTunerControl +++");
+
+ initRadio();
+
+ DP0("S60RadioTunerControl::S60RadioTunerControl ---");
+}
+
+S60RadioTunerControl::~S60RadioTunerControl()
+{
+ DP0("S60RadioTunerControl::~S60RadioTunerControl +++");
+
+ if (m_tunerUtility) {
+ m_tunerUtility->Close();
+ m_tunerUtility->CancelNotifyChange();
+ m_tunerUtility->CancelNotifySignalStrength();
+ m_tunerUtility->CancelNotifyStereoChange();
+ delete m_tunerUtility;
+ }
+ if (m_audioPlayerUtility) {
+ m_audioPlayerUtility = NULL;
+ }
+
+ DP0("S60RadioTunerControl::~S60RadioTunerControl ---");
+}
+
+bool S60RadioTunerControl::initRadio()
+{
+ DP0("S60RadioTunerControl::initRadio +++");
+
+ m_available = false;
+
+ TRAPD(tunerError, m_tunerUtility = CMMTunerUtility::NewL(*this, CMMTunerUtility::ETunerBandFm, 1,
+ CMMTunerUtility::ETunerAccessPriorityNormal));
+ if (tunerError != KErrNone) {
+ m_radioError = QRadioTuner::OpenError;
+ return m_available;
+ }
+
+ TRAPD(playerError, m_audioPlayerUtility = m_tunerUtility->TunerPlayerUtilityL(*this));
+ if (playerError != KErrNone) {
+ m_radioError = QRadioTuner::OpenError;
+ return m_available;
+ }
+
+ TRAPD(initializeError, m_audioPlayerUtility->InitializeL(KAudioPriorityFMRadio,
+ TMdaPriorityPreference(KAudioPrefRadioAudioEvent)));
+ if (initializeError != KErrNone) {
+ m_radioError = QRadioTuner::OpenError;
+ return m_available;
+ }
+
+ m_tunerUtility->NotifyChange(*this);
+ m_tunerUtility->NotifyStereoChange(*this);
+ m_tunerUtility->NotifySignalStrength(*this);
+
+ TFrequency freq(m_currentFreq);
+ m_tunerUtility->Tune(freq);
+
+ m_available = true;
+
+ DP0("S60RadioTunerControl::initRadio ---");
+
+ return m_available;
+}
+
+void S60RadioTunerControl::start()
+{
+ DP0("S60RadioTunerControl::start +++");
+
+ if (!m_audioInitializationComplete) {
+ TFrequency freq(m_currentFreq);
+ m_tunerUtility->Tune(freq);
+ } else {
+ m_audioPlayerUtility->Play();
+ }
+
+ m_apiTunerState = QRadioTuner::ActiveState;
+ emit stateChanged(m_apiTunerState);
+
+ DP0("S60RadioTunerControl::start ---");
+}
+
+void S60RadioTunerControl::stop()
+{
+ DP0("S60RadioTunerControl::stop +++");
+
+ if (m_audioPlayerUtility) {
+ m_audioPlayerUtility->Stop();
+ m_apiTunerState = QRadioTuner::StoppedState;
+ emit stateChanged(m_apiTunerState);
+ }
+
+ DP0("S60RadioTunerControl::stop ---");
+}
+
+QRadioTuner::State S60RadioTunerControl::state() const
+{
+ DP0("S60RadioTunerControl::state");
+
+ return m_apiTunerState;
+}
+
+QRadioTuner::Band S60RadioTunerControl::band() const
+{
+ DP0("S60RadioTunerControl::band");
+
+ return m_currentBand;
+}
+
+bool S60RadioTunerControl::isBandSupported(QRadioTuner::Band b) const
+{
+ DP0("S60RadioTunerControl::isBandSupported");
+
+ if(b == QRadioTuner::FM)
+ return true;
+ else if(b == QRadioTuner::LW)
+ return false;
+ else if(b == QRadioTuner::AM)
+ return true;
+ else if(b == QRadioTuner::SW)
+ return false;
+ else
+ return false;
+}
+
+void S60RadioTunerControl::setBand(QRadioTuner::Band b)
+{
+ DP0("S60RadioTunerControl::setBand +++");
+
+ QRadioTuner::Band tempBand = b;
+ if (tempBand != m_currentBand) {
+ m_currentBand = b;
+ emit bandChanged(m_currentBand);
+ }
+
+ DP0("S60RadioTunerControl::setBand ---");
+}
+
+int S60RadioTunerControl::frequency() const
+{
+ DP0("S60RadioTunerControl::frequency");
+
+ return m_currentFreq;
+}
+
+void S60RadioTunerControl::setFrequency(int frequency)
+{
+ DP0("S60RadioTunerControl::setFrequency +++");
+
+ m_currentFreq = frequency;
+ TFrequency freq(m_currentFreq);
+ m_tunerUtility->Tune(freq);
+
+ DP0("S60RadioTunerControl::setFrequency ---");
+}
+
+int S60RadioTunerControl::frequencyStep(QRadioTuner::Band b) const
+{
+ DP0("S60RadioTunerControl::frequencyStep +++");
+
+ int step = 0;
+
+ if(b == QRadioTuner::FM)
+ step = 100000; // 100kHz steps
+ else if(b == QRadioTuner::LW)
+ step = 1000; // 1kHz steps
+ else if(b == QRadioTuner::AM)
+ step = 1000; // 1kHz steps
+ else if(b == QRadioTuner::SW)
+ step = 500; // 500Hz steps
+
+ DP1("S60RadioTunerControl::frequencyStep, Step:", step);
+ DP0("S60RadioTunerControl::frequencyStep ---");
+
+ return step;
+}
+
+QPair<int,int> S60RadioTunerControl::frequencyRange(QRadioTuner::Band band) const
+{
+ DP0("S60RadioTunerControl::frequencyRange +++");
+
+ TFrequency bottomFreq;
+ TFrequency topFreq;
+ int bandError = KErrNone;
+
+ if (m_tunerUtility){
+ bandError = m_tunerUtility->GetFrequencyBandRange(bottomFreq, topFreq);
+ if (!bandError) {
+ return qMakePair<int,int>(bottomFreq.iFrequency, topFreq.iFrequency);
+ }
+ }
+
+ DP0("S60RadioTunerControl::frequencyRange ---");
+
+ return qMakePair<int,int>(0,0);
+}
+
+CMMTunerUtility::TTunerBand S60RadioTunerControl::getNativeBand(QRadioTuner::Band b) const
+{
+ DP0("S60RadioTunerControl::getNativeBand");
+
+ // api match to native s60 bands
+ if (b == QRadioTuner::AM)
+ return CMMTunerUtility::ETunerBandAm;
+ else if (b == QRadioTuner::FM)
+ return CMMTunerUtility::ETunerBandFm;
+ else if (b == QRadioTuner::LW)
+ return CMMTunerUtility::ETunerBandLw;
+ else
+ return CMMTunerUtility::ETunerNoBand;
+}
+
+bool S60RadioTunerControl::isStereo() const
+{
+ DP0("S60RadioTunerControl::isStereo");
+
+ return m_isStereo;
+}
+
+QRadioTuner::StereoMode S60RadioTunerControl::stereoMode() const
+{
+ DP0("S60RadioTunerControl::stereoMode");
+
+ return m_stereoMode;
+}
+
+void S60RadioTunerControl::setStereoMode(QRadioTuner::StereoMode mode)
+{
+ DP0("S60RadioTunerControl::setStereoMode +++");
+
+ m_stereoMode = mode;
+ if (m_tunerUtility) {
+ if (QRadioTuner::ForceMono == mode)
+ m_tunerUtility->ForceMonoReception(true);
+ else
+ m_tunerUtility->ForceMonoReception(false);
+ }
+
+ DP0("S60RadioTunerControl::setStereoMode ---");
+}
+
+int S60RadioTunerControl::signalStrength() const
+{
+ DP0("S60RadioTunerControl::signalStrength +++");
+
+ // return value is a percentage value
+ if (m_tunerUtility) {
+ TInt maxSignalStrength;
+ TInt currentSignalStrength;
+ m_error = m_tunerUtility->GetMaxSignalStrength(maxSignalStrength);
+ if (m_error == KErrNone) {
+ m_error = m_tunerUtility->GetSignalStrength(currentSignalStrength);
+ if (m_error == KErrNone) {
+ if (maxSignalStrength == 0 || currentSignalStrength == 0) {
+ return 0;
+ }
+ m_signal = ((TInt64)currentSignalStrength) * 100 / maxSignalStrength;
+ }
+ }
+ }
+
+ DP1("S60RadioTunerControl::signalStrength, m_signal:", m_signal);
+ DP0("S60RadioTunerControl::signalStrength ---");
+
+ return m_signal;
+}
+
+int S60RadioTunerControl::volume() const
+{
+ DP0("S60RadioTunerControl::volume");
+
+ return m_vol;
+}
+
+void S60RadioTunerControl::setVolume(int volume)
+{
+ DP0("S60RadioTunerControl::setVolume +++");
+ DP1("S60RadioTunerControl::setVolume: ", volume);
+
+ if (m_audioPlayerUtility) {
+ m_vol = volume;
+ TInt error = m_audioPlayerUtility->SetVolume(volume/10);
+ emit volumeChanged(m_vol);
+ }
+
+ DP0("S60RadioTunerControl::setVolume ---");
+}
+
+bool S60RadioTunerControl::isMuted() const
+{
+ DP0("S60RadioTunerControl::isMuted");
+
+ return m_muted;
+}
+
+void S60RadioTunerControl::setMuted(bool muted)
+{
+ DP0("S60RadioTunerControl::setMuted +++");
+
+ DP1("S60RadioTunerControl::setMuted:", muted);
+
+ if (m_audioPlayerUtility && m_audioInitializationComplete) {
+ m_muted = muted;
+ m_audioPlayerUtility->Mute(m_muted);
+ emit mutedChanged(m_muted);
+ }
+
+ DP0("S60RadioTunerControl::setMuted ---");
+}
+
+bool S60RadioTunerControl::isSearching() const
+{
+ DP0("S60RadioTunerControl::isSearching");
+
+ if (m_tunerUtility) {
+ TUint32 tempState;
+ m_tunerUtility->GetState(tempState);
+ if (tempState == CMMTunerUtility::ETunerStateRetuning || m_scanning) {
+ return true;
+ } else
+ return false;
+ }
+ return true;
+}
+
+void S60RadioTunerControl::cancelSearch()
+{
+ DP0("S60RadioTunerControl::cancelSearch +++");
+
+ m_tunerUtility->CancelRetune();
+ m_scanning = false;
+ emit searchingChanged(false);
+
+ DP0("S60RadioTunerControl::cancelSearch ---");
+}
+
+void S60RadioTunerControl::searchForward()
+{
+ DP0("S60RadioTunerControl::searchForward +++");
+
+ m_scanning = true;
+ setVolume(m_vol);
+ m_tunerUtility->StationSeek(CMMTunerUtility::ESearchDirectionUp);
+ emit searchingChanged(true);
+
+ DP0("S60RadioTunerControl::searchForward ---");
+}
+
+void S60RadioTunerControl::searchBackward()
+{
+ DP0("S60RadioTunerControl::searchBackward +++");
+
+ m_scanning = true;
+ setVolume(m_vol);
+ m_tunerUtility->StationSeek(CMMTunerUtility::ESearchDirectionDown);
+ emit searchingChanged(true);
+
+ DP0("S60RadioTunerControl::searchBackward ---");
+}
+
+bool S60RadioTunerControl::isValid() const
+{
+ DP0("S60RadioTunerControl::isValid");
+
+ return m_available;
+}
+
+bool S60RadioTunerControl::isAvailable() const
+{
+ DP0("S60RadioTunerControl::isAvailable");
+
+ return m_available;
+}
+
+QtMultimediaKit::AvailabilityError S60RadioTunerControl::availabilityError() const
+{
+ DP0("S60RadioTunerControl::availabilityError");
+
+ if (m_available)
+ return QtMultimediaKit::NoError;
+ else
+ return QtMultimediaKit::ResourceError;
+}
+
+QRadioTuner::Error S60RadioTunerControl::error() const
+{
+ DP1("QtMultimediaKit::NoError", m_radioError);
+
+ return m_radioError;
+}
+
+QString S60RadioTunerControl::errorString() const
+{
+ DP1("S60RadioTunerControl::errorString", m_errorString);
+
+ return m_errorString;
+}
+
+void S60RadioTunerControl::MToTuneComplete(TInt aError)
+{
+ DP0("S60RadioTunerControl::MToTuneComplete +++");
+ DP1("S60RadioTunerControl::MToTuneComplete, aError:",aError);
+
+ if (aError == KErrNone) {
+ m_scanning = false;
+ m_audioPlayerUtility->Play();
+ if (!m_audioInitializationComplete) {
+ TRAPD(initializeError, m_audioPlayerUtility->InitializeL(KAudioPriorityFMRadio,
+ TMdaPriorityPreference(KAudioPrefRadioAudioEvent)));
+ if (initializeError != KErrNone) {
+ m_radioError = QRadioTuner::OpenError;
+ }
+ }
+ }
+
+ DP0("S60RadioTunerControl::MToTuneComplete ---");
+}
+
+void S60RadioTunerControl::MTcoFrequencyChanged(const TFrequency& aOldFrequency, const TFrequency& aNewFrequency)
+{
+ DP0("S60RadioTunerControl::MTcoFrequencyChanged +++");
+
+ m_currentFreq = aNewFrequency.iFrequency;
+ m_scanning = false;
+ emit frequencyChanged(m_currentFreq);
+
+ DP0("S60RadioTunerControl::MTcoFrequencyChanged ---");
+}
+
+void S60RadioTunerControl::MTcoStateChanged(const TUint32& aOldState, const TUint32& aNewState)
+{
+ DP0("S60RadioTunerControl::MTcoStateChanged +++");
+
+ if (aNewState == CMMTunerUtility::ETunerStateActive) {
+ m_apiTunerState = QRadioTuner::ActiveState;
+ }
+ if (aNewState == CMMTunerUtility::ETunerStatePlaying) {
+ m_apiTunerState = QRadioTuner::ActiveState;
+ }
+ if (aOldState != aNewState){
+ emit stateChanged(m_apiTunerState);
+ }
+
+ DP0("S60RadioTunerControl::MTcoStateChanged ---");
+}
+
+void S60RadioTunerControl::MTcoAntennaDetached()
+{
+ DP0("S60RadioTunerControl::MTcoAntennaDetached +++");
+
+ DP0("S60RadioTunerControl::MTcoAntennaDetached ---");
+
+ // no actions
+}
+
+void S60RadioTunerControl::MTcoAntennaAttached()
+{
+ DP0("S60RadioTunerControl::MTcoAntennaAttached +++");
+
+ DP0("S60RadioTunerControl::MTcoAntennaAttached ---");
+
+ // no actions
+}
+
+void S60RadioTunerControl::FlightModeChanged(TBool aFlightMode)
+{
+ DP0("S60RadioTunerControl::FlightModeChanged +++");
+
+ DP0("S60RadioTunerControl::FlightModeChanged ---");
+
+ // no actions
+}
+
+void S60RadioTunerControl::MTsoStereoReceptionChanged(TBool aStereo)
+{
+ DP0("S60RadioTunerControl::MTsoStereoReceptionChanged +++");
+ DP1("S60RadioTunerControl::MTsoStereoReceptionChanged, aStereo:", aStereo);
+ m_isStereo = aStereo;
+ emit stereoStatusChanged(aStereo);
+
+ DP0("S60RadioTunerControl::MTsoStereoReceptionChanged ---");
+}
+
+void S60RadioTunerControl::MTsoForcedMonoChanged(TBool aForcedMono)
+{
+ DP0("S60RadioTunerControl::MTsoForcedMonoChanged +++");
+ DP1("S60RadioTunerControl::MTsoForcedMonoChanged, aForcedMono:", aForcedMono);
+
+ if (aForcedMono) {
+ m_stereoMode = QRadioTuner::ForceMono;
+ }
+
+ DP0("S60RadioTunerControl::MTsoForcedMonoChanged ---");
+}
+
+void S60RadioTunerControl::MssoSignalStrengthChanged(TInt aNewSignalStrength)
+{
+ DP0("S60RadioTunerControl::MssoSignalStrengthChanged +++");
+ DP1("S60RadioTunerControl::MssoSignalStrengthChanged, aNewSignalStrength:", aNewSignalStrength);
+
+ m_signal = aNewSignalStrength;
+ emit signalStrengthChanged(m_signal);
+
+ DP0("S60RadioTunerControl::MssoSignalStrengthChanged ---");
+}
+
+void S60RadioTunerControl::MTapoInitializeComplete(TInt aError)
+{
+ DP0("S60RadioTunerControl::MTapoInitializeComplete +++");
+ DP1("S60RadioTunerControl::MTapoInitializeComplete, aError:", aError);
+ if (aError == KErrNone) {
+ m_audioInitializationComplete = true;
+ m_available = true;
+ m_audioPlayerUtility->Play();
+ m_apiTunerState = QRadioTuner::ActiveState;
+ emit stateChanged(m_apiTunerState);
+ } else if (aError != KErrNone) {
+ m_radioError = QRadioTuner::OpenError;
+ }
+
+ DP0("S60RadioTunerControl::MTapoInitializeComplete ---");
+}
+
+void S60RadioTunerControl::MTapoPlayEvent(TEventType aEvent, TInt aError, TAny* aAdditionalInfo)
+{
+ DP0("S60RadioTunerControl::MTapoPlayEvent +++");
+
+ DP0("S60RadioTunerControl::MTapoPlayEvent ---");
+
+ // no actions
+}
+
+
+
diff --git a/src/plugins/symbian/mmf/radio/s60radiotunercontrol_31.h b/src/plugins/symbian/mmf/radio/s60radiotunercontrol_31.h
new file mode 100644
index 000000000..c8bb8d362
--- /dev/null
+++ b/src/plugins/symbian/mmf/radio/s60radiotunercontrol_31.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60RADIOTUNERCONTROL_H
+#define S60RADIOTUNERCONTROL_H
+
+#include <QtCore/qobject.h>
+#include <qradiotunercontrol.h>
+#include <qradiotuner.h>
+#include <tuner.h>
+
+class S60RadioTunerService;
+
+QT_USE_NAMESPACE
+
+class S60RadioTunerControl
+ : public QRadioTunerControl
+ , public MMMTunerObserver
+ , public MMMTunerStereoObserver
+ , public MMMSignalStrengthObserver
+ , public MMMTunerChangeObserver
+ , public MMMTunerAudioPlayerObserver
+{
+ Q_OBJECT
+public:
+ S60RadioTunerControl(QObject *parent = 0);
+ ~S60RadioTunerControl();
+
+ QRadioTuner::State state() const;
+
+ QRadioTuner::Band band() const;
+ void setBand(QRadioTuner::Band b);
+ bool isBandSupported(QRadioTuner::Band b) const;
+
+ int frequency() const;
+ int frequencyStep(QRadioTuner::Band b) const;
+ QPair<int,int> frequencyRange(QRadioTuner::Band b) const;
+ void setFrequency(int frequency);
+
+ bool isStereo() const;
+ QRadioTuner::StereoMode stereoMode() const;
+ void setStereoMode(QRadioTuner::StereoMode mode);
+
+ int signalStrength() const;
+
+ int volume() const;
+ void setVolume(int volume);
+
+ bool isMuted() const;
+ void setMuted(bool muted);
+
+ bool isSearching() const;
+ void searchForward();
+ void searchBackward();
+ void cancelSearch();
+
+ bool isValid() const;
+
+ bool isAvailable() const;
+ QtMultimediaKit::AvailabilityError availabilityError() const;
+
+ void start();
+ void stop();
+
+ QRadioTuner::Error error() const;
+ QString errorString() const;
+
+ //MMMTunerObserver
+ void MToTuneComplete(TInt aError);
+
+ //MMMTunerChangeObserver
+ void MTcoFrequencyChanged(const TFrequency& aOldFrequency, const TFrequency& aNewFrequency);
+ void MTcoStateChanged(const TUint32& aOldState, const TUint32& aNewState);
+ void MTcoAntennaDetached();
+ void MTcoAntennaAttached();
+ void FlightModeChanged(TBool aFlightMode);
+
+ //MMMTunerStereoObserver
+ void MTsoStereoReceptionChanged(TBool aStereo);
+ void MTsoForcedMonoChanged(TBool aForcedMono);
+
+ //MMMSignalStrengthObserver
+ void MssoSignalStrengthChanged(TInt aNewSignalStrength);
+
+ //MMMTunerAudioPlayerObserver
+ void MTapoInitializeComplete(TInt aError);
+ void MTapoPlayEvent(TEventType aEvent, TInt aError, TAny* aAdditionalInfo);
+
+private slots:
+
+
+private:
+ bool initRadio();
+ CMMTunerUtility::TTunerBand getNativeBand(QRadioTuner::Band b) const;
+
+ mutable int m_error;
+ CMMTunerUtility *m_tunerUtility;
+ CMMTunerAudioPlayerUtility *m_audioPlayerUtility;
+
+ bool m_audioInitializationComplete;
+ bool m_muted;
+ bool m_isStereo;
+ bool m_available;
+ int m_step;
+ int m_vol;
+ mutable int m_signal;
+ bool m_scanning;
+ bool forward;
+ QRadioTuner::Band m_currentBand;
+ qint64 m_currentFreq;
+
+ QRadioTuner::Error m_radioError;
+ QRadioTuner::StereoMode m_stereoMode;
+ QString m_errorString;
+ //caps meaning what the tuner can do.
+ TTunerCapabilities m_currentTunerCapabilities;
+ long m_tunerState;
+ QRadioTuner::State m_apiTunerState;
+
+};
+
+#endif
+
diff --git a/src/plugins/symbian/mmf/radio/s60radiotunercontrol_since32.cpp b/src/plugins/symbian/mmf/radio/s60radiotunercontrol_since32.cpp
new file mode 100644
index 000000000..991c6b8e4
--- /dev/null
+++ b/src/plugins/symbian/mmf/radio/s60radiotunercontrol_since32.cpp
@@ -0,0 +1,685 @@
+/****************************************************************************
+**
+** 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$
+** 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 "DebugMacros.h"
+
+#include "s60radiotunercontrol_since32.h"
+#include "s60radiotunerservice.h"
+
+#include <QtCore/qdebug.h>
+#include <RadioFmTunerUtility.h>
+
+S60RadioTunerControl::S60RadioTunerControl(QObject *parent)
+ : QRadioTunerControl(parent)
+ , m_error(0)
+ , m_radioUtility(NULL)
+ , m_fmTunerUtility(NULL)
+ , m_playerUtility(NULL)
+ , m_maxVolume(100)
+ , m_audioInitializationComplete(false)
+ , m_muted(false)
+ , m_isStereo(true)
+ , m_vol(50)
+ , m_signal(0)
+ , m_scanning(false)
+ , m_currentBand(QRadioTuner::FM)
+ , m_currentFreq(87500000)
+ , m_radioError(QRadioTuner::NoError)
+ , m_stereoMode(QRadioTuner::Auto)
+ , m_apiTunerState(QRadioTuner::StoppedState)
+ , m_previousSignal(0)
+ , m_volChangeRequired(false)
+ , m_signalStrengthTimer(new QTimer(this))
+{
+ DP0("S60RadioTunerControl::S60RadioTunerControl +++");
+ bool retValue = initRadio();
+ if (!retValue) {
+ m_errorString = QString(tr("Initialize Error."));
+ emit error(QRadioTuner::ResourceError);
+ } else {
+ connect(m_signalStrengthTimer, SIGNAL(timeout()), this, SLOT(changeSignalStrength()));
+ }
+ DP0("S60RadioTunerControl::S60RadioTunerControl ---");
+}
+
+S60RadioTunerControl::~S60RadioTunerControl()
+{
+ DP0("S60RadioTunerControl::~S60RadioTunerControl +++");
+
+ if (m_fmTunerUtility) {
+ m_fmTunerUtility->Close();
+ }
+
+ if (m_playerUtility) {
+ m_playerUtility->Close();
+ }
+
+ delete m_radioUtility;
+
+ DP0("S60RadioTunerControl::~S60RadioTunerControl ---");
+}
+
+QRadioTuner::State S60RadioTunerControl::state() const
+{
+ DP0("S60RadioTunerControl::state");
+
+ return m_apiTunerState;
+}
+
+QRadioTuner::Band S60RadioTunerControl::band() const
+{
+ DP0("S60RadioTunerControl::band");
+
+ return m_currentBand;
+}
+
+bool S60RadioTunerControl::isBandSupported(QRadioTuner::Band b) const
+{
+ DP0("S60RadioTunerControl::isBandSupported");
+ if (b == QRadioTuner::FM)
+ return true;
+ else if (b == QRadioTuner::LW)
+ return false;
+ else if (b == QRadioTuner::AM)
+ return false;
+ else if (b == QRadioTuner::SW)
+ return false;
+ else if (b == QRadioTuner::FM2)
+ return false;
+ else
+ return false;
+}
+
+void S60RadioTunerControl::changeSignalStrength()
+ {
+
+ int currentSignal = signalStrength();
+ if (currentSignal != m_previousSignal)
+ {
+ m_previousSignal = currentSignal;
+ emit signalStrengthChanged(currentSignal);
+ }
+ }
+void S60RadioTunerControl::setBand(QRadioTuner::Band b)
+{
+ DP0("S60RadioTunerControl::setBand +++");
+ QRadioTuner::Band tempBand = b;
+ if (tempBand != m_currentBand ) {
+ if (isBandSupported(tempBand)){
+ m_currentBand = b;
+ emit bandChanged(m_currentBand);
+ }
+ else {
+ switch(tempBand)
+ {
+ case QRadioTuner::FM :
+ m_errorString = QString(tr("Band FM not Supported"));
+ break;
+ case QRadioTuner::AM :
+ m_errorString = QString(tr("Band AM not Supported"));
+ break;
+ case QRadioTuner::SW :
+ m_errorString = QString(tr("Band SW not Supported"));
+ break;
+ case QRadioTuner::LW :
+ m_errorString = QString(tr("Band LW not Supported"));
+ break;
+ case QRadioTuner::FM2 :
+ m_errorString = QString(tr("Band FM2 not Supported"));
+ break;
+ default :
+ m_errorString = QString("Band %1 not Supported").arg(tempBand);
+ break;
+ }
+ emit error(QRadioTuner::OutOfRangeError);
+ }
+ }
+
+ DP0("S60RadioTunerControl::setBand ---");
+}
+
+int S60RadioTunerControl::frequency() const
+{
+ DP0("S60RadioTunerControl::frequency");
+
+ return m_currentFreq;
+}
+
+void S60RadioTunerControl::setFrequency(int frequency)
+{
+ DP0("S60RadioTunerControl::setFrequency +++");
+ DP1("S60RadioTunerControl::setFrequency, frequency:", frequency);
+
+ m_currentFreq = frequency;
+ m_fmTunerUtility->SetFrequency(m_currentFreq);
+
+ DP0("S60RadioTunerControl::setFrequency ---");
+}
+int S60RadioTunerControl::frequencyStep(QRadioTuner::Band b) const
+{
+ DP0("S60RadioTunerControl::frequencyStep +++");
+
+ int step = 0;
+ if (b == QRadioTuner::FM)
+ step = 100000; // 100kHz steps
+ else if(b == QRadioTuner::LW)
+ step = 1000; // 1kHz steps
+ else if (b == QRadioTuner::AM)
+ step = 1000; // 1kHz steps
+ else if(b == QRadioTuner::SW)
+ step = 500; // 500Hz steps
+ DP1("S60RadioTunerControl::frequencyStep, Step:", step);
+ DP0("S60RadioTunerControl::frequencyStep ---");
+
+ return step;
+}
+
+QPair<int,int> S60RadioTunerControl::frequencyRange(QRadioTuner::Band band) const
+{
+ DP0("S60RadioTunerControl::frequencyRange +++");
+
+ int bottomFreq;
+ int topFreq;
+
+ int bandError = KErrNone;
+ TFmRadioFrequencyRange range;
+
+ if (m_fmTunerUtility) {
+ bandError = m_fmTunerUtility->GetFrequencyRange(range, bottomFreq, topFreq);
+ }
+ if (!bandError) {
+ return qMakePair<int,int>(bottomFreq, topFreq);
+ }
+
+ DP0("S60RadioTunerControl::frequencyRange ---");
+
+ return qMakePair<int,int>(0,0);
+}
+
+bool S60RadioTunerControl::isStereo() const
+{
+ DP0("S60RadioTunerControl::isStereo");
+
+ return m_isStereo;
+}
+
+QRadioTuner::StereoMode S60RadioTunerControl::stereoMode() const
+{
+ DP0("S60RadioTunerControl::stereoMode");
+
+ return m_stereoMode;
+}
+
+void S60RadioTunerControl::setStereoMode(QRadioTuner::StereoMode mode)
+{
+ DP0("S60RadioTunerControl::setStereoMode +++");
+
+ if (m_fmTunerUtility) {
+ if (QRadioTuner::ForceMono == mode) {
+ m_fmTunerUtility->ForceMonoReception(true);
+ m_stereoMode = QRadioTuner::ForceMono;
+ m_isStereo = false;
+ } else {
+ m_fmTunerUtility->ForceMonoReception(false);
+ m_isStereo = true;
+ m_stereoMode = QRadioTuner::ForceStereo;
+ }
+ }
+
+ DP0("S60RadioTunerControl::setStereoMode ---");
+}
+
+int S60RadioTunerControl::signalStrength() const
+{
+ DP0("S60RadioTunerControl::signalStrength +++");
+
+ // return value is a percentage value
+ if (m_fmTunerUtility) {
+ TInt maxSignalStrength;
+ TInt currentSignalStrength;
+ m_error = m_fmTunerUtility->GetMaxSignalStrength(maxSignalStrength);
+
+ if (m_error == KErrNone) {
+ m_error = m_fmTunerUtility->GetSignalStrength(currentSignalStrength);
+ if (m_error == KErrNone) {
+ if (currentSignalStrength == 0 || maxSignalStrength == 0) {
+ return currentSignalStrength;
+ }
+ m_signal = ((TInt64)currentSignalStrength) * 100 / maxSignalStrength;
+ }
+ }
+ }
+
+ DP1("S60RadioTunerControl::signalStrength, m_signal:", m_signal);
+ DP0("S60RadioTunerControl::signalStrength ---");
+
+ return m_signal;
+}
+
+int S60RadioTunerControl::volume() const
+{
+ DP0("S60RadioTunerControl::volume");
+
+ return m_vol;
+}
+
+void S60RadioTunerControl::setVolume(int volume)
+{
+ DP0("S60RadioTunerControl::setVolume +++");
+ DP1("S60RadioTunerControl::setVolume, Volume:", volume);
+
+ int boundVolume = qBound(0, volume, 100);
+
+ if (m_vol == boundVolume )
+ return;
+
+ if (!m_muted && m_playerUtility) {
+ m_vol = boundVolume;
+ // Don't set volume until State is in Active State.
+ if (state() == QRadioTuner::ActiveState ) {
+ m_playerUtility->SetVolume(m_vol*m_volMultiplier);
+
+ } else {
+ m_volChangeRequired = TRUE;
+ emit volumeChanged(boundVolume);
+ }
+ }
+ DP0("S60RadioTunerControl::setVolume ---");
+}
+
+bool S60RadioTunerControl::isMuted() const
+{
+ DP0("S60RadioTunerControl::isMuted");
+
+ return m_muted;
+}
+
+void S60RadioTunerControl::setMuted(bool muted)
+{
+ DP0("S60RadioTunerControl::setMuted +++");
+ DP1("S60RadioTunerControl::setMuted, Muted:", muted);
+ if (m_playerUtility) {
+ m_muted = muted;
+ m_playerUtility->Mute(m_muted);
+ }
+ DP0("S60RadioTunerControl::setMuted ---");
+}
+
+bool S60RadioTunerControl::isSearching() const
+{
+ DP0("S60RadioTunerControl::isSearching");
+
+ return m_scanning;
+}
+
+void S60RadioTunerControl::cancelSearch()
+{
+ DP0("S60RadioTunerControl::cancelSearch +++");
+
+ m_fmTunerUtility->CancelStationSeek();
+ m_scanning = false;
+ emit searchingChanged(false);
+
+ DP0("S60RadioTunerControl::cancelSearch ---");
+}
+
+void S60RadioTunerControl::searchForward()
+{
+ DP0("S60RadioTunerControl::searchForward +++");
+ m_fmTunerUtility->StationSeek(true);
+ m_scanning = true;
+ emit searchingChanged(m_scanning);
+ DP0("S60RadioTunerControl::searchForward ---");
+}
+
+void S60RadioTunerControl::searchBackward()
+{
+ DP0("S60RadioTunerControl::searchBackward +++");
+ m_fmTunerUtility->StationSeek(false);
+ m_scanning = true;
+ emit searchingChanged(m_scanning);
+ DP0("S60RadioTunerControl::searchBackward ---");
+}
+
+bool S60RadioTunerControl::isValid() const
+{
+ DP0("S60RadioTunerControl::isValid");
+
+ return m_available;
+}
+
+bool S60RadioTunerControl::initRadio()
+{
+ DP0("S60RadioTunerControl::initRadio +++");
+ m_available = false;
+ // create an instance of Radio Utility factory and indicate
+ // FM Radio is a primary client
+ TRAPD(utilityError,
+ m_radioUtility = CRadioUtility::NewL(ETrue);
+ // Get a tuner utility
+ m_fmTunerUtility = &m_radioUtility->RadioFmTunerUtilityL(*this);
+ // we want to listen radio in offline mode too
+ m_fmTunerUtility->EnableTunerInOfflineMode(ETrue);
+ // Get a player utility
+ m_playerUtility = &m_radioUtility->RadioPlayerUtilityL(*this);
+ );
+ if (utilityError != KErrNone) {
+ m_radioError = QRadioTuner::ResourceError;
+ return m_available;
+ }
+
+ m_tunerControl = false;
+
+ m_available = true;
+ DP1("S60RadioTunerControl::initRadio, m_available:", m_available);
+ DP0("S60RadioTunerControl::initRadio ---");
+ return m_available;
+}
+
+bool S60RadioTunerControl::isAvailable() const
+{
+ DP0("S60RadioTunerControl::isAvailable");
+
+ return m_available;
+}
+
+QtMultimediaKit::AvailabilityError S60RadioTunerControl::availabilityError() const
+{
+ DP0("S60RadioTunerControl::availabilityError");
+ if (m_available)
+ return QtMultimediaKit::NoError;
+ else
+ return QtMultimediaKit::ResourceError;
+}
+
+void S60RadioTunerControl::start()
+{
+ DP0("S60RadioTunerControl::start +++");
+ if (!m_tunerControl) {
+ m_fmTunerUtility->RequestTunerControl();
+ } else {
+ m_playerUtility->Play();
+ }
+ m_signalStrengthTimer->start(3000);
+
+ DP0("S60RadioTunerControl::start ---");
+}
+
+void S60RadioTunerControl::stop()
+{
+ DP0("S60RadioTunerControl::stop +++");
+ if (m_playerUtility) {
+ m_playerUtility->Stop();
+ }
+ m_signalStrengthTimer->stop();
+ DP0("S60RadioTunerControl::stop ---");
+}
+
+QRadioTuner::Error S60RadioTunerControl::error() const
+{
+ DP1("S60RadioTunerControl::error", m_radioError);
+
+ return m_radioError;
+}
+QString S60RadioTunerControl::errorString() const
+{
+ DP1("S60RadioTunerControl::errorString", m_errorString);
+
+ return m_errorString;
+}
+
+void S60RadioTunerControl::MrpoStateChange(TPlayerState aState, TInt aError)
+{
+ DP0("S60RadioTunerControl::MrpoStateChange +++");
+ if (aError == KErrNone){
+ m_radioError = QRadioTuner::NoError;
+ if (aState == ERadioPlayerIdle) {
+ m_apiTunerState = QRadioTuner::StoppedState;
+ } else if (aState == ERadioPlayerPlaying) {
+ m_apiTunerState = QRadioTuner::ActiveState;
+ //Apply pending volume changes.
+ if(m_volChangeRequired){
+ setVolume(m_vol);
+ }
+ }
+ } else {
+ m_apiTunerState = QRadioTuner::StoppedState;
+ }
+ emit stateChanged(m_apiTunerState);
+ DP0("S60RadioTunerControl::MrpoStateChange ---");
+}
+
+void S60RadioTunerControl::MrpoVolumeChange(TInt aVolume)
+{
+ DP0("S60RadioTunerControl::MrpoVolumeChange +++");
+ DP1("S60RadioTunerControl::MrpoVolumeChange, aVolume:", aVolume);
+ m_vol = (aVolume/m_volMultiplier);
+ if (!m_volChangeRequired) {
+ emit volumeChanged(m_vol);
+
+ } else {
+ m_volChangeRequired = false;
+ }
+ DP0("S60RadioTunerControl::MrpoVolumeChange ---");
+}
+
+void S60RadioTunerControl::MrpoMuteChange(TBool aMute)
+{
+ DP0("S60RadioTunerControl::MrpoMuteChange +++");
+ DP1("S60RadioTunerControl::MrpoMuteChange, aMute:", aMute);
+ m_muted = aMute;
+ emit mutedChanged(m_muted);
+ DP0("S60RadioTunerControl::MrpoMuteChange ---");
+}
+
+void S60RadioTunerControl::MrpoBalanceChange(TInt aLeftPercentage, TInt aRightPercentage)
+{
+ DP0("S60RadioTunerControl::MrpoBalanceChange +++");
+
+ DP0("S60RadioTunerControl::MrpoBalanceChange ---");
+
+ // no actions
+}
+
+void S60RadioTunerControl::MrftoRequestTunerControlComplete(TInt aError)
+{
+ DP0("S60RadioTunerControl::MrftoRequestTunerControlComplete +++");
+ DP1("S60RadioTunerControl::MrftoRequestTunerControlComplete, aError:", aError);
+ if (aError == KErrNone) {
+ m_playerUtility->GetMaxVolume(m_maxVolume);
+ m_volMultiplier = float(m_maxVolume)/float(100);
+ m_radioError = QRadioTuner::NoError;
+ m_tunerControl = true;
+ m_available = true;
+ m_fmTunerUtility->SetFrequency(m_currentFreq);
+ m_playerUtility->Play();
+ int signal = signalStrength();
+ if (m_signal != signal) {
+ emit signalStrengthChanged(signal);
+ m_signal = signal;
+ }
+
+ } else if (aError == KFmRadioErrAntennaNotConnected) {
+ m_radioError = QRadioTuner::OpenError;
+ m_errorString = QString(tr("Antenna Not Connected"));
+ emit error(m_radioError);
+ } else if (aError == KErrAlreadyExists){
+ m_radioError = QRadioTuner::ResourceError;
+ m_errorString = QString(tr("Resource Error."));
+ emit error(m_radioError);
+ } else if (aError == KFmRadioErrFrequencyOutOfBandRange) {
+ m_radioError = QRadioTuner::OutOfRangeError;
+ m_errorString = QString(tr("Frequency out of band range"));
+ emit error(m_radioError);
+ }else{
+ m_radioError = QRadioTuner::OpenError;
+ m_errorString = QString(tr("Unknown Error."));
+ emit error(m_radioError);
+ }
+
+ DP0("S60RadioTunerControl::MrftoRequestTunerControlComplete ---");
+}
+
+void S60RadioTunerControl::MrftoSetFrequencyRangeComplete(TInt aError)
+{
+ DP0("S60RadioTunerControl::MrftoSetFrequencyRangeComplete +++");
+ DP1("S60RadioTunerControl::MrftoSetFrequencyRangeComplete, aError:", aError);
+ if (aError == KFmRadioErrFrequencyOutOfBandRange || KFmRadioErrFrequencyNotValid) {
+ m_radioError = QRadioTuner::OutOfRangeError;
+ m_errorString = QString(tr("Frequency Out of Band Range or Frequency Not Valid"));
+ emit error(m_radioError);
+ } else if (aError == KFmRadioErrHardwareFaulty || KFmRadioErrOfflineMode) {
+ m_radioError = QRadioTuner::OpenError;
+ m_errorString = QString(tr("Hardware failure or RadioInOfflineMode"));
+ emit error(m_radioError);
+ }
+ DP0("S60RadioTunerControl::MrftoSetFrequencyRangeComplete ---");
+}
+
+void S60RadioTunerControl::MrftoSetFrequencyComplete(TInt aError)
+{
+ DP0("S60RadioTunerControl::MrftoSetFrequencyComplete +++");
+ DP1("S60RadioTunerControl::MrftoSetFrequencyComplete, aError", aError);
+ if (aError == KErrNone) {
+ m_radioError = QRadioTuner::NoError;
+ } else if (aError == KFmRadioErrFrequencyOutOfBandRange || KFmRadioErrFrequencyNotValid) {
+ m_radioError = QRadioTuner::OutOfRangeError;
+ m_errorString = QString(tr("Frequency Out of range or not Valid."));
+ emit error(m_radioError);
+ } else if (aError == KFmRadioErrHardwareFaulty || KFmRadioErrOfflineMode) {
+ m_radioError = QRadioTuner::OpenError;
+ m_errorString = QString("Hardware failure or Radio In Offline Mode");
+ emit error(m_radioError);
+ }
+ DP0("S60RadioTunerControl::MrftoSetFrequencyComplete ---");
+}
+
+void S60RadioTunerControl::MrftoStationSeekComplete(TInt aError, TInt aFrequency)
+{
+ DP0("S60RadioTunerControl::MrftoStationSeekComplete +++");
+ DP3("S60RadioTunerControl::MrftoStationSeekComplete, aError:", aError, " Frequency:", aFrequency);
+ m_scanning = false;
+ if (aError == KErrNone) {
+ m_radioError = QRadioTuner::NoError;
+ m_currentFreq = aFrequency;
+ emit searchingChanged(m_scanning);
+ } else {
+ m_radioError = QRadioTuner::OpenError;
+ emit searchingChanged(m_scanning);
+ m_errorString = QString("Scanning Error");
+ emit error(m_radioError);
+ }
+ DP0("S60RadioTunerControl::MrftoStationSeekComplete ---");
+}
+
+void S60RadioTunerControl::MrftoFmTransmitterStatusChange(TBool aActive)
+{
+ DP0("S60RadioTunerControl::MrftoFmTransmitterStatusChange +++");
+
+ DP0("S60RadioTunerControl::MrftoFmTransmitterStatusChange ---");
+
+ //no actions
+}
+
+void S60RadioTunerControl::MrftoAntennaStatusChange(TBool aAttached)
+{
+ DP0("S60RadioTunerControl::MrftoAntennaStatusChange +++");
+ DP1("S60RadioTunerControl::MrftoAntennaStatusChange, aAttached:", aAttached);
+ if (aAttached && m_tunerControl) {
+ m_playerUtility->Play();
+ }
+ DP0("S60RadioTunerControl::MrftoAntennaStatusChange ---");
+}
+
+void S60RadioTunerControl::MrftoOfflineModeStatusChange(TBool /*aOfflineMode*/)
+{
+ DP0("S60RadioTunerControl::MrftoOfflineModeStatusChange +++");
+
+ DP0("S60RadioTunerControl::MrftoOfflineModeStatusChange ---");
+
+
+}
+
+void S60RadioTunerControl::MrftoFrequencyRangeChange(TFmRadioFrequencyRange aBand /*, TInt aMinFreq, TInt aMaxFreq*/)
+{
+ DP0("S60RadioTunerControl::MrftoFrequencyRangeChange +++");
+ if (aBand == EFmRangeEuroAmerica) {
+ setBand(QRadioTuner::FM);
+ }
+ DP0("S60RadioTunerControl::MrftoFrequencyRangeChange ---");
+}
+
+void S60RadioTunerControl::MrftoFrequencyChange(TInt aNewFrequency)
+{
+ DP0("S60RadioTunerControl::MrftoFrequencyChange +++");
+ DP1("S60RadioTunerControl::MrftoFrequencyChange, aNewFrequency:", aNewFrequency);
+ m_currentFreq = aNewFrequency;
+ emit frequencyChanged(m_currentFreq);
+
+ int signal = signalStrength();
+ if (m_signal != signal) {
+ emit signalStrengthChanged(signal);
+ m_signal = signal;
+ }
+ DP0("S60RadioTunerControl::MrftoFrequencyChange ---");
+}
+
+void S60RadioTunerControl::MrftoForcedMonoChange(TBool aForcedMono)
+{
+ DP0("S60RadioTunerControl::MrftoForcedMonoChange +++");
+ DP1("S60RadioTunerControl::MrftoForcedMonoChange, aForcedMono:", aForcedMono);
+ if (aForcedMono) {
+ m_stereoMode = QRadioTuner::ForceMono;
+ } else {
+ m_stereoMode = QRadioTuner::ForceStereo;
+ }
+ emit stereoStatusChanged(!aForcedMono);
+ DP0("S60RadioTunerControl::MrftoForcedMonoChange ---");
+}
+
+void S60RadioTunerControl::MrftoSquelchChange(TBool aSquelch)
+{
+ DP0("S60RadioTunerControl::MrftoSquelchChange");
+
+ DP1("S60RadioTunerControl::MrftoSquelchChange, aSquelch:", aSquelch);
+
+ // no actions
+}
diff --git a/src/plugins/symbian/mmf/radio/s60radiotunercontrol_since32.h b/src/plugins/symbian/mmf/radio/s60radiotunercontrol_since32.h
new file mode 100644
index 000000000..481d64c67
--- /dev/null
+++ b/src/plugins/symbian/mmf/radio/s60radiotunercontrol_since32.h
@@ -0,0 +1,296 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60RADIOTUNERCONTROL_H
+#define S60RADIOTUNERCONTROL_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qtimer.h>
+#include <qradiotunercontrol.h>
+#include <qradiotuner.h>
+
+#include <RadioUtility.h>
+#include <RadioFmTunerUtility.h>
+#include <RadioPlayerUtility.h>
+
+class S60RadioTunerService;
+class CFMRadioEngineCallObserver;
+
+QT_USE_NAMESPACE
+
+class S60RadioTunerControl
+ : public QRadioTunerControl
+ , public MRadioPlayerObserver
+ , public MRadioFmTunerObserver
+{
+ Q_OBJECT
+public:
+ S60RadioTunerControl(QObject *parent = 0);
+ ~S60RadioTunerControl();
+
+ QRadioTuner::State state() const;
+
+ QRadioTuner::Band band() const;
+ void setBand(QRadioTuner::Band b);
+ bool isBandSupported(QRadioTuner::Band b) const;
+
+ int frequency() const;
+ int frequencyStep(QRadioTuner::Band b) const;
+ QPair<int,int> frequencyRange(QRadioTuner::Band b) const;
+ void setFrequency(int frequency);
+
+ bool isStereo() const;
+ QRadioTuner::StereoMode stereoMode() const;
+ void setStereoMode(QRadioTuner::StereoMode mode);
+
+ int signalStrength() const;
+
+ int volume() const;
+ void setVolume(int volume);
+
+ bool isMuted() const;
+ void setMuted(bool muted);
+
+ bool isSearching() const;
+ void searchForward();
+ void searchBackward();
+ void cancelSearch();
+
+ bool isValid() const;
+
+ bool isAvailable() const;
+ QtMultimediaKit::AvailabilityError availabilityError() const;
+
+ void start();
+ void stop();
+
+ QRadioTuner::Error error() const;
+ QString errorString() const;
+
+ /**
+ * From MRadioPlayerObserver.
+ * Called when Radio state changed.
+ *
+ * @since S60 3.2
+ * @param aState Radio player state
+ * @param aError A standard system error code, only used when aState is ERadioPlayerIdle
+ */
+ void MrpoStateChange(TPlayerState aState, TInt aError);
+
+ /**
+ * From MRadioPlayerObserver.
+ * Called when volume changes. This may be caused by other applications.
+ *
+ * @since S60 3.2
+ * @param aVolume Current volume.
+ */
+ void MrpoVolumeChange(TInt aVolume);
+
+ /**
+ * From MRadioPlayerObserver.
+ * Called when mute setting changes. This may be caused by other applications.
+ *
+ * @since S60 3.2
+ * @param aMute ETrue indicates audio is muted.
+ */
+ void MrpoMuteChange(TBool aMute);
+
+ /**
+ * From MRadioPlayerObserver.
+ * Called when mute setting changes. This may be caused by other applications.
+ *
+ * Called when balance setting changes. This may be caused by other applications.
+ *
+ * @since S60 3.2
+ * Left speaker volume percentage. This can be any value from zero to 100.
+ * Zero value means left speaker is muted.
+ * @param aRightPercentage
+ * Right speaker volume percentage. This can be any value from zero to 100.
+ * Zero value means right speaker is muted.
+ */
+ void MrpoBalanceChange(TInt aLeftPercentage, TInt aRightPercentage);
+
+
+ /**
+ * From MRadioFmTunerObserver.
+ * Called when Request for tuner control completes.
+ *
+ * @since S60 3.2
+ * @param aError A standard system error code or FM tuner error (TFmRadioTunerError).
+ */
+ void MrftoRequestTunerControlComplete(TInt aError);
+
+ /**
+ * From MRadioFmTunerObserver.
+ * Set frequency range complete event. This event is asynchronous and is received after
+ * a call to CRadioFmTunerUtility::SetFrequencyRange.
+ *
+ * @since S60 3.2
+ * @param aError A standard system error code or FM tuner error (TFmRadioTunerError).
+ */
+ void MrftoSetFrequencyRangeComplete(TInt aError);
+
+ /**
+ * From MRadioFmTunerObserver.
+ * Set frequency complete event. This event is asynchronous and is received after a call to
+ * CRadioFmTunerUtility::SetFrequency.
+ *
+ * @since S60 3.2
+ * @param aError A standard system error code or FM tuner error (TFmRadioTunerError).
+ */
+ void MrftoSetFrequencyComplete(TInt aError);
+
+ /**
+ * From MRadioFmTunerObserver.
+ * Station seek complete event. This event is asynchronous and is received after a call to
+ * CRadioFmTunerUtility::StationSeek.
+ *
+ * @since S60 3.2
+ * @param aError A standard system error code or FM tuner error (TFmRadioTunerError).
+ * @param aFrequency The frequency(Hz) of the radio station that was found.
+ */
+ void MrftoStationSeekComplete(TInt aError, TInt aFrequency);
+
+ /**
+ * From MRadioFmTunerObserver.
+ * Called when FM Transmitter status changes (if one is present in the device). Tuner receiver
+ * is forced to be turned off due to hardware conflicts when FM transmitter is activated.
+ *
+ * @since S60 3.2
+ * @param aActive ETrue if FM transmitter is active; EFalse otherwise.
+ */
+ void MrftoFmTransmitterStatusChange(TBool aActive);
+
+ /**
+ * From MRadioFmTunerObserver.
+ * Called when antenna status changes.
+ *
+ * @since S60 3.2
+ * @param aAttached ETrue if antenna is attached; EFalse otherwise.
+ */
+ void MrftoAntennaStatusChange(TBool aAttached);
+
+ /**
+ * From MRadioFmTunerObserver.
+ * Called when offline mode status changes.
+ * @since S60 3.2
+ *
+ ** @param aAttached ETrue if offline mode is enabled; EFalse otherwise.
+ */
+ void MrftoOfflineModeStatusChange(TBool aOfflineMode);
+
+ /**
+ * From MRadioFmTunerObserver.
+ * Called when the frequency range changes. This may be caused by other applications.
+ *
+ * @since S60 3.2
+ * @param aNewRange New frequency range.
+ */
+ void MrftoFrequencyRangeChange(TFmRadioFrequencyRange aBand /*, TInt aMinFreq, TInt aMaxFreq*/);
+
+ /**
+ * From MRadioFmTunerObserver.
+ * Called when the tuned frequency changes. This may be caused by other
+ * applications or RDS if AF/TA is enabled.
+ *
+ * @since S60 3.2
+ * @param aNewFrequency The new tuned frequency(Hz).
+ */
+ void MrftoFrequencyChange(TInt aNewFrequency);
+
+ /**
+ * From MRadioFmTunerObserver.
+ * Called when the forced mono status change. This may be caused by other applications.
+ *
+ * @since S60 3.2
+ * @param aForcedMono ETrue if forced mono mode is enabled; EFalse otherwise.
+ */
+ void MrftoForcedMonoChange(TBool aForcedMono);
+
+ /**
+ * From MRadioFmTunerObserver.
+ * Called when the squelch (muting the frequencies without broadcast) status change.
+ * This may be caused by other applications.
+ *
+ * @since S60 3.2
+ * @param aSquelch ETrue if squelch is enabled; EFalse otherwise.
+ */
+ void MrftoSquelchChange(TBool aSquelch);
+
+private:
+ bool initRadio();
+
+ mutable int m_error;
+
+ CRadioUtility* m_radioUtility;
+ CRadioFmTunerUtility* m_fmTunerUtility;
+ CRadioPlayerUtility* m_playerUtility;
+ TInt m_maxVolume;
+ TReal m_volMultiplier;
+
+ bool m_tunerControl;
+ bool m_audioInitializationComplete;
+ bool m_muted;
+ bool m_isStereo;
+ bool m_available;
+ int m_vol;
+ bool m_volChangeRequired;
+ mutable int m_signal;
+ int m_previousSignal;
+ bool m_scanning;
+ QRadioTuner::Band m_currentBand;
+ qint64 m_currentFreq;
+
+ QRadioTuner::Error m_radioError;
+ QRadioTuner::StereoMode m_stereoMode;
+ QString m_errorString;
+ QRadioTuner::State m_apiTunerState;
+ QTimer *m_signalStrengthTimer;
+
+Q_SIGNALS:
+ void error(QRadioTuner::Error) const;
+
+protected slots:
+ void changeSignalStrength();
+};
+
+#endif
+
diff --git a/src/plugins/symbian/mmf/radio/s60radiotunerservice.cpp b/src/plugins/symbian/mmf/radio/s60radiotunerservice.cpp
new file mode 100644
index 000000000..99b0bf0d2
--- /dev/null
+++ b/src/plugins/symbian/mmf/radio/s60radiotunerservice.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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$
+** 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 "DebugMacros.h"
+
+#include "s60radiotunerservice.h"
+
+
+S60RadioTunerService::S60RadioTunerService(QObject *parent)
+ : QMediaService(parent)
+{
+ DP0("S60RadioTunerService::S60RadioTunerService +++");
+
+ m_playerControl = new S60RadioTunerControl(this);
+
+ DP0("S60RadioTunerService::S60RadioTunerService ---");
+}
+
+S60RadioTunerService::~S60RadioTunerService()
+{
+ DP0("S60RadioTunerService::~S60RadioTunerService +++");
+
+ delete m_playerControl;
+
+ DP0("S60RadioTunerService::~S60RadioTunerService ---");
+}
+
+QMediaControl *S60RadioTunerService::requestControl(const char* name)
+{
+ DP0("S60RadioTunerService::requestControl");
+
+ if (qstrcmp(name, QRadioTunerControl_iid) == 0)
+ return m_playerControl;
+
+ return 0;
+}
+
+void S60RadioTunerService::releaseControl(QMediaControl *control)
+{
+ DP0("S60RadioTunerService::releaseControl +++");
+
+ Q_UNUSED(control);
+
+ DP0("S60RadioTunerService::releaseControl ---");
+}
diff --git a/src/plugins/symbian/mmf/radio/s60radiotunerservice.h b/src/plugins/symbian/mmf/radio/s60radiotunerservice.h
new file mode 100644
index 000000000..92e3eb7f8
--- /dev/null
+++ b/src/plugins/symbian/mmf/radio/s60radiotunerservice.h
@@ -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$
+** 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 S60RADIOTUNERSERVICE_H
+#define S60RADIOTUNERSERVICE_H
+
+#include <QtCore/qobject.h>
+
+#include <qmediaservice.h>
+
+#ifdef TUNERLIBUSED
+#include "s60radiotunercontrol_31.h"
+#else
+#include "s60radiotunercontrol_since32.h"
+#endif
+
+QT_USE_NAMESPACE
+
+class S60RadioTunerService : public QMediaService
+{
+ Q_OBJECT
+public:
+ S60RadioTunerService(QObject *parent = 0);
+ ~S60RadioTunerService();
+
+ QMediaControl *requestControl(const char* name);
+ void releaseControl(QMediaControl *control);
+
+private:
+ S60RadioTunerControl *m_playerControl;
+};
+
+#endif
diff --git a/src/plugins/symbian/mmf/s60formatsupported.cpp b/src/plugins/symbian/mmf/s60formatsupported.cpp
new file mode 100644
index 000000000..e892008ab
--- /dev/null
+++ b/src/plugins/symbian/mmf/s60formatsupported.cpp
@@ -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$
+** 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 "s60formatsupported.h"
+
+
+
+S60FormatSupported::S60FormatSupported()
+{}
+
+S60FormatSupported::~S60FormatSupported()
+{
+ if (m_controllerparam) {
+ delete m_controllerparam;
+ m_controllerparam = NULL;
+ }
+}
+
+QStringList S60FormatSupported::supportedPlayMimeTypesL()
+{
+
+ RArray<TUid> mediaIds; //search for both audio and video
+
+ RMMFControllerImplInfoArray iControllers;
+
+ m_controllerparam = CMMFControllerPluginSelectionParameters::NewL();
+
+ m_playformatparam = CMMFFormatSelectionParameters::NewL();
+
+ mediaIds.Append(KUidMediaTypeAudio);
+
+ mediaIds.Append(KUidMediaTypeVideo);
+
+ m_controllerparam->SetMediaIdsL(mediaIds, CMMFPluginSelectionParameters::EAllowOtherMediaIds);
+
+ m_controllerparam->SetRequiredPlayFormatSupportL(*m_playformatparam);
+
+ m_controllerparam->ListImplementationsL(iControllers);
+
+ CDesC8ArrayFlat* controllerArray = new (ELeave) CDesC8ArrayFlat(1);
+
+ for (TInt i = 0; i < iControllers.Count(); i++) {
+ for (TInt j = 0; j < (iControllers[i]->PlayFormats()).Count(); j++) {
+ const CDesC8Array& iarr = (iControllers[i]->PlayFormats()[j]->SupportedMimeTypes());
+
+ TInt count = iarr.Count();
+
+ for (TInt k = 0; k < count; k++) {
+ TPtrC8 ptr = iarr.MdcaPoint(k);
+
+ HBufC8* n = HBufC8::NewL(ptr.Length());
+
+ TPtr8 ptr1 = n->Des();
+
+ ptr1.Copy((TUint8*) ptr.Ptr(), ptr.Length());
+
+ controllerArray->AppendL(ptr1);
+ }
+ }
+ }
+
+// converting CDesC8Array to QStringList
+ for (TInt x = 0; x < controllerArray->Count(); x++) {
+ m_supportedplaymime.append(QString::fromUtf8(
+ (const char*) (controllerArray->MdcaPoint(x).Ptr()),
+ controllerArray->MdcaPoint(x).Length()));
+ }
+
+ // populating the list with only audio and controller mime types
+ QStringList tempaudio = m_supportedplaymime.filter(QString("audio"));
+ QStringList tempvideo = m_supportedplaymime.filter(QString("video"));
+
+ m_supportedplaymime.clear();
+
+ m_supportedplaymime = tempaudio + tempvideo;
+
+ mediaIds.Close();
+ delete controllerArray;
+ iControllers.ResetAndDestroy();
+
+ return m_supportedplaymime;
+}
diff --git a/src/plugins/symbian/mmf/s60formatsupported.h b/src/plugins/symbian/mmf/s60formatsupported.h
new file mode 100644
index 000000000..3b5a3ffe6
--- /dev/null
+++ b/src/plugins/symbian/mmf/s60formatsupported.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60FORMATSUPPORTED_H_
+#define S60FORMATSUPPORTED_H_
+
+#include <mmf/common/mmfcontrollerpluginresolver.h>
+#include <mmf/server/mmfdatasourcesink.hrh>
+#include <qstringlist.h>
+#include <badesca.h>
+#include <qstring.h>
+
+class S60FormatSupported
+{
+public:
+ S60FormatSupported();
+ ~S60FormatSupported();
+
+ QStringList supportedPlayMimeTypesL();
+
+private:
+
+ CMMFFormatSelectionParameters* m_playformatparam;
+ CMMFControllerPluginSelectionParameters* m_controllerparam;
+ QStringList m_supportedplaymime;
+};
+#endif /* S60FORMATSUPPORTED_H_ */
diff --git a/src/plugins/symbian/mmf/s60mediaserviceplugin.cpp b/src/plugins/symbian/mmf/s60mediaserviceplugin.cpp
new file mode 100644
index 000000000..cfb77255f
--- /dev/null
+++ b/src/plugins/symbian/mmf/s60mediaserviceplugin.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qstring.h>
+#include <QtCore/qdebug.h>
+
+#include "s60mediaserviceplugin.h"
+#if defined(TUNERLIBUSED) || defined(RADIOUTILITYLIBUSED)
+#include "s60radiotunerservice.h"
+#endif
+#ifdef HAS_MEDIA_PLAYER
+#include "s60mediaplayerservice.h"
+#endif
+#ifdef AUDIOSOURCEUSED
+#include "s60audiocaptureservice.h"
+#endif /* AUDIOSOURCEUSED */
+
+QStringList S60MediaServicePlugin::keys() const
+{
+ QStringList list;
+#if defined(TUNERLIBUSED) || defined(RADIOUTILITYLIBUSED)
+ list << QLatin1String(Q_MEDIASERVICE_RADIO);
+#endif
+
+#ifdef HAS_MEDIA_PLAYER
+ list << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER);
+#endif
+#ifdef AUDIOSOURCEUSED
+ list << QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE);
+#endif /* AUDIOSOURCEUSED */
+ return list;
+}
+
+QMediaService* S60MediaServicePlugin::create(QString const& key)
+{
+#ifdef HAS_MEDIA_PLAYER
+ if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER))
+ return new S60MediaPlayerService;
+#endif
+#ifdef AUDIOSOURCEUSED
+ if (key == QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE))
+ return new S60AudioCaptureService;
+#endif /* AUDIOSOURCEUSED */
+#if defined(TUNERLIBUSED) || defined(RADIOUTILITYLIBUSED)
+ if (key == QLatin1String(Q_MEDIASERVICE_RADIO))
+ return new S60RadioTunerService;
+#endif
+
+ return 0;
+}
+
+void S60MediaServicePlugin::release(QMediaService *service)
+{
+ delete service;
+}
+
+QtMultimediaKit::SupportEstimate S60MediaServicePlugin::hasSupport(const QString &mimeType, const QStringList& codecs) const
+{
+ Q_UNUSED(mimeType);
+ Q_UNUSED(codecs);
+ return QtMultimediaKit::PreferredService;
+}
+
+QStringList S60MediaServicePlugin::supportedMimeTypes() const
+{
+ if (m_supportedmimetypes.isEmpty()) {
+ TInt err;
+ S60FormatSupported* formats = new (ELeave) S60FormatSupported();
+ if (formats) {
+ TRAP(err, m_supportedmimetypes = formats->supportedPlayMimeTypesL());
+ delete formats;
+ }
+ }
+ return m_supportedmimetypes;
+}
+
+Q_EXPORT_PLUGIN2(qtmultimediakit_mmfengine, S60MediaServicePlugin);
diff --git a/src/plugins/symbian/mmf/s60mediaserviceplugin.h b/src/plugins/symbian/mmf/s60mediaserviceplugin.h
new file mode 100644
index 000000000..b2140dd6f
--- /dev/null
+++ b/src/plugins/symbian/mmf/s60mediaserviceplugin.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60SERVICEPLUGIN_H
+#define S60SERVICEPLUGIN_H
+
+#include <QtCore/qobject.h>
+#include <qmediaservice.h>
+#include <qmediaserviceproviderplugin.h>
+#include "s60formatsupported.h"
+
+QT_USE_NAMESPACE
+
+class S60MediaServicePlugin : public QMediaServiceProviderPlugin,public QMediaServiceSupportedFormatsInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceSupportedFormatsInterface)
+public:
+
+ QStringList keys() const;
+ QMediaService* create(QString const& key);
+ void release(QMediaService *service);
+
+ QtMultimediaKit::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const;
+ QStringList supportedMimeTypes() const;
+private:
+ mutable QStringList m_supportedmimetypes;
+};
+
+#endif // S60SERVICEPLUGIN_H
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/mediaplayer.pri b/src/plugins/symbian/openmaxal/mediaplayer/mediaplayer.pri
new file mode 100644
index 000000000..7c6843e19
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/mediaplayer.pri
@@ -0,0 +1,36 @@
+INCLUDEPATH += $$PWD
+
+LIBS += \
+ -lws32 \
+ -lcone
+
+#DEFINES += USE_VIDEOPLAYERUTILITY
+
+HEADERS += \
+ $$PWD/qxametadatacontrol.h \
+ $$PWD/qxamediastreamscontrol.h \
+ $$PWD/qxamediaplayercontrol.h \
+ $$PWD/qxaplaymediaservice.h \
+ $$PWD/qxaplaysession.h \
+ $$PWD/xaplaysessioncommon.h \
+ $$PWD/qxavideowidgetcontrol.h \
+ $$PWD/qxavideowindowcontrol.h \
+ $$PWD/qxawidget.h \
+ $$PWD/xaplaysessionimpl.h
+
+SOURCES += \
+ $$PWD/qxamediaplayercontrol.cpp \
+ $$PWD/qxametadatacontrol.cpp \
+ $$PWD/qxamediastreamscontrol.cpp \
+ $$PWD/qxaplaymediaservice.cpp \
+ $$PWD/qxaplaysession.cpp \
+ $$PWD/qxavideowidgetcontrol.cpp \
+ $$PWD/qxavideowindowcontrol.cpp \
+ $$PWD/qxawidget.cpp \
+ $$PWD/xaplaysessionimpl.cpp
+
+# check for USE_VIDEOPLAYERUTILITY
+contains(DEFINES, USE_VIDEOPLAYERUTILITY) {
+ message("Using VideoPlayerUtility instead of OpenMAX AL.")
+ LIBS += -lmediaclientvideo
+}
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxamediaplayercontrol.cpp b/src/plugins/symbian/openmaxal/mediaplayer/qxamediaplayercontrol.cpp
new file mode 100644
index 000000000..ee192105b
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxamediaplayercontrol.cpp
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <QtCore/qurl.h>
+#include "qxamediaplayercontrol.h"
+#include "qxaplaysession.h"
+#include "qxacommon.h"
+
+QXAMediaPlayerControl::QXAMediaPlayerControl(QXAPlaySession *session, QObject *parent)
+ :QMediaPlayerControl(parent), mSession(session)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ connect(mSession, SIGNAL(mediaChanged(const QMediaContent &)),
+ this, SIGNAL(mediaChanged(const QMediaContent& )));
+ connect(mSession, SIGNAL(durationChanged(qint64)),
+ this, SIGNAL(durationChanged(qint64)));
+ connect(mSession, SIGNAL(positionChanged(qint64)),
+ this, SIGNAL(positionChanged(qint64)));
+ connect(mSession, SIGNAL(stateChanged(QMediaPlayer::State)),
+ this, SIGNAL(stateChanged(QMediaPlayer::State)));
+ connect(mSession, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
+ this, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ connect(mSession, SIGNAL(volumeChanged(int)),
+ this, SIGNAL(volumeChanged(int)));
+ connect(mSession, SIGNAL(mutedChanged(bool)),
+ this, SIGNAL(mutedChanged(bool)));
+ connect(mSession, SIGNAL(audioAvailableChanged(bool)),
+ this, SIGNAL(audioAvailableChanged(bool)));
+ connect(mSession, SIGNAL(videoAvailableChanged(bool)),
+ this, SIGNAL(videoAvailableChanged(bool)));
+ connect(mSession,SIGNAL(bufferStatusChanged(int)),
+ this, SIGNAL(bufferStatusChanged(int)));
+ connect(mSession, SIGNAL(seekableChanged(bool)),
+ this, SIGNAL(seekableChanged(bool)));
+ connect(mSession, SIGNAL(availablePlaybackRangesChanged(const QMediaTimeRange&)),
+ this, SIGNAL(availablePlaybackRangesChanged(const QMediaTimeRange&)));
+ connect(mSession, SIGNAL(playbackRateChanged(qreal)),
+ this, SIGNAL(playbackRateChanged(qreal)));
+ connect(mSession, SIGNAL(error(int, const QString &)),
+ this, SIGNAL(error(int, const QString &)));
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+QXAMediaPlayerControl::~QXAMediaPlayerControl()
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+}
+
+QMediaPlayer::State QXAMediaPlayerControl::state() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ QMediaPlayer::State retVal = QMediaPlayer::StoppedState;
+ RET_s_IF_p_IS_NULL(mSession, retVal);
+ retVal = mSession->state();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+QMediaPlayer::MediaStatus QXAMediaPlayerControl::mediaStatus() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ QMediaPlayer::MediaStatus retVal = QMediaPlayer::NoMedia;
+ RET_s_IF_p_IS_NULL(mSession, retVal);
+ retVal = mSession->mediaStatus();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+qint64 QXAMediaPlayerControl::duration() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ qint64 retVal = 0;
+ RET_s_IF_p_IS_NULL(mSession, retVal);
+ retVal = mSession->duration();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+qint64 QXAMediaPlayerControl::position() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ qint64 retVal = 0;
+ RET_s_IF_p_IS_NULL(mSession, retVal);
+ retVal = mSession->position();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+void QXAMediaPlayerControl::setPosition(qint64 pos)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_IF_p_IS_NULL(mSession);
+ mSession->setPosition(pos);
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+int QXAMediaPlayerControl::volume() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ int retVal = 0;
+ RET_s_IF_p_IS_NULL(mSession, retVal);
+ retVal = mSession->volume();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+void QXAMediaPlayerControl::setVolume(int volume)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_IF_p_IS_NULL(mSession);
+ mSession->setVolume(volume);
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+bool QXAMediaPlayerControl::isMuted() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ bool retVal = false;
+ RET_s_IF_p_IS_NULL(mSession, retVal);
+ retVal = mSession->isMuted();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+void QXAMediaPlayerControl::setMuted(bool muted)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_IF_p_IS_NULL(mSession);
+ mSession->setMuted(muted);
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+int QXAMediaPlayerControl::bufferStatus() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ int retVal = 0;
+ RET_s_IF_p_IS_NULL(mSession, retVal);
+ retVal = mSession->bufferStatus();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+bool QXAMediaPlayerControl::isAudioAvailable() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ bool retVal = false;
+ RET_s_IF_p_IS_NULL(mSession, retVal);
+ retVal = mSession->isAudioAvailable();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+bool QXAMediaPlayerControl::isVideoAvailable() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ bool retVal = false;
+ RET_s_IF_p_IS_NULL(mSession, retVal);
+ retVal = mSession->isVideoAvailable();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+bool QXAMediaPlayerControl::isSeekable() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ bool retVal = false;
+ RET_s_IF_p_IS_NULL(mSession, retVal);
+ retVal = mSession->isSeekable();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+QMediaTimeRange QXAMediaPlayerControl::availablePlaybackRanges() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ QMediaTimeRange retVal;
+ RET_s_IF_p_IS_NULL(mSession, retVal);
+ if (mSession->isSeekable())
+ retVal.addInterval(0, mSession->duration());
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+float QXAMediaPlayerControl::playbackRate() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ float retVal = 0;
+ RET_s_IF_p_IS_NULL(mSession, retVal);
+ retVal = mSession->playbackRate();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+void QXAMediaPlayerControl::setPlaybackRate(float rate)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_IF_p_IS_NULL(mSession);
+ mSession->setPlaybackRate(rate);
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+QMediaContent QXAMediaPlayerControl::media() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ QMediaContent retVal;
+ RET_s_IF_p_IS_NULL(mSession, retVal);
+ retVal = mSession->media();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+const QIODevice *QXAMediaPlayerControl::mediaStream() const
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return mStream;
+}
+
+void QXAMediaPlayerControl::setMedia(const QMediaContent &content, QIODevice *stream)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_IF_p_IS_NULL(mSession);
+ mSession->setMedia(content);
+ mStream = stream;
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXAMediaPlayerControl::play()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_IF_p_IS_NULL(mSession);
+ mSession->play();
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXAMediaPlayerControl::pause()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_IF_p_IS_NULL(mSession);
+ mSession->pause();
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXAMediaPlayerControl::stop()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_IF_p_IS_NULL(mSession);
+ mSession->stop();
+ QT_TRACE_FUNCTION_EXIT;
+}
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxamediaplayercontrol.h b/src/plugins/symbian/openmaxal/mediaplayer/qxamediaplayercontrol.h
new file mode 100644
index 000000000..b9d7802bd
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxamediaplayercontrol.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QXAMEDIAPLAYERCONTROL_H
+#define QXAMEDIAPLAYERCONTROL_H
+
+#include "qmediaplayercontrol.h"
+#include "qmediaplayer.h"
+
+QT_USE_NAMESPACE
+
+class QXAPlaySession;
+
+class QXAMediaPlayerControl : public QMediaPlayerControl
+{
+ Q_OBJECT
+public:
+ QXAMediaPlayerControl(QXAPlaySession *session, QObject *parent = 0);
+ ~QXAMediaPlayerControl();
+
+ QMediaPlayer::State state() const;
+ QMediaPlayer::MediaStatus mediaStatus() const;
+
+ qint64 duration() const;
+
+ qint64 position() const;
+ void setPosition(qint64 position);
+
+ int volume() const;
+ void setVolume(int volume);
+
+ bool isMuted() const;
+ void setMuted(bool muted);
+
+ int bufferStatus() const;
+
+ bool isAudioAvailable() const;
+ bool isVideoAvailable() const;
+
+ bool isSeekable() const;
+
+ QMediaTimeRange availablePlaybackRanges() const;
+
+ float playbackRate() const;
+ void setPlaybackRate(float rate);
+
+ QMediaContent media() const;
+ const QIODevice *mediaStream() const;
+ void setMedia(const QMediaContent&, QIODevice *);
+
+ void play();
+ void pause();
+ void stop();
+
+
+private:
+ QXAPlaySession *mSession;
+ QIODevice *mStream;
+};
+
+#endif /* QXAMEDIAPLAYERCONTROL_H */
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxamediastreamscontrol.cpp b/src/plugins/symbian/openmaxal/mediaplayer/qxamediastreamscontrol.cpp
new file mode 100644
index 000000000..528fb1837
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxamediastreamscontrol.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qurl.h>
+
+#include "qxamediastreamscontrol.h"
+#include "qxaplaysession.h"
+#include "qxacommon.h"
+
+QXAMediaStreamsControl::QXAMediaStreamsControl(QXAPlaySession *session, QObject *parent)
+ :QMediaStreamsControl(parent), mSession(session)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ connect(mSession, SIGNAL(activeStreamsChanged()),
+ this, SIGNAL(activeStreamsChanged()));
+ connect(mSession, SIGNAL(streamsChanged()),
+ this, SIGNAL(streamsChanged()));
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+QXAMediaStreamsControl::~QXAMediaStreamsControl()
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+}
+
+bool QXAMediaStreamsControl::isActive (int stream)
+{
+ RET_s_IF_p_IS_NULL(mSession, false);
+ return mSession->isStreamActive(stream);
+}
+
+QVariant QXAMediaStreamsControl::metaData (int stream, QtMultimediaKit::MetaData key)
+{
+ QVariant var;
+ RET_s_IF_p_IS_NULL(mSession, var);
+ QT_TRACE_FUNCTION_ENTRY;
+ var = mSession->metaData(stream, key);
+ QT_TRACE_FUNCTION_EXIT;
+ return var;
+}
+
+void QXAMediaStreamsControl::setActive (int stream, bool state)
+{
+ Q_UNUSED(stream);
+ Q_UNUSED(state);
+}
+
+int QXAMediaStreamsControl::streamCount()
+{
+ RET_s_IF_p_IS_NULL(mSession, 0);
+ return mSession->streamCount();
+}
+
+QMediaStreamsControl::StreamType QXAMediaStreamsControl::streamType (int stream)
+{
+ RET_s_IF_p_IS_NULL(mSession, QMediaStreamsControl::UnknownStream);
+ return mSession->streamType(stream);
+}
+
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxamediastreamscontrol.h b/src/plugins/symbian/openmaxal/mediaplayer/qxamediastreamscontrol.h
new file mode 100644
index 000000000..d77b89ca5
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxamediastreamscontrol.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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$
+** 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 QXAMEDIASTREAMSCONTROL_H
+#define QXAMEDIASTREAMSCONTROL_H
+
+
+
+#include <QStringList>
+#include <QList>
+#include <QVariant>
+#include <QString>
+
+#include <qtmedianamespace.h>
+
+#include <qmediastreamscontrol.h>
+
+QT_USE_NAMESPACE
+
+class QXAPlaySession;
+
+class QXAMediaStreamsControl : public QMediaStreamsControl
+{
+ Q_OBJECT
+public:
+ QXAMediaStreamsControl(QXAPlaySession *session, QObject *parent = 0);
+ ~QXAMediaStreamsControl();
+
+ bool isActive (int stream);
+ QVariant metaData (int stream, QtMultimediaKit::MetaData key);
+ void setActive (int stream, bool state);
+ int streamCount();
+ QMediaStreamsControl::StreamType streamType (int stream);
+private:
+ QXAPlaySession *mSession;
+};
+
+#endif //QXAMEDIASTREAMSCONTROL_H
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxametadatacontrol.cpp b/src/plugins/symbian/openmaxal/mediaplayer/qxametadatacontrol.cpp
new file mode 100644
index 000000000..9c6b906cf
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxametadatacontrol.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qurl.h>
+
+#include "qxametadatacontrol.h"
+#include "qxaplaysession.h"
+#include "qxacommon.h"
+
+QXAMetaDataControl::QXAMetaDataControl(QXAPlaySession *session, QObject *parent)
+ :QMetaDataReaderControl(parent), mSession(session)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ connect(mSession, SIGNAL(metaDataAvailableChanged(bool)),
+ this, SIGNAL(metaDataAvailableChanged(bool)));
+ connect(mSession, SIGNAL(metaDataChanged()),
+ this, SIGNAL(metaDataChanged()));
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+QXAMetaDataControl::~QXAMetaDataControl()
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+}
+
+QStringList QXAMetaDataControl::availableExtendedMetaData ()const
+{
+ QStringList list;
+ RET_s_IF_p_IS_NULL(mSession, list);
+ QT_TRACE_FUNCTION_ENTRY;
+ list = mSession->availableExtendedMetaData();
+ QT_TRACE_FUNCTION_EXIT;
+ return list;
+}
+
+QList<QtMultimediaKit::MetaData> QXAMetaDataControl::availableMetaData () const
+{
+ QList<QtMultimediaKit::MetaData> list;
+ RET_s_IF_p_IS_NULL(mSession, list);
+ QT_TRACE_FUNCTION_ENTRY;
+ list = mSession->availableMetaData();
+ QT_TRACE_FUNCTION_EXIT;
+ return list;
+}
+
+QVariant QXAMetaDataControl::extendedMetaData(const QString & key ) const
+{
+ QVariant var;
+ RET_s_IF_p_IS_NULL(mSession, var);
+ QT_TRACE_FUNCTION_ENTRY;
+ var = mSession->extendedMetaData(key);
+ QT_TRACE_FUNCTION_EXIT;
+ return var;
+}
+
+bool QXAMetaDataControl::isMetaDataAvailable() const
+{
+ RET_s_IF_p_IS_NULL(mSession, false);
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return mSession->isMetaDataAvailable();
+}
+
+bool QXAMetaDataControl::isWritable() const
+{
+ RET_s_IF_p_IS_NULL(mSession, false);
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return mSession->isWritable();
+}
+
+QVariant QXAMetaDataControl::metaData( QtMultimediaKit::MetaData key ) const
+{
+ QVariant var;
+ RET_s_IF_p_IS_NULL(mSession, var);
+ QT_TRACE_FUNCTION_ENTRY;
+ var = mSession->metaData(key);
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return var;
+}
+
+void QXAMetaDataControl::setExtendedMetaData( const QString & key, const QVariant & value )
+{
+ RET_IF_p_IS_NULL(mSession);
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return mSession->setExtendedMetaData(key,value);
+}
+
+void QXAMetaDataControl::setMetaData( QtMultimediaKit::MetaData key, const QVariant & value )
+{
+ RET_IF_p_IS_NULL(mSession);
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return mSession->setMetaData(key,value);
+}
+
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxametadatacontrol.h b/src/plugins/symbian/openmaxal/mediaplayer/qxametadatacontrol.h
new file mode 100644
index 000000000..8904a5ff4
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxametadatacontrol.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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$
+** 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 QXAMETADATACONTROL_H
+#define QXAMETADATACONTROL_H
+
+
+
+#include <QStringList>
+#include <QList>
+#include <QVariant>
+#include <QString>
+
+#include <qmetadatareadercontrol.h>
+#include <qtmedianamespace.h>
+QT_USE_NAMESPACE
+
+class QXAPlaySession;
+
+class QXAMetaDataControl : public QMetaDataReaderControl
+{
+ Q_OBJECT
+public:
+ QXAMetaDataControl(QXAPlaySession *session, QObject *parent = 0);
+ ~QXAMetaDataControl();
+
+ QStringList availableExtendedMetaData () const;
+ QList<QtMultimediaKit::MetaData> availableMetaData () const;
+ QVariant extendedMetaData(const QString & key ) const;
+ bool isMetaDataAvailable() const;
+ bool isWritable() const;
+ QVariant metaData( QtMultimediaKit::MetaData key ) const;
+ void setExtendedMetaData( const QString & key, const QVariant & value );
+ void setMetaData( QtMultimediaKit::MetaData key, const QVariant & value );
+
+private:
+ QXAPlaySession *mSession;
+};
+
+#endif //QXAMETADATACONTROL_H
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxaplaymediaservice.cpp b/src/plugins/symbian/openmaxal/mediaplayer/qxaplaymediaservice.cpp
new file mode 100644
index 000000000..f2d3c4b15
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxaplaymediaservice.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <QString>
+#include "qxaplaymediaservice.h"
+#include "qxaplaysession.h"
+#include "qxamediaplayercontrol.h"
+#include "qxacommon.h"
+#include "qxavideowidgetcontrol.h"
+#include "qxavideowindowcontrol.h"
+#include "qxametadatacontrol.h"
+#include "qxamediastreamscontrol.h"
+
+QXAPlayMediaService::QXAPlayMediaService(QObject *parent) : QMediaService(parent)
+{
+ mSession = NULL;
+ mMediaPlayerControl = NULL;
+ mVideowidgetControl = NULL;
+ mVideoWindowControl = NULL;
+ mMetaDataControl = NULL;
+ mMediaStreamsControl = NULL;
+
+ mSession = new QXAPlaySession(this);
+ mMediaPlayerControl = new QXAMediaPlayerControl(mSession, this);
+ mMetaDataControl = new QXAMetaDataControl(mSession, this);
+ mMediaStreamsControl = new QXAMediaStreamsControl(mSession, this);
+}
+
+QXAPlayMediaService::~QXAPlayMediaService()
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+}
+
+QMediaControl *QXAPlayMediaService::requestControl(const char *name)
+{
+ if (qstrcmp(name, QMediaPlayerControl_iid) == 0) {
+ return mMediaPlayerControl;
+ }
+ else if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
+ if (!mVideowidgetControl) {
+ mVideowidgetControl = new QXAVideoWidgetControl(mSession, this);
+ if (mSession && mVideowidgetControl)
+ mSession->setVideoWidgetControl(mVideowidgetControl);
+ }
+ return mVideowidgetControl;
+ }
+ else if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
+ if (!mVideoWindowControl) {
+ mVideoWindowControl = new QXAVideoWindowControl(mSession, this);
+ if (mSession && mVideoWindowControl)
+ mSession->setVideoWindowControl(mVideoWindowControl);
+ }
+ return mVideoWindowControl;
+ }
+ else if (qstrcmp(name,QMetaDataReaderControl_iid) == 0) {
+ return mMetaDataControl;
+ }
+ else if (qstrcmp(name,QMediaStreamsControl_iid) == 0) {
+ return mMediaStreamsControl;
+ }
+
+ return 0;
+}
+
+void QXAPlayMediaService::releaseControl(QMediaControl *control)
+{
+ if (control == mVideowidgetControl) {
+ if (mSession)
+ mSession->unsetVideoWidgetControl(qobject_cast<QXAVideoWidgetControl*>(control));
+ mVideowidgetControl = NULL;
+ }
+ else if (control == mVideoWindowControl) {
+ if (mSession)
+ mSession->unsetVideoWindowControl(qobject_cast<QXAVideoWindowControl*>(control));
+ mVideoWindowControl = NULL;
+ }
+}
+
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxaplaymediaservice.h b/src/plugins/symbian/openmaxal/mediaplayer/qxaplaymediaservice.h
new file mode 100644
index 000000000..4a344b087
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxaplaymediaservice.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QXAPLAYMEDIASERVICE_H
+#define QXAPLAYMEDIASERVICE_H
+
+#include <QtCore/qobject.h>
+#include <qmediaservice.h>
+
+QT_USE_NAMESPACE
+
+class QXAPlaySession;
+class QXAMediaPlayerControl;
+class QXAVideoWidgetControl;
+class QXAVideoWindowControl;
+class QXAMetaDataControl;
+class QXAMediaStreamsControl;
+
+class QXAPlayMediaService : public QMediaService
+{
+ Q_OBJECT
+public:
+ QXAPlayMediaService(QObject *parent = 0);
+ ~QXAPlayMediaService();
+ QMediaControl *requestControl(const char *name);
+ void releaseControl( QMediaControl *control);
+private:
+ QXAPlaySession *mSession;
+ QXAMediaPlayerControl *mMediaPlayerControl;
+ QXAVideoWidgetControl *mVideowidgetControl;
+ QXAVideoWindowControl *mVideoWindowControl;
+ QXAMetaDataControl *mMetaDataControl;
+ QXAMediaStreamsControl *mMediaStreamsControl;
+};
+
+#endif /* QXAPLAYMEDIASERVICE_H */
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxaplaysession.cpp b/src/plugins/symbian/openmaxal/mediaplayer/qxaplaysession.cpp
new file mode 100644
index 000000000..2254a9363
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxaplaysession.cpp
@@ -0,0 +1,610 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QMetaType>
+#include "qxaplaysession.h"
+#include "xaplaysessionimpl.h"
+#include "qxacommon.h"
+#include <COECNTRL.H>
+
+QXAPlaySession::QXAPlaySession(QObject *parent):QObject(parent),
+m_state(QMediaPlayer::StoppedState),
+m_mediaStatus(QMediaPlayer::NoMedia),
+mSeekable(-1),
+mNumStreams(0),
+mbAudioAvailable(EFalse),
+mbVideoAvailable(EFalse),
+mImpl(NULL),
+mVideowidgetControl(NULL),
+mWidgetCtrlWindow(NULL),
+mWidgetCtrlWindowId(NULL),
+mVideoWindowControl(NULL),
+mWindowCtrlWindow(NULL),
+mWindowCtrlWindowId(NULL),
+mWsSession(&(CCoeEnv::Static()->WsSession()))
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ mImpl = new XAPlaySessionImpl(*this);
+
+ if (mImpl && (mImpl->postConstruct() != KErrNone)) {
+ delete mImpl;
+ mImpl = NULL;
+ QT_TRACE1("Error initializing implementation");
+ }
+
+ if (!mImpl)
+ emit error(QMediaPlayer::ResourceError, tr("Service has not been started"));
+
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+QXAPlaySession::~QXAPlaySession()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ delete mImpl;
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXAPlaySession::setVideoWidgetControl( QXAVideoWidgetControl * videoWidgetControl )
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ if (mVideowidgetControl) {
+ disconnect(mVideowidgetControl, SIGNAL(widgetUpdated()),
+ this, SLOT(videoWidgetControlWidgetUpdated()));
+ RWindow* window = static_cast<RWindow*>(mVideowidgetControl->videoWidgetWId()->DrawableWindow());
+ mImpl->removeNativeDisplay(window, mWsSession);
+ }
+ mVideowidgetControl = videoWidgetControl;
+ if (mVideowidgetControl)
+ connect(mVideowidgetControl, SIGNAL(widgetUpdated()),
+ this, SLOT(videoWidgetControlWidgetUpdated()));
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXAPlaySession::unsetVideoWidgetControl( QXAVideoWidgetControl * videoWidgetControl )
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ if ((mVideowidgetControl == videoWidgetControl) && (mImpl)) {
+ disconnect(mVideowidgetControl, SIGNAL(widgetUpdated()),
+ this, SLOT(videoWidgetControlWidgetUpdated()));
+ RWindow* window = static_cast<RWindow*>(mVideowidgetControl->videoWidgetWId()->DrawableWindow());
+ mImpl->removeNativeDisplay(window, mWsSession);
+ }
+ mVideowidgetControl = NULL;
+ mWidgetCtrlWindow = NULL;
+ mWidgetCtrlWindowId = NULL;
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXAPlaySession::setVideoWindowControl( QXAVideoWindowControl * videoWindowControl )
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ if (mVideoWindowControl) {
+ disconnect(mVideoWindowControl, SIGNAL(windowUpdated()),
+ this, SLOT(videoWindowControlWindowUpdated()));
+ RWindow* window = static_cast<RWindow*>(mVideoWindowControl->winId()->DrawableWindow());
+ mImpl->removeNativeDisplay(window, mWsSession);
+ }
+ mVideoWindowControl = videoWindowControl;
+ if (mVideoWindowControl) {
+ connect(mVideoWindowControl, SIGNAL(windowUpdated()),
+ this, SLOT(videoWindowControlWindowUpdated()));
+ videoWindowControlWindowUpdated();
+ }
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXAPlaySession::unsetVideoWindowControl( QXAVideoWindowControl * videoWindowControl )
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ if ((mVideoWindowControl == videoWindowControl) && (mImpl)) {
+ disconnect(mVideoWindowControl, SIGNAL(windowUpdated()),
+ this, SLOT(videoWindowControlWindowUpdated()));
+ RWindow* window = static_cast<RWindow*>(mVideoWindowControl->winId()->DrawableWindow());
+ mImpl->removeNativeDisplay(window, mWsSession);
+ }
+ mVideoWindowControl = NULL;
+ mWindowCtrlWindow = NULL;
+ mWindowCtrlWindowId = NULL;
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+qint64 QXAPlaySession::duration()
+{
+ TInt64 dur(0);
+ if (mImpl)
+ mImpl->duration(dur);
+
+ return (qint64)dur;
+}
+
+qint64 QXAPlaySession::position()
+{
+ TInt64 pos(0);
+ if (mImpl)
+ mImpl->position(pos);
+
+ return (qint64)pos;
+}
+
+void QXAPlaySession::setPosition(qint64 ms)
+{
+ if (mImpl) {
+ qint64 currPos = position();
+ mImpl->seek(ms);
+
+ if(currPos != position()) {
+ emit positionChanged(position());
+
+ if(position()>=duration()) {
+ setMediaStatus(QMediaPlayer::EndOfMedia);
+ stop();
+ }
+ }
+ }
+}
+
+int QXAPlaySession::volume()
+{
+ if(mImpl) {
+ TInt v(0);
+
+ TInt err = mImpl->volume(v);
+ if(KErrNone == err)
+ return v;
+ }
+
+ return 50;
+}
+
+void QXAPlaySession::setVolume(int v)
+{
+ if(mImpl) {
+ if(v != volume()) {
+ TInt err = mImpl->setVolume(v);
+ if(KErrNone == err)
+ emit volumeChanged(volume());
+ }
+ }
+}
+
+
+bool QXAPlaySession::isMuted()
+{
+ if(mImpl) {
+ TBool bCurrMute = EFalse;
+ TInt err = mImpl->getMute(bCurrMute);
+ if(err == KErrNone)
+ return bCurrMute;
+ }
+
+ return EFalse;
+}
+
+void QXAPlaySession::setMuted(bool muted)
+{
+ if(muted != isMuted())
+ {
+ if(mImpl)
+ {
+ TInt err = mImpl->setMute(muted);
+
+ if(KErrNone == err)
+ {
+ emit mutedChanged(muted);
+ }
+ }
+ }
+}
+
+int QXAPlaySession::bufferStatus()
+{
+ if(mImpl) {
+ TInt fillLevel = 0;
+ TInt err = mImpl->bufferStatus(fillLevel);
+ if(err == KErrNone)
+ return fillLevel;
+ }
+
+ return 100;//default
+}
+
+bool QXAPlaySession::isAudioAvailable()
+{
+ return mbAudioAvailable;
+}
+
+bool QXAPlaySession::isVideoAvailable()
+{
+ return mbVideoAvailable;
+}
+
+bool QXAPlaySession::isSeekable()
+{
+ return ((mSeekable==1) || (mSeekable==-1));//default seekable
+}
+
+float QXAPlaySession::playbackRate()
+{
+ if(mImpl) {
+ TReal32 currPBRate = 0.0;
+ TInt ret = mImpl->getPlaybackRate(currPBRate);
+ if(ret == KErrNone)
+ return currPBRate;
+ }
+
+ return 1.0;
+}
+
+void QXAPlaySession::setPlaybackRate(float rate)
+{
+ if(mImpl) {
+ TReal32 currPBRate = 0.0;
+ TInt ret = mImpl->getPlaybackRate(currPBRate);
+ if( (ret == KErrNone) &&
+ (rate!=currPBRate)) {
+ ret = mImpl->setPlaybackRate(rate);
+ if(ret == KErrNone)
+ emit playbackRateChanged(rate);
+ }
+ }
+}
+
+QMediaContent QXAPlaySession::media()
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return mMediaContent;
+}
+
+void QXAPlaySession::setMedia(const QMediaContent& media)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_IF_p_IS_NULL_EMIT_PLAYER_RESOURCE_ERROR(mImpl);
+
+ if (media.isNull() ||
+ mMediaContent == media) {
+ return;
+ }
+
+ setMediaStatus(QMediaPlayer::NoMedia);
+
+ QString urlStr = media.canonicalUrl().toString();
+ TPtrC16 urlPtr(reinterpret_cast<const TUint16*>(urlStr.utf16()));
+
+ setMediaStatus(QMediaPlayer::LoadingMedia);
+ if (mImpl->load(urlPtr) == 0) {
+ setMediaStatus(QMediaPlayer::LoadedMedia);
+ emit error(QMediaPlayer::NoError, "");
+ mMediaContent = media;
+ setPlayerState(QMediaPlayer::StoppedState);
+ emit mediaChanged(mMediaContent);
+
+ if(mImpl->isMetaDataAvailable()) {
+ emit metaDataAvailableChanged(true);
+ emit metaDataChanged();
+ }
+ else {
+ emit metaDataAvailableChanged(false);
+ }
+ }
+ else {
+ setMediaStatus(QMediaPlayer::NoMedia);
+ emit error(QMediaPlayer::ResourceError, tr("Unable to load media"));
+ }
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXAPlaySession::play()
+{
+ if (mImpl) {
+ setMediaStatus(QMediaPlayer::BufferingMedia);
+
+ TInt err = mImpl->play();
+ if (err != KErrNone) {
+ setMediaStatus(QMediaPlayer::NoMedia);
+ RET_IF_ERROR(err);
+ }
+ setPlayerState(QMediaPlayer::PlayingState);
+
+ TInt fillLevel = 0;
+ err = mImpl->bufferStatus(fillLevel);
+ RET_IF_ERROR(err);
+ if (fillLevel == 100) {
+ setMediaStatus(QMediaPlayer::BufferedMedia);
+ }
+ }
+}
+
+void QXAPlaySession::pause()
+{
+ if (mImpl) {
+ TInt err = mImpl->pause();
+ RET_IF_ERROR(err);
+ setPlayerState(QMediaPlayer::PausedState);
+ }
+}
+
+void QXAPlaySession::stop()
+{
+ if (mImpl) {
+ TInt err = mImpl->stop();
+ RET_IF_ERROR(err);
+ setPlayerState(QMediaPlayer::StoppedState);
+ }
+}
+
+void QXAPlaySession::cbDurationChanged(TInt64 new_dur)
+{
+ emit durationChanged((qint64)new_dur);
+}
+
+void QXAPlaySession::cbPositionChanged(TInt64 new_pos)
+{
+ emit positionChanged((qint64)new_pos);
+}
+
+void QXAPlaySession::cbSeekableChanged(TBool seekable)
+{
+ if( (mSeekable==-1) ||
+ (seekable != (TBool)mSeekable)) {
+ mSeekable = seekable?1:0;
+ emit seekableChanged((bool)seekable);
+ }
+}
+
+void QXAPlaySession::cbPlaybackStopped(TInt err)
+{
+ if (err) {
+ emit error(QMediaPlayer::ResourceError, tr("Resources Unavailable"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaPlayer::ResourceError, tr(\"Resources Unavailable\"))");
+ emit positionChanged(position());
+ setPlayerState(QMediaPlayer::StoppedState);
+ setMediaStatus(QMediaPlayer::NoMedia);
+ }
+ else {
+ setMediaStatus(QMediaPlayer::EndOfMedia);
+ /* Set player state to Stopped */
+ stop();
+ }
+}
+
+void QXAPlaySession::cbPrefetchStatusChanged()
+{
+ if(mImpl) {
+ TInt fillLevel = 0;
+ TInt err = mImpl->bufferStatus(fillLevel);
+ if(err == KErrNone) {
+ emit bufferStatusChanged(fillLevel);
+
+ if(fillLevel == 100)
+ setMediaStatus(QMediaPlayer::BufferedMedia);
+ else if(fillLevel ==0)
+ setMediaStatus(QMediaPlayer::StalledMedia);
+ }
+ }
+}
+
+void QXAPlaySession::cbStreamInformation(TBool bFirstTime)
+{
+ updateStreamInfo(bFirstTime);
+}
+
+
+
+void QXAPlaySession::videoWidgetControlWidgetUpdated()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ if (mVideowidgetControl) {
+ WId newId = mVideowidgetControl->videoWidgetWId();
+ if ((newId != NULL) && (newId != mWidgetCtrlWindowId)) {
+ mWidgetCtrlWindow = static_cast<RWindow*>(newId->DrawableWindow());
+ if (mWidgetCtrlWindowId == NULL)
+ mImpl->addNativeDisplay(mWidgetCtrlWindow, mWsSession);
+ else
+ mImpl->updateNativeDisplay(mWidgetCtrlWindow, mWsSession);
+ mWidgetCtrlWindowId = newId;
+ }
+ }
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXAPlaySession::videoWindowControlWindowUpdated()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ if (mVideoWindowControl) {
+ WId newId = mVideoWindowControl->winId();
+ if ((newId != NULL) && (newId != mWindowCtrlWindowId)) {
+ mWidgetCtrlWindow = static_cast<RWindow*>(newId->DrawableWindow());
+ if (mWindowCtrlWindowId == NULL)
+ mImpl->addNativeDisplay(mWidgetCtrlWindow, mWsSession);
+ else
+ mImpl->updateNativeDisplay(mWidgetCtrlWindow, mWsSession);
+ mWindowCtrlWindowId = newId;
+ }
+ }
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXAPlaySession::setMediaStatus(QMediaPlayer::MediaStatus status)
+{
+ if (m_mediaStatus != status) {
+ m_mediaStatus = status;
+ emit mediaStatusChanged(status);
+ }
+}
+
+void QXAPlaySession::setPlayerState(QMediaPlayer::State state)
+{
+ if (m_state != state) {
+ m_state = state;
+ emit stateChanged(m_state);
+ }
+}
+
+QStringList QXAPlaySession::availableExtendedMetaData () const
+{
+ QStringList list;
+ RET_s_IF_p_IS_NULL(mImpl, list);
+ list = mImpl->availableExtendedMetaData();
+ return list;
+}
+
+QList<QtMultimediaKit::MetaData> QXAPlaySession::availableMetaData () const
+{
+ QList<QtMultimediaKit::MetaData> list;
+ RET_s_IF_p_IS_NULL(mImpl, list);
+ return mImpl->availableMetaData();
+}
+
+QVariant QXAPlaySession::extendedMetaData(const QString & key ) const
+{
+ QVariant var;
+ RET_s_IF_p_IS_NULL(mImpl, var);
+ return mImpl->extendedMetaData(key);
+}
+
+bool QXAPlaySession::isMetaDataAvailable() const
+{
+ RET_s_IF_p_IS_NULL(mImpl, false);
+ return mImpl->isMetaDataAvailable();
+}
+
+bool QXAPlaySession::isWritable() const
+{
+ RET_s_IF_p_IS_NULL(mImpl, false);
+ return mImpl->isWritable();
+}
+
+QVariant QXAPlaySession::metaData( QtMultimediaKit::MetaData key ) const
+{
+ QVariant var;
+ RET_s_IF_p_IS_NULL(mImpl, var);
+ return mImpl->metaData(key);
+}
+
+void QXAPlaySession::setExtendedMetaData( const QString & key, const QVariant & value )
+{
+ RET_IF_p_IS_NULL(mImpl);
+ mImpl->setExtendedMetaData(key, value);
+}
+
+void QXAPlaySession::setMetaData( QtMultimediaKit::MetaData key, const QVariant & value )
+{
+ RET_IF_p_IS_NULL(mImpl);
+ mImpl->setMetaData(key, value);
+}
+
+void QXAPlaySession::updateStreamInfo(TBool emitSignal)
+{
+ if(mImpl) {
+ mNumStreams = 0;
+ TInt ret = mImpl->numMediaStreams(mNumStreams);
+ if(ret == KErrNone) {
+ TBool bAudioAvailable = EFalse;//lcoal variable
+ TBool bVideoAvailable = EFalse;//lcvoal variable
+
+ for(TUint i = 0; i < mNumStreams; i++) {
+ QMediaStreamsControl::StreamType strType;
+ mImpl->streamType(i, strType);
+ if(strType == QMediaStreamsControl::AudioStream)
+ bAudioAvailable = ETrue;
+ else if(strType == QMediaStreamsControl::VideoStream)
+ bVideoAvailable = ETrue;
+ }
+
+ if(emitSignal || (bAudioAvailable != mbAudioAvailable)) {
+ emit audioAvailableChanged(bAudioAvailable);
+ mbAudioAvailable = bAudioAvailable;
+ }
+
+ if(emitSignal || (bVideoAvailable != mbVideoAvailable)) {
+ emit videoAvailableChanged(bVideoAvailable);
+ mbVideoAvailable = bVideoAvailable;
+ }
+
+ emit streamsChanged();
+ }
+ }
+}
+
+bool QXAPlaySession::isStreamActive ( int stream )
+{
+ RET_s_IF_p_IS_NULL(mImpl, false);
+ TBool isActive = EFalse;
+ mImpl->isStreamActive(stream,isActive);
+ return isActive;
+}
+
+QVariant QXAPlaySession::metaData ( int /*stream*/, QtMultimediaKit::MetaData key )
+{
+ return this->metaData(key);
+}
+
+int QXAPlaySession::streamCount()
+{
+ return mNumStreams;
+}
+
+QMediaStreamsControl::StreamType QXAPlaySession::streamType ( int stream )
+{
+ QMediaStreamsControl::StreamType strType = QMediaStreamsControl::UnknownStream;
+ RET_s_IF_p_IS_NULL(mImpl, strType);
+ if(mImpl->streamType(stream, strType) == KErrNone) {
+ return strType;
+ }
+
+ return QMediaStreamsControl::UnknownStream;
+}
+
+////AspectRatioMode
+void QXAPlaySession::setAspectRatioMode(Qt::AspectRatioMode aspectRatioMode)
+{
+ RET_IF_p_IS_NULL(mImpl);
+ mImpl->setAspectRatioMode(aspectRatioMode);
+}
+
+Qt::AspectRatioMode QXAPlaySession::getAspectRatioMode()
+{
+ RET_s_IF_p_IS_NULL(mImpl, Qt::KeepAspectRatio);
+ return mImpl->getAspectRatioMode();
+}
+
+
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxaplaysession.h b/src/plugins/symbian/openmaxal/mediaplayer/qxaplaysession.h
new file mode 100644
index 000000000..0d366518f
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxaplaysession.h
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** 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$
+** 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 QXAPLAYSESSION_H
+#define QXAPLAYSESSION_H
+
+#include <QObject>
+#include <QUrl>
+#include <qtmedianamespace.h>
+
+#include "qxamediaplayercontrol.h"
+#include "qxametadatacontrol.h"
+#include "qmediaplayer.h"
+#include "xaplaysessioncommon.h"
+#include "qxavideowidgetcontrol.h"
+#include "qxavideowindowcontrol.h"
+#include "qmediastreamscontrol.h"
+
+
+QT_USE_NAMESPACE
+
+class XAPlaySessionImpl;
+class RWindow;
+class RWsSession;
+class QXAVideoWidgetControl;
+
+class QXAPlaySession : public QObject,
+ public XAPlayObserver
+{
+ Q_OBJECT
+public:
+ QXAPlaySession(QObject *parent);
+ virtual ~QXAPlaySession();
+
+ void setVideoWidgetControl( QXAVideoWidgetControl * videoWidgetControl );
+ void unsetVideoWidgetControl( QXAVideoWidgetControl * videoWidgetControl );
+ void setVideoWindowControl( QXAVideoWindowControl * videoWindowControl );
+ void unsetVideoWindowControl( QXAVideoWindowControl * videoWindowControl );
+
+ //QXAMediaPlayerControl
+ QMediaPlayer::State state() const { return m_state; }
+ QMediaPlayer::MediaStatus mediaStatus() const { return m_mediaStatus; }
+ qint64 duration();
+ qint64 position();
+ void setPosition(qint64 position);
+ int volume();
+ void setVolume(int volume);
+ bool isMuted();
+ void setMuted(bool muted);
+ int bufferStatus();
+ bool isAudioAvailable();
+ bool isVideoAvailable();
+ bool isSeekable();
+ float playbackRate();
+ void setPlaybackRate(float rate);
+ QMediaContent media();
+ void setMedia(const QMediaContent& media);
+ void play();
+ void pause();
+ void stop();
+
+ // Callback from XAPlaySessionImpl
+ void cbDurationChanged(TInt64 new_dur);
+ void cbPositionChanged(TInt64 new_pos);
+ void cbSeekableChanged(TBool seekable);
+ void cbPlaybackStopped(TInt error);
+ void cbPrefetchStatusChanged();
+ void cbStreamInformation(TBool);
+
+ //MetadataControl methods
+ QStringList availableExtendedMetaData () const;
+ QList<QtMultimediaKit::MetaData> availableMetaData () const;
+ QVariant extendedMetaData(const QString & key ) const;
+ bool isMetaDataAvailable() const;
+ bool isWritable() const;
+ QVariant metaData( QtMultimediaKit::MetaData key ) const;
+ void setExtendedMetaData( const QString & key, const QVariant & value );
+ void setMetaData( QtMultimediaKit::MetaData key, const QVariant & value );
+
+ //QMediaStreamsControl
+ bool isStreamActive ( int stream ) ;
+ QVariant metaData ( int stream, QtMultimediaKit::MetaData key );
+ int streamCount();
+ QMediaStreamsControl::StreamType streamType ( int stream );
+
+ //QVideoWidgetControl
+ void setAspectRatioMode(Qt::AspectRatioMode);
+ Qt::AspectRatioMode getAspectRatioMode();
+
+public Q_SLOTS:
+ void videoWidgetControlWidgetUpdated();
+ void videoWindowControlWindowUpdated();
+
+Q_SIGNALS:
+ void mediaChanged(const QMediaContent& content);
+ void durationChanged(qint64 duration);
+ void positionChanged(qint64 position);
+ void stateChanged(QMediaPlayer::State newState);
+ void mediaStatusChanged(QMediaPlayer::MediaStatus status);
+ void volumeChanged(int volume);
+ void mutedChanged(bool muted);
+ void audioAvailableChanged(bool audioAvailable);
+ void videoAvailableChanged(bool videoAvailable);
+ void bufferStatusChanged(int percentFilled);
+ void seekableChanged(bool);
+ void availablePlaybackRangesChanged(const QMediaTimeRange&);
+ void error(int errorCode, const QString &errorString);
+ void playbackRateChanged(qreal rate);
+
+ //metadata
+ void metaDataAvailableChanged(bool);
+ void metaDataChanged();
+ void writableChanged(bool);
+
+ //QMediaStreamsControl
+ void streamsChanged();
+ void activeStreamsChanged();
+
+private:
+ void setMediaStatus(QMediaPlayer::MediaStatus);
+ void setPlayerState(QMediaPlayer::State state);
+ void updateStreamInfo(TBool emitSignal = EFalse);
+
+private:
+ QMediaPlayer::State m_state;
+ QMediaPlayer::MediaStatus m_mediaStatus;
+
+ QMap<QString,QVariant> m_tags;
+ QList< QMap<QString,QVariant> > m_streamProperties;
+
+ //seekable
+ int mSeekable; //-1 =unintialized, 0=nonseekable, 1=seekable
+
+ //StreamInfo
+ TUint mNumStreams;
+ TBool mbAudioAvailable;
+ TBool mbVideoAvailable;
+
+ //Own
+ XAPlaySessionImpl* mImpl;
+
+ // Does not own
+ QXAVideoWidgetControl *mVideowidgetControl;
+ RWindow *mWidgetCtrlWindow;
+ WId mWidgetCtrlWindowId;
+ QXAVideoWindowControl *mVideoWindowControl;
+ RWindow *mWindowCtrlWindow;
+ WId mWindowCtrlWindowId;
+ RWsSession *mWsSession;
+
+ QMediaContent mMediaContent;
+};
+
+#endif /* QXAPLAYSESSION_H */
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxavideowidgetcontrol.cpp b/src/plugins/symbian/openmaxal/mediaplayer/qxavideowidgetcontrol.cpp
new file mode 100644
index 000000000..6e9c833fd
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxavideowidgetcontrol.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qxavideowidgetcontrol.h"
+#include "qxacommon.h"
+#include "qxawidget.h"
+#include <QEvent>
+
+QXAVideoWidgetControl::QXAVideoWidgetControl(QXAPlaySession *session, QObject *parent)
+ : QVideoWidgetControl(parent), mSession(session)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ mWidget = new QXAWidget;
+ if (mWidget)
+ mWidget->installEventFilter(this);
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+QXAVideoWidgetControl::~QXAVideoWidgetControl()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ delete mWidget;
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+QWidget* QXAVideoWidgetControl::videoWidget()
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return mWidget;
+}
+
+Qt::AspectRatioMode QXAVideoWidgetControl::aspectRatioMode() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_s_IF_p_IS_NULL(mSession, Qt::IgnoreAspectRatio);
+ QT_TRACE_FUNCTION_EXIT;
+ return mSession->getAspectRatioMode();
+}
+
+void QXAVideoWidgetControl::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_IF_p_IS_NULL(mSession);
+ mSession->setAspectRatioMode(mode);
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+bool QXAVideoWidgetControl::isFullScreen() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ bool retVal = false;
+ RET_s_IF_p_IS_NULL(mWidget, retVal);
+ retVal = mWidget->isFullScreen();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+void QXAVideoWidgetControl::setFullScreen(bool fullScreen)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_IF_p_IS_NULL(mWidget);
+ if (fullScreen == mWidget->isFullScreen())
+ return;
+ else if (fullScreen)
+ mWidget->showFullScreen();
+ else
+ mWidget->showNormal();
+
+ emit fullScreenChanged(fullScreen);
+
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+int QXAVideoWidgetControl::brightness() const
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return 0;
+}
+
+void QXAVideoWidgetControl::setBrightness(int brightness)
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ Q_UNUSED(brightness);
+}
+
+int QXAVideoWidgetControl::contrast() const
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return 0;
+}
+
+void QXAVideoWidgetControl::setContrast(int contrast)
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ Q_UNUSED(contrast);
+}
+
+int QXAVideoWidgetControl::hue() const
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return 0;
+}
+
+void QXAVideoWidgetControl::setHue(int hue)
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ Q_UNUSED(hue);
+}
+
+int QXAVideoWidgetControl::saturation() const
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return 0;
+}
+
+void QXAVideoWidgetControl::setSaturation(int saturation)
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ Q_UNUSED(saturation);
+}
+
+bool QXAVideoWidgetControl::eventFilter(QObject *object, QEvent *event)
+{
+ if (object == mWidget) {
+ if ( event->type() == QEvent::Resize
+ || event->type() == QEvent::Move
+ || event->type() == QEvent::WinIdChange
+ || event->type() == QEvent::ParentChange
+ || event->type() == QEvent::Show) {
+ emit widgetUpdated();
+ }
+ }
+ return false;
+}
+
+WId QXAVideoWidgetControl::videoWidgetWId()
+{
+ if (mWidget->internalWinId())
+ return mWidget->internalWinId();
+ else if (mWidget->effectiveWinId())
+ return mWidget->effectiveWinId();
+
+ return NULL;
+}
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxavideowidgetcontrol.h b/src/plugins/symbian/openmaxal/mediaplayer/qxavideowidgetcontrol.h
new file mode 100644
index 000000000..7a0eda765
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxavideowidgetcontrol.h
@@ -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$
+** 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 QXAVIDEOWIDGETCONTROL_H
+#define QXAVIDEOWIDGETCONTROL_H
+
+#include <QObject>
+#include <qvideowidgetcontrol.h>
+#include "qxaplaysession.h"
+
+QT_USE_NAMESPACE
+
+class QXAWidget;
+
+class QXAVideoWidgetControl : public QVideoWidgetControl
+{
+ Q_OBJECT
+public:
+ QXAVideoWidgetControl(QXAPlaySession *session, QObject *parent = 0);
+ ~QXAVideoWidgetControl();
+
+ QWidget *videoWidget();
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ bool isFullScreen() const;
+ void setFullScreen(bool fullScreen);
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ bool eventFilter(QObject *object, QEvent *event);
+
+ WId videoWidgetWId();
+
+Q_SIGNALS:
+ void widgetUpdated();
+
+private:
+ QXAPlaySession *mSession;
+ QXAWidget *mWidget;
+
+};
+
+#endif // QXAVIDEOWIDGETCONTROL_H
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxavideowindowcontrol.cpp b/src/plugins/symbian/openmaxal/mediaplayer/qxavideowindowcontrol.cpp
new file mode 100644
index 000000000..c19b949ac
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxavideowindowcontrol.cpp
@@ -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$
+** 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 "qxavideowindowcontrol.h"
+#include "qxacommon.h"
+#include <QEvent>
+#include "qxaplaysession.h"
+
+QXAVideoWindowControl::QXAVideoWindowControl(QXAPlaySession* session, QObject *parent)
+ :QVideoWindowControl(parent),
+ mWid(NULL),
+ mWidget(NULL),
+ mAspectRatioMode(Qt::IgnoreAspectRatio),
+ mSession(session)
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+}
+
+QXAVideoWindowControl::~QXAVideoWindowControl()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ if (mWidget)
+ mWidget->removeEventFilter(this);
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+WId QXAVideoWindowControl::winId() const
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return mWid;
+}
+
+void QXAVideoWindowControl::setWinId(WId id)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ if (mWid != id) {
+ if (mWidget)
+ mWidget->removeEventFilter(this);
+ mWid = id;
+ mWidget = QWidget::find(mWid);
+ if (mWidget)
+ mWidget->installEventFilter(this);
+ emit windowUpdated();
+ }
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+QRect QXAVideoWindowControl::displayRect() const
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return mDisplayRect;
+}
+
+void QXAVideoWindowControl::setDisplayRect(const QRect &rect)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ mDisplayRect = rect;
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+bool QXAVideoWindowControl::isFullScreen() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ bool retVal(false);
+ if (mWidget)
+ retVal = mWidget->isFullScreen();
+ QT_TRACE_FUNCTION_EXIT;
+ return retVal;
+}
+
+void QXAVideoWindowControl::setFullScreen(bool fullScreen)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ if (mWidget && (fullScreen != mWidget->isFullScreen())) {
+ if (fullScreen)
+ mWidget->showFullScreen();
+ else
+ mWidget->showNormal();
+ emit fullScreenChanged(fullScreen);
+ }
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXAVideoWindowControl::repaint()
+{
+}
+
+QSize QXAVideoWindowControl::nativeSize() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ QSize size(0, 0);
+ RET_s_IF_p_IS_NULL(mSession, size);
+ QVariant sizeBundle = mSession->metaData(QtMultimediaKit::Resolution);
+ QString metadata = sizeBundle.toString();
+ if (!metadata.isNull() && !metadata.isEmpty()) {
+ int xIndex = metadata.indexOf('x');
+ if (xIndex > 0) {
+ size.setWidth(metadata.left(xIndex).toInt());
+ xIndex = metadata.length() - (xIndex + 1);
+ if (xIndex > 0)
+ size.setHeight(metadata.right(xIndex).toInt());
+ }
+ }
+ QT_TRACE_FUNCTION_EXIT;
+ return size;
+}
+
+Qt::AspectRatioMode QXAVideoWindowControl::aspectRatioMode() const
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_s_IF_p_IS_NULL(mSession, Qt::IgnoreAspectRatio);
+ QT_TRACE_FUNCTION_EXIT;
+ return mSession->getAspectRatioMode();
+}
+
+void QXAVideoWindowControl::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ RET_IF_p_IS_NULL(mSession);
+ mSession->setAspectRatioMode(mode);
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+int QXAVideoWindowControl::brightness() const
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return 0;
+}
+
+void QXAVideoWindowControl::setBrightness(int brightness)
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ Q_UNUSED(brightness);
+}
+
+int QXAVideoWindowControl::contrast() const
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return 0;
+}
+
+void QXAVideoWindowControl::setContrast(int contrast)
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ Q_UNUSED(contrast);
+}
+
+int QXAVideoWindowControl::hue() const
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return 0;
+}
+
+void QXAVideoWindowControl::setHue(int hue)
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ Q_UNUSED(hue);
+}
+
+int QXAVideoWindowControl::saturation() const
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ return 0;
+}
+
+void QXAVideoWindowControl::setSaturation(int saturation)
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+ Q_UNUSED(saturation);
+}
+
+bool QXAVideoWindowControl::eventFilter(QObject *object, QEvent *event)
+{
+ if (object == mWidget) {
+ if (event->type() == QEvent::Resize
+ || event->type() == QEvent::Move
+ || event->type() == QEvent::WinIdChange
+ || event->type() == QEvent::ParentChange
+ || event->type() == QEvent::Show) {
+ emit windowUpdated();
+ }
+ }
+ return false;
+}
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxavideowindowcontrol.h b/src/plugins/symbian/openmaxal/mediaplayer/qxavideowindowcontrol.h
new file mode 100644
index 000000000..879349822
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxavideowindowcontrol.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** 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$
+** 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 QXAVIDEOWINDOWCONTROL_H
+#define QXAVIDEOWINDOWCONTROL_H
+
+#include <QObject>
+#include <QVideoWindowControl>
+
+QT_USE_NAMESPACE
+
+class QXAPlaySession;
+
+class QXAVideoWindowControl : public QVideoWindowControl
+{
+ Q_OBJECT
+
+public:
+ QXAVideoWindowControl(QXAPlaySession* session, QObject *parent = 0);
+ ~QXAVideoWindowControl();
+
+ // QVideoWindowControl virtual functions
+ WId winId() const;
+ void setWinId(WId id);
+
+ QRect displayRect() const;
+ void setDisplayRect(const QRect &rect);
+
+ bool isFullScreen() const;
+ void setFullScreen(bool fullScreen);
+
+ void repaint();
+
+ QSize nativeSize() const;
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ //Callback function to receive event from Qt framework
+ //for object represented by mWid
+ bool eventFilter(QObject *object, QEvent *event);
+
+Q_SIGNALS:
+ void windowUpdated();
+
+private:
+ WId mWid;
+ QWidget* mWidget; /* QWidget represented by mWid */
+ QRect mDisplayRect;
+ Qt::AspectRatioMode mAspectRatioMode;
+
+ QXAPlaySession* mSession;
+};
+
+#endif /* QXAVIDEOWINDOWCONTROL_H */
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxawidget.cpp b/src/plugins/symbian/openmaxal/mediaplayer/qxawidget.cpp
new file mode 100644
index 000000000..4685226fd
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxawidget.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qxawidget.h"
+#include <coemain.h>
+
+QXAWidget::QXAWidget(QWidget *parent)
+ : QWidget(parent)
+{
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ setAttribute(Qt::WA_OpaquePaintEvent, true);
+ setAttribute(Qt::WA_NoSystemBackground, true);
+ setAutoFillBackground(false);
+ setPalette(QPalette(Qt::black));
+ /* Initialize the native window*/
+ winId();
+}
+
+QXAWidget::~QXAWidget()
+{
+}
+
+void QXAWidget::paintEvent(QPaintEvent *event)
+{
+ Q_UNUSED(event);
+}
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/qxawidget.h b/src/plugins/symbian/openmaxal/mediaplayer/qxawidget.h
new file mode 100644
index 000000000..d36be1fa4
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/qxawidget.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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$
+** 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 QXAWIDGET_H
+#define QXAWIDGET_H
+
+#include <QObject>
+#include <qwidget.h>
+
+QT_USE_NAMESPACE
+
+class QXAWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ QXAWidget(QWidget *parent = 0);
+ virtual ~QXAWidget();
+
+protected:
+ void paintEvent(QPaintEvent *event);
+};
+
+
+#endif /* QXAWIDGET_H */
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/xaplaysessioncommon.h b/src/plugins/symbian/openmaxal/mediaplayer/xaplaysessioncommon.h
new file mode 100644
index 000000000..a9497e475
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/xaplaysessioncommon.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** 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$
+** 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 XAPLAYSESSIONCOMMON_H
+#define XAPLAYSESSIONCOMMON_H
+
+#include <e32base.h>
+
+class XAPlayObserver
+ {
+public:
+ virtual void cbDurationChanged(TInt64 new_dur) = 0;
+ virtual void cbPositionChanged(TInt64 new_pos) = 0;
+ virtual void cbSeekableChanged(TBool seekable) = 0;
+ virtual void cbPlaybackStopped(TInt error) = 0;
+ virtual void cbPrefetchStatusChanged() = 0;
+ virtual void cbStreamInformation(TBool bFirstTime) = 0;
+ };
+
+#endif /*XAPLAYSESSIONCOMMON_H*/
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/xaplaysessionimpl.cpp b/src/plugins/symbian/openmaxal/mediaplayer/xaplaysessionimpl.cpp
new file mode 100644
index 000000000..88a06807f
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/xaplaysessionimpl.cpp
@@ -0,0 +1,1259 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QString>
+#include <QVariant>
+#include <QList>
+#include <QStringList>
+#include <QImage>
+
+#include "xaplaysessionimpl.h"
+#include "xaplaysessioncommon.h"
+#include "xacommon.h"
+
+#ifdef USE_VIDEOPLAYERUTILITY
+#include <COECNTRL.H>
+#endif
+
+_LIT8(K8WAVMIMETYPE, "audio/wav");
+
+#define RET_ERR_IF_ERR(e) \
+ if (e != 0) {\
+ return e; \
+ } \
+
+#define MAX_NUMBER_INTERFACES 20
+const TUint KPlayPosUpdatePeriod = 1000;
+
+/* Local functions for callback registation */
+void MediaPlayerCallback( XAObjectItf caller,
+ const void *pContext,
+ XAuint32 event,
+ XAresult result,
+ XAuint32 param,
+ void *pInterface);
+
+void PlayItfCallback( XAPlayItf caller,
+ void *pContext,
+ XAuint32 event);
+
+void PrefetchItfCallback( XAPrefetchStatusItf caller,
+ void * pContext,
+ XAuint32 event);
+
+void StreamInformationItfCallback( XAStreamInformationItf caller,
+ XAuint32 eventId,
+ XAuint32 streamIndex,
+ void * pEventData,
+ void * pContext);
+
+XAPlaySessionImpl::XAPlaySessionImpl(XAPlayObserver& parent)
+:mParent(parent),
+mEOEngine(NULL),
+mMOPlayer(NULL),
+mPlayItf(NULL),
+mSeekItf(NULL),
+mURIName(NULL),
+mWAVMime(NULL),
+mbMetadataAvailable(EFalse),
+mbVolEnabled(EFalse),
+mbMuteEnabled(EFalse),
+mbPrefetchStatusChange(EFalse),
+mbStreamInfoAvailable(EFalse),
+mbPlaybackRateItfAvailable(EFalse),
+mbScalable(EFalse),
+mCurrAspectRatioMode(Qt::KeepAspectRatio)
+#ifdef USE_VIDEOPLAYERUTILITY
+, mVideoPlayUtil(NULL)
+, mActiveSchedulerWait(NULL)
+#endif
+{
+}
+
+XAPlaySessionImpl::~XAPlaySessionImpl()
+{
+ if (mMOPlayer)
+ (*mMOPlayer)->Destroy(mMOPlayer);
+
+ if (mEOEngine)
+ (*mEOEngine)->Destroy(mEOEngine);
+
+ delete mURIName;
+ delete mWAVMime;
+
+ //clear metadata datastructures
+ alKeyMap.clear();
+ keyMap.clear();
+ extendedKeyMap.clear();
+
+#ifdef USE_VIDEOPLAYERUTILITY
+ delete mVideoPlayUtil;
+ if (mActiveSchedulerWait && \
+ mActiveSchedulerWait->IsStarted()) {
+ mActiveSchedulerWait->AsyncStop();
+ }
+
+ delete mActiveSchedulerWait;
+#endif
+
+}
+
+TInt XAPlaySessionImpl::postConstruct()
+{
+ TInt retVal;
+ XAresult xaRes;
+ XAEngineOption engineOption[] = { (XAuint32) XA_ENGINEOPTION_THREADSAFE,
+ (XAuint32) XA_BOOLEAN_TRUE
+ };
+ XAEngineItf engineItf;
+
+ mNativeDisplay.locatorType = XA_DATALOCATOR_NATIVEDISPLAY;
+ mNativeDisplay.hWindow = NULL;
+ mNativeDisplay.hDisplay = NULL;
+ mVideoSink.pLocator = (void*)&mNativeDisplay;
+ mVideoSink.pFormat = NULL;
+
+ // Create and realize Engine object
+ xaRes = xaCreateEngine (&mEOEngine, 1, engineOption, 0, NULL, NULL);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+ xaRes = (*mEOEngine)->Realize(mEOEngine, XA_BOOLEAN_FALSE);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ // Create and realize Output Mix object to be used by player
+ xaRes = (*mEOEngine)->GetInterface(mEOEngine, XA_IID_ENGINE, (void**) &engineItf);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ TRAP(retVal, mWAVMime = HBufC8::NewL(K8WAVMIMETYPE().Length() + 1));
+ RET_ERR_IF_ERR(retVal);
+ TPtr8 ptr = mWAVMime->Des();
+ ptr = K8WAVMIMETYPE(); // copy uri name into local variable
+ ptr.PtrZ(); // append zero terminator to end of URI
+
+#ifdef USE_VIDEOPLAYERUTILITY
+ TRAP(retVal, mVideoPlayUtil =
+ CVideoPlayerUtility2::NewL( *this,
+ EMdaPriorityNormal,
+ EMdaPriorityPreferenceTimeAndQuality)
+ );
+ mActiveSchedulerWait = new CActiveSchedulerWait;
+#endif
+
+ return retVal;
+}
+
+TInt XAPlaySessionImpl::addNativeDisplay(RWindow* window, RWsSession* wssession)
+ {
+ TInt retVal(KErrNotReady);
+
+ if (!mMOPlayer && !mPlayItf) {
+ // window can only be set before player creation
+ mNativeDisplay.locatorType = XA_DATALOCATOR_NATIVEDISPLAY;
+ mNativeDisplay.hWindow = (void*)window;
+ mNativeDisplay.hDisplay = (void*)wssession;
+ retVal = KErrNone;
+ }
+ return retVal;
+}
+
+TInt XAPlaySessionImpl::updateNativeDisplay(RWindow* /*window*/, RWsSession* /*wssession*/)
+{
+ return KErrNone;
+}
+
+TInt XAPlaySessionImpl::removeNativeDisplay(RWindow* /*window*/, RWsSession* /*wssession*/)
+{
+ return KErrNone;
+}
+
+TInt XAPlaySessionImpl::load(const TDesC& aURI)
+{
+ TInt retVal;
+ XAresult xaRes;
+ XAEngineItf engineItf;
+ XADynamicSourceItf dynamicSourceItf;
+ XAboolean required[MAX_NUMBER_INTERFACES];
+ XAInterfaceID iidArray[MAX_NUMBER_INTERFACES];
+ XAuint32 noOfInterfaces = 0;
+ TInt i;
+
+ XAmillisecond dur(0);
+ TPtr8 uriPtr(0,0,0);
+ TPtr8 mimeTypePtr(0,0,0);
+
+#ifdef USE_VIDEOPLAYERUTILITY
+ TRAP(m_VPError, mVideoPlayUtil->OpenFileL(_L("C:\\data\\test.3gp")));
+ if (m_VPError)
+ return 0;
+
+ if(!mActiveSchedulerWait->IsStarted())
+ mActiveSchedulerWait->Start();
+
+ if (m_VPError)
+ return 0;
+
+ mVideoPlayUtil->Prepare();
+
+ if(!mActiveSchedulerWait->IsStarted())
+ mActiveSchedulerWait->Start();
+
+ return 0;
+#endif
+
+ delete mURIName;
+ mURIName = NULL;
+ TRAP(retVal, mURIName = HBufC8::NewL(aURI.Length()+1));
+ RET_ERR_IF_ERR(retVal);
+ uriPtr.Set(mURIName->Des());
+
+ // This has to be done here since we can not destroy the Player
+ // in the Resource Lost callback.
+ if (mbMediaPlayerUnrealized) {
+ if (mMOPlayer) {
+ (*mMOPlayer)->Destroy(mMOPlayer);
+ mMOPlayer = NULL;
+ }
+ }
+
+ //py uri name into local variable
+ //TODO fix copy issue from 16 bit to 8 bit
+ uriPtr.Copy(aURI);
+
+ //If media player object already exists, just switch source
+ //using dynamic source interface
+ if (mMOPlayer && mPlayItf) {
+ dynamicSourceItf = NULL;
+ xaRes = (*mMOPlayer)->GetInterface(mMOPlayer, XA_IID_DYNAMICSOURCE, &dynamicSourceItf);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ //Setup the data source
+ //TODO Hard coded locator type
+ mUri.locatorType = XA_DATALOCATOR_URI;
+
+ //append zero terminator to end of URI
+ mUri.URI = (XAchar*) uriPtr.PtrZ();
+
+ //TODO Hard coded locator type
+ mMime.containerType = XA_CONTAINERTYPE_WAV;
+
+ //TODO Hard coded locator type
+ mMime.formatType = XA_DATAFORMAT_MIME;
+ mimeTypePtr.Set(mWAVMime->Des());
+ mMime.mimeType = (XAchar*)mimeTypePtr.Ptr();
+ mDataSource.pFormat = (void*)&mMime;
+ mDataSource.pLocator = (void*)&mUri;
+
+ xaRes = (*dynamicSourceItf)->SetSource(dynamicSourceItf, &mDataSource);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+ }
+ else { // Create media player object
+
+ // Setup the data source
+ // TODO Hard coded locator type
+ mUri.locatorType = XA_DATALOCATOR_URI;
+
+ //append zero terminator to end of URI
+ mUri.URI = (XAchar*) uriPtr.PtrZ();
+
+ //TODO Hard coded locator type
+ mMime.containerType = XA_CONTAINERTYPE_WAV;
+
+ //TODO Hard coded locator type
+ mMime.formatType = XA_DATAFORMAT_MIME;
+ mimeTypePtr.Set(mWAVMime->Des());
+ mMime.mimeType = (XAchar*)mimeTypePtr.Ptr();
+ mDataSource.pFormat = (void*)&mMime;
+ mDataSource.pLocator = (void*)&mUri;
+
+ //Setup the audio data sink
+ mLocatorOutputDevice.locatorType = XA_DATALOCATOR_IODEVICE;
+ mLocatorOutputDevice.deviceType = 6;
+ mAudioSink.pLocator = (void*) &mLocatorOutputDevice;
+ mAudioSink.pFormat = NULL;
+
+ //Init arrays required[] and iidArray[]
+ for (i = 0; i < MAX_NUMBER_INTERFACES; i++) {
+ required[i] = XA_BOOLEAN_FALSE;
+ iidArray[i] = XA_IID_NULL;
+ }
+
+ noOfInterfaces = 0;
+ required[noOfInterfaces] = XA_BOOLEAN_FALSE;
+ iidArray[noOfInterfaces] = XA_IID_SEEK;
+ noOfInterfaces++;
+ required[noOfInterfaces] = XA_BOOLEAN_FALSE;
+ iidArray[noOfInterfaces] = XA_IID_DYNAMICSOURCE;
+ noOfInterfaces++;
+ required[noOfInterfaces] = XA_BOOLEAN_FALSE;
+ iidArray[noOfInterfaces] = XA_IID_METADATAEXTRACTION;
+ noOfInterfaces++;
+ required[noOfInterfaces] = XA_BOOLEAN_FALSE;
+ iidArray[noOfInterfaces] = XA_IID_NOKIALINEARVOLUME;
+ noOfInterfaces++;
+ required[noOfInterfaces] = XA_BOOLEAN_FALSE;
+ iidArray[noOfInterfaces] = XA_IID_NOKIAVOLUMEEXT;
+ noOfInterfaces++;
+ required[noOfInterfaces] = XA_BOOLEAN_FALSE;
+ iidArray[noOfInterfaces] = XA_IID_PREFETCHSTATUS;
+ noOfInterfaces++;
+ required[noOfInterfaces] = XA_BOOLEAN_FALSE;
+ iidArray[noOfInterfaces] = XA_IID_STREAMINFORMATION;
+ noOfInterfaces++;
+ required[noOfInterfaces] = XA_BOOLEAN_FALSE;
+ iidArray[noOfInterfaces] = XA_IID_PLAYBACKRATE;
+ noOfInterfaces++;
+ required[noOfInterfaces] = XA_BOOLEAN_FALSE;
+ iidArray[noOfInterfaces] = XA_IID_VIDEOPOSTPROCESSING;
+ noOfInterfaces++;
+
+ xaRes = (*mEOEngine)->GetInterface(mEOEngine, XA_IID_ENGINE, (void**) &engineItf);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ xaRes = (*engineItf)->CreateMediaPlayer(engineItf,
+ &mMOPlayer,
+ &mDataSource,
+ NULL,
+ &mAudioSink,
+ &mVideoSink,
+ NULL,
+ NULL,
+ noOfInterfaces,
+ iidArray,
+ required);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ xaRes = (*mMOPlayer)->Realize(mMOPlayer, XA_BOOLEAN_FALSE);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ mbMediaPlayerUnrealized = FALSE;
+
+ xaRes = (*mMOPlayer)->RegisterCallback(mMOPlayer, MediaPlayerCallback, (void*)this);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ xaRes = (*mMOPlayer)->GetInterface(mMOPlayer, XA_IID_PLAY, &mPlayItf);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ xaRes = (*mPlayItf)->RegisterCallback(mPlayItf, PlayItfCallback, (void*)this);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ xaRes = (*mPlayItf)->SetPositionUpdatePeriod(mPlayItf, (XAmillisecond)KPlayPosUpdatePeriod);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ xaRes = (*mPlayItf)->SetCallbackEventsMask( mPlayItf,
+ ( XA_PLAYEVENT_HEADATEND |
+ XA_PLAYEVENT_HEADATNEWPOS |
+ XA_PLAYEVENT_HEADMOVING )
+ );
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ xaRes = (*mMOPlayer)->GetInterface(mMOPlayer, XA_IID_SEEK, &mSeekItf);
+ retVal = mapError(xaRes, ETrue);
+
+ //Metadata
+ xaRes = (*mMOPlayer)->GetInterface(mMOPlayer, XA_IID_METADATAEXTRACTION, &mMetadataExtItf);
+ if(mapError(xaRes, ETrue)==KErrNone) {
+ mbMetadataAvailable = ETrue;
+ setupALKeyMap(); //done only once at creation of meadia player
+ }
+
+ //volume
+ xaRes = (*mMOPlayer)->GetInterface(mMOPlayer, XA_IID_NOKIALINEARVOLUME, &mNokiaLinearVolumeItf);
+ if(mapError(xaRes, ETrue)==KErrNone)
+ mbVolEnabled = ETrue;
+
+ xaRes = (*mMOPlayer)->GetInterface(mMOPlayer, XA_IID_NOKIAVOLUMEEXT, &mNokiaVolumeExtItf);
+ if(mapError(xaRes, ETrue)==KErrNone)
+ mbMuteEnabled = ETrue;
+
+ //buffer status
+ xaRes = (*mMOPlayer)->GetInterface(mMOPlayer, XA_IID_PREFETCHSTATUS, &mPrefetchStatusItf);
+ if(mapError(xaRes, ETrue)==KErrNone) {
+ mbPrefetchStatusChange = ETrue;
+ (*mPrefetchStatusItf)->RegisterCallback(mPrefetchStatusItf, PrefetchItfCallback, (void*)this);
+ (*mPrefetchStatusItf)->SetCallbackEventsMask(mPrefetchStatusItf, XA_PREFETCHEVENT_FILLLEVELCHANGE);
+ }
+
+ //stream information
+ xaRes = (*mMOPlayer)->GetInterface(mMOPlayer, XA_IID_STREAMINFORMATION, &mStreamInformationItf);
+ if(mapError(xaRes, ETrue)==KErrNone) {
+ mbStreamInfoAvailable = ETrue;
+ mParent.cbStreamInformation(ETrue); //indicate first time
+ (*mStreamInformationItf)->RegisterStreamChangeCallback(mStreamInformationItf, StreamInformationItfCallback, (void*)this);
+ }
+
+ //playback rate
+ xaRes = (*mMOPlayer)->GetInterface(mMOPlayer, XA_IID_PLAYBACKRATE, &mPlaybackRateItf);
+ if(mapError(xaRes, ETrue)==KErrNone)
+ mbPlaybackRateItfAvailable = ETrue;
+
+
+ //videopostprocessing
+ xaRes = (*mMOPlayer)->GetInterface(mMOPlayer, XA_IID_VIDEOPOSTPROCESSING, &mVideoPostProcessingItf);
+ if(mapError(xaRes, ETrue)==KErrNone)
+ mbScalable = ETrue;
+
+ }
+
+ if(mbMetadataAvailable) {
+ keyMap.clear();
+ extendedKeyMap.clear();
+ setupMetaData(); //done every time source is changed
+ }
+ else { //send signal for seekable
+ mParent.cbSeekableChanged(ETrue);
+ }
+
+ mCurPosition = 0;
+ mParent.cbPositionChanged(mCurPosition);
+
+ xaRes = (*mPlayItf)->GetDuration(mPlayItf, &dur);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ mDuration = dur;
+ mParent.cbDurationChanged(mDuration);
+
+ return retVal;
+}
+
+void XAPlaySessionImpl::unload()
+{
+ mPlayItf = NULL;
+ mSeekItf = NULL;
+
+ //Metadata
+ mbMetadataAvailable = FALSE;
+ mMetadataExtItf = NULL;
+ alKeyMap.clear();
+ keyMap.clear();
+ extendedKeyMap.clear();
+ //Volume
+ mNokiaLinearVolumeItf = NULL;
+ mbVolEnabled = FALSE;
+ mNokiaVolumeExtItf = NULL;
+ mbMuteEnabled = NULL;
+
+ //buffer status
+ mPrefetchStatusItf = NULL;
+ mbPrefetchStatusChange = FALSE;
+
+ //stream information
+ mStreamInformationItf = NULL;
+ mbStreamInfoAvailable = FALSE;
+ mbAudioStream = FALSE;
+ mbVideoStream = FALSE;
+ mNumStreams = 0;
+
+ //Playbackrate
+ mPlaybackRateItf = NULL;
+ mbPlaybackRateItfAvailable = FALSE;
+
+ mVideoPostProcessingItf = NULL;
+ mbScalable = FALSE;
+ mCurrAspectRatioMode = Qt::KeepAspectRatio;
+
+ //internal
+ mCurPosition = 0; // in milliseconds
+ mDuration = 0; // in milliseconds
+
+
+ mbMediaPlayerUnrealized = TRUE;
+
+ delete mURIName;
+ mURIName = NULL;
+
+}
+
+TInt XAPlaySessionImpl::play()
+{
+ TInt retVal(KErrGeneral);
+ XAresult xaRes;
+ XAuint32 state;
+
+#ifdef USE_VIDEOPLAYERUTILITY
+ mVideoPlayUtil->Play();
+ return 0;
+#endif
+
+ if (!mMOPlayer || !mPlayItf)
+ return retVal;
+
+ xaRes = (*mPlayItf)->GetPlayState(mPlayItf, &state);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ if ((state == XA_PLAYSTATE_STOPPED) ||
+ (state == XA_PLAYSTATE_PAUSED)) {
+ xaRes = (*mPlayItf)->SetPlayState(mPlayItf, XA_PLAYSTATE_PLAYING);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+ }
+ return retVal;
+}
+
+TInt XAPlaySessionImpl::pause()
+{
+ TInt retVal(KErrGeneral);
+ XAresult xaRes;
+ XAuint32 state;
+
+#ifdef USE_VIDEOPLAYERUTILITY
+ TRAPD(err, mVideoPlayUtil->PauseL());
+ return 0;
+#endif
+
+ if (!mMOPlayer || !mPlayItf)
+ return retVal;
+
+ xaRes = (*mPlayItf)->GetPlayState(mPlayItf, &state);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ if ((state == XA_PLAYSTATE_STOPPED) ||
+ (state == XA_PLAYSTATE_PLAYING)) {
+ xaRes = (*mPlayItf)->SetPlayState(mPlayItf, XA_PLAYSTATE_PAUSED);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+ }
+
+ return retVal;
+}
+
+TInt XAPlaySessionImpl::stop()
+{
+ TInt retVal(KErrGeneral);
+ XAresult xaRes;
+ XAuint32 state;
+
+#ifdef USE_VIDEOPLAYERUTILITY
+ mVideoPlayUtil->Stop();
+ return 0;
+#endif
+
+ if (!mMOPlayer || !mPlayItf)
+ return retVal;
+
+ xaRes = (*mPlayItf)->GetPlayState(mPlayItf, &state);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+
+ if ((state == XA_PLAYSTATE_PAUSED) ||
+ (state == XA_PLAYSTATE_PLAYING)) {
+ xaRes = (*mPlayItf)->SetPlayState(mPlayItf, XA_PLAYSTATE_STOPPED);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+ mCurPosition += KPlayPosUpdatePeriod;
+ mParent.cbPositionChanged(mCurPosition);
+ }
+
+ return retVal;
+}
+
+TInt XAPlaySessionImpl::duration(TInt64& aDur)
+{
+ TInt retVal(KErrGeneral);
+
+#ifdef USE_VIDEOPLAYERUTILITY
+ TTimeIntervalMicroSeconds dur(0);
+ TRAPD(err, mVideoPlayUtil->DurationL());
+ if (!err)
+ aDur = dur.Int64() / 1000;
+ return 0;
+#endif
+ if (!mMOPlayer || !mPlayItf)
+ return retVal;
+ aDur = mDuration;
+ return retVal;
+}
+
+TInt XAPlaySessionImpl::position(TInt64& aPos)
+{
+ TInt retVal(KErrGeneral);
+#ifdef USE_VIDEOPLAYERUTILITY
+ TTimeIntervalMicroSeconds dur(0);
+ TRAPD(err, mVideoPlayUtil->PositionL());
+ if (!err)
+ aPos = dur.Int64() / 1000;
+ return 0;
+#endif
+
+/* XAresult xaRes;
+ XAmillisecond pos(0);*/
+
+ if (!mMOPlayer || !mPlayItf)
+ return retVal;
+
+ aPos = mCurPosition;
+ return retVal;
+}
+
+TInt XAPlaySessionImpl::getSeekable(TBool& seekable)
+{
+ TInt retVal(KErrGeneral);
+
+ if (!mMOPlayer || !mSeekItf)
+ return retVal;
+
+ retVal = ETrue;
+ seekable = ETrue;
+
+ return retVal;
+}
+
+TInt XAPlaySessionImpl::seek(TInt64 pos)
+{
+ TInt retVal(KErrGeneral);
+ XAresult xaRes;
+
+ if (!mMOPlayer || !mSeekItf)
+ return retVal;
+
+ xaRes = (*mSeekItf)->SetPosition(mSeekItf, (XAmillisecond)pos, XA_SEEKMODE_FAST);
+ retVal = mapError(xaRes, ETrue);
+ RET_ERR_IF_ERR(retVal);
+ mCurPosition = pos;
+
+ return retVal;
+}
+
+void XAPlaySessionImpl::cbMediaPlayer(XAObjectItf /*caller*/,
+ const void */*pContext*/,
+ XAuint32 event,
+ XAresult result,
+ XAuint32 /*param*/,
+ void */*pInterface*/)
+
+{
+ switch (event) {
+ case XA_OBJECT_EVENT_RESOURCES_LOST:
+ unload();
+ mParent.cbPlaybackStopped(result);
+ break;
+ case XA_OBJECT_EVENT_RUNTIME_ERROR:
+ {
+ switch (result) {
+ case XA_RESULT_RESOURCE_LOST:
+ unload();
+ mParent.cbPlaybackStopped(result);
+ break;
+ default:
+ break;
+ }; /* of switch (result) */
+ }
+ default:
+ break;
+ } /* of switch (event) */
+}
+
+void XAPlaySessionImpl::cbPlayItf(XAPlayItf /*caller*/,
+ void */*pContext*/,
+ XAuint32 event)
+{
+ switch(event) {
+ case XA_PLAYEVENT_HEADATEND:
+ mParent.cbPlaybackStopped(KErrNone);
+ break;
+ case XA_PLAYEVENT_HEADATMARKER:
+ break;
+ case XA_PLAYEVENT_HEADATNEWPOS:
+ mCurPosition += KPlayPosUpdatePeriod;
+ mParent.cbPositionChanged(mCurPosition);
+ break;
+ case XA_PLAYEVENT_HEADMOVING:
+ break;
+ case XA_PLAYEVENT_HEADSTALLED:
+ break;
+ default:
+ break;
+ }
+}
+
+void XAPlaySessionImpl::cbPrefetchItf(XAuint32 event)
+{
+ if(event == XA_PREFETCHEVENT_FILLLEVELCHANGE)
+ mParent.cbPrefetchStatusChanged();
+}
+
+void XAPlaySessionImpl::cbStreamInformationItf( XAuint32 /*eventId*/,
+ XAuint32 /*streamIndex*/,
+ void * /*pEventData*/)
+{
+ mParent.cbStreamInformation(EFalse);
+}
+
+void XAPlaySessionImpl::setAspectRatioMode(Qt::AspectRatioMode aspectRatioMode)
+{
+ if( !mbScalable ||
+ (mCurrAspectRatioMode == aspectRatioMode)) {
+ return;
+ }
+
+ XAuint32 scaleOptions;;
+ XAuint32 backgrndColor = 1;
+ XAuint32 renderingHints = 1;
+
+ switch(aspectRatioMode) {
+ case Qt::IgnoreAspectRatio:
+ scaleOptions = XA_VIDEOSCALE_STRETCH;
+ break;
+ case Qt::KeepAspectRatio:
+ scaleOptions = XA_VIDEOSCALE_FIT;
+ break;
+ case Qt::KeepAspectRatioByExpanding:
+ scaleOptions = XA_VIDEOSCALE_CROP;
+ break;
+ default:
+ return;
+ }
+
+ XAresult xaRes = (*mVideoPostProcessingItf)->SetScaleOptions(mVideoPostProcessingItf, \
+ scaleOptions, backgrndColor, renderingHints);
+ if(mapError(xaRes, ETrue) == KErrNone)
+ xaRes = (*mVideoPostProcessingItf)->Commit(mVideoPostProcessingItf);
+
+ if(mapError(xaRes, ETrue) == KErrNone)
+ mCurrAspectRatioMode = aspectRatioMode;
+}
+
+Qt::AspectRatioMode XAPlaySessionImpl::getAspectRatioMode()
+{
+ return mCurrAspectRatioMode;
+}
+
+
+#ifdef USE_VIDEOPLAYERUTILITY
+void XAPlaySessionImpl::MvpuoOpenComplete(TInt aError)
+{
+ TRACE_FUNCTION_ENTRY;
+ m_VPError = aError;
+ if (mActiveSchedulerWait->IsStarted())
+ mActiveSchedulerWait->AsyncStop();
+ TRACE_FUNCTION_EXIT;
+}
+
+void XAPlaySessionImpl::MvpuoPrepareComplete(TInt aError)
+{
+ TRACE_FUNCTION_ENTRY;
+ m_VPError = aError;
+ if (mActiveSchedulerWait->IsStarted())
+ mActiveSchedulerWait->AsyncStop();
+
+ RWindow* window = (RWindow*)mNativeDisplay.hWindow;
+ RWsSession* wssession = (RWsSession*)mNativeDisplay.hDisplay;
+
+ if (window) {
+ TRect videoExtent = TRect(window->Size());
+ TRect clipRect = TRect(window->Size());
+ TRAP_IGNORE(mVideoPlayUtil->AddDisplayWindowL(*wssession, *(CCoeEnv::Static()->ScreenDevice()), *window, videoExtent, clipRect));
+ TRAP_IGNORE(mVideoPlayUtil->SetAutoScaleL(*window, EAutoScaleBestFit));
+ }
+ TRACE_FUNCTION_EXIT;
+}
+
+void XAPlaySessionImpl::MvpuoFrameReady(CFbsBitmap& /*aFrame*/,TInt /*aError*/)
+{
+ TRACE_FUNCTION_ENTRY_EXIT;
+}
+
+void XAPlaySessionImpl::MvpuoPlayComplete(TInt /*aError*/)
+{
+ TRACE_FUNCTION_ENTRY;
+ mParent.cbPlaybackStopped_EOS();
+ TRACE_FUNCTION_EXIT;
+}
+
+void XAPlaySessionImpl::MvpuoEvent(const TMMFEvent& /*aEvent*/)
+{
+ TRACE_FUNCTION_ENTRY_EXIT;
+}
+
+#endif
+
+TInt XAPlaySessionImpl::mapError(XAresult xa_err, TBool /*debPrn*/)
+{
+ TInt retVal(KErrGeneral);
+
+ switch(xa_err) {
+ case XA_RESULT_SUCCESS:
+ retVal = KErrNone;
+ break;
+ case XA_RESULT_PRECONDITIONS_VIOLATED:
+ break;
+ case XA_RESULT_PARAMETER_INVALID:
+ break;
+ case XA_RESULT_MEMORY_FAILURE:
+ break;
+ case XA_RESULT_RESOURCE_ERROR:
+ break;
+ case XA_RESULT_RESOURCE_LOST:
+ break;
+ case XA_RESULT_IO_ERROR:
+ break;
+ case XA_RESULT_BUFFER_INSUFFICIENT:
+ break;
+ case XA_RESULT_CONTENT_CORRUPTED:
+ break;
+ case XA_RESULT_CONTENT_UNSUPPORTED:
+ break;
+ case XA_RESULT_CONTENT_NOT_FOUND:
+ break;
+ case XA_RESULT_PERMISSION_DENIED:
+ break;
+ case XA_RESULT_FEATURE_UNSUPPORTED:
+ break;
+ case XA_RESULT_INTERNAL_ERROR:
+ break;
+ case XA_RESULT_UNKNOWN_ERROR:
+ break;
+ case XA_RESULT_OPERATION_ABORTED:
+ break;
+ case XA_RESULT_CONTROL_LOST:
+ break;
+ default:
+ break;
+ }
+
+ return retVal;
+}
+
+
+QStringList XAPlaySessionImpl::availableExtendedMetaData () const
+{
+ QStringList retList;
+
+ //create a qlist with all keys in keyMap hash
+ QHashIterator<QString, int> it(extendedKeyMap);
+ while(it.hasNext()) {
+ it.next();
+ retList << it.key();
+ }
+
+ return retList;
+}
+
+QList<QtMultimediaKit::MetaData> XAPlaySessionImpl::availableMetaData () const
+{
+ QList<QtMultimediaKit::MetaData> retList;
+
+ //create a qlist with all keys in keyMap hash
+ QHashIterator<QtMultimediaKit::MetaData, int> it(keyMap);
+ while( it.hasNext() ) {
+ it.next();
+ retList << it.key();
+ }
+
+ return retList;
+}
+
+QVariant XAPlaySessionImpl::getMetaData( int alIndex ) const
+{
+ QVariant ret; //invalid variant
+
+ //find index for the given key
+ if(mMetadataExtItf) {
+ XAuint32 valueSize = 0;
+ XAresult res = (*mMetadataExtItf)->GetValueSize(mMetadataExtItf, alIndex, &valueSize);
+ if(res == XA_RESULT_SUCCESS) {
+ XAMetadataInfo * value = (XAMetadataInfo*)calloc(valueSize, 1);
+ if(value) {
+ res = (*mMetadataExtItf)->GetValue(mMetadataExtItf, alIndex, valueSize, value);
+ if(res == XA_RESULT_SUCCESS) {
+ if(value->encoding == XA_CHARACTERENCODING_ASCII)
+ ret = QVariant ((const char*)value->data);
+ else if(value->encoding == XA_CHARACTERENCODING_UTF16LE)
+ ret = QVariant(QString::fromUtf16((ushort*)value->data, (value->size/2)-1)); //dont include null terminating character
+ else if(value->encoding == XA_CHARACTERENCODING_BINARY)
+ ret = QVariant(QImage::fromData(value->data, value->size));
+ }
+
+ free(value);
+ }
+ }
+ }
+
+ return ret;
+}
+
+QVariant XAPlaySessionImpl::metaData( QtMultimediaKit::MetaData key ) const
+{
+ QVariant ret;
+ if(keyMap.contains(key))
+ ret = getMetaData(keyMap[key]);
+ return ret;
+}
+
+QVariant XAPlaySessionImpl::extendedMetaData(const QString & key ) const
+{
+ QVariant ret;
+ if(extendedKeyMap.contains(key))
+ ret = getMetaData(extendedKeyMap[key]);
+
+ return ret;
+}
+
+bool XAPlaySessionImpl::isMetaDataAvailable() const
+{
+ return ((keyMap.size()>0) || (extendedKeyMap.size()>0));
+}
+
+bool XAPlaySessionImpl::isWritable() const
+{
+ return false;
+}
+
+void XAPlaySessionImpl::setExtendedMetaData( const QString&, const QVariant&)
+{
+ //Do Nothing
+}
+
+void XAPlaySessionImpl::setMetaData( QtMultimediaKit::MetaData, const QVariant& )
+{
+ //Do Nothing
+}
+
+void XAPlaySessionImpl::setupALKeyMap()
+{
+ alKeyMap["KhronosTitle"] = QtMultimediaKit::Title;
+ alKeyMap["KhronosComment"] = QtMultimediaKit::Comment;
+ alKeyMap["KhronosTrackNumber"] = QtMultimediaKit::TrackNumber;
+ alKeyMap["KhronosAlbumArtJPEG"] = QtMultimediaKit::CoverArtImage;
+ alKeyMap["KhronosAlbumArtPNG"] = QtMultimediaKit::CoverArtImage;
+ alKeyMap["KhronosAlbum"] = QtMultimediaKit::AlbumTitle;
+ alKeyMap["KhronosArtist"] = QtMultimediaKit::AlbumArtist;
+ alKeyMap["KhronosGenre"] = QtMultimediaKit::Genre;
+ alKeyMap["KhronosYear"] = QtMultimediaKit::Year;
+ alKeyMap["KhronosYear"] = QtMultimediaKit::Date;
+ alKeyMap["KhronosRating"] = QtMultimediaKit::UserRating;
+ alKeyMap["KhronosCopyright"] = QtMultimediaKit::Copyright;
+ alKeyMap["Author"] = QtMultimediaKit::Author;
+ alKeyMap["Duration"] = QtMultimediaKit::Duration;
+ alKeyMap["Stream Count"] = QtMultimediaKit::ChannelCount;
+ alKeyMap["Composer"] = QtMultimediaKit::Composer;
+ alKeyMap["Resolution"] = QtMultimediaKit::Resolution;
+ alKeyMap["FrameRate"] = QtMultimediaKit::VideoFrameRate;
+ alKeyMap["ClipBitRate"] = QtMultimediaKit::VideoBitRate;
+ alKeyMap["Codec"] = QtMultimediaKit::VideoCodec;
+ alKeyMap["attachedpicture"] = QtMultimediaKit::CoverArtImage;
+
+ /*Keys not available
+ QtMedia::SubTitle
+ QtMedia::Description
+ QtMedia::Category
+ QtMedia::Keywords
+ QtMedia::Language
+ QtMedia::Publisher
+ QtMedia::ParentalRating
+ QtMedia::RatingOrganisation
+ QtMedia::Size
+ QtMedia::MediaType
+ QtMedia::AudioBitrate
+ QtMedia::AudioCodec
+ QtMedia::AverageLevel
+ QtMedia::PeakValue
+ QtMedia::Frequency
+ QtMedia::ContributingArtist
+ QtMedia::Conductor
+ QtMedia::Lyrics
+ QtMedia::Mood
+ QtMedia::TrackCount
+ QtMedia::PixelAspectRatio
+ QtMedia::PosterUri
+ QtMedia::ChapterNumber
+ QtMedia::Director
+ QtMedia::LeadPerformer
+ QtMedia::Writer */
+}
+
+TInt XAPlaySessionImpl::mapMetaDataKey(const char* asckey, QtMultimediaKit::MetaData& key)
+{
+ if(alKeyMap.contains(asckey)) {
+ key = alKeyMap[asckey];
+ return KErrNone;
+ }
+
+ return KErrNotFound;
+}
+
+TInt XAPlaySessionImpl::setupMetaData()
+{
+ XAresult res;
+ if(mMetadataExtItf) {
+ XAuint32 numItems = 0;
+ res = (*mMetadataExtItf)->GetItemCount(mMetadataExtItf, &numItems);
+ RET_ERR_IF_ERR(mapError(res, ETrue));
+
+ for(int i=0; i<numItems; ++i) {
+ XAuint32 keySize;
+ res = (*mMetadataExtItf)->GetKeySize(mMetadataExtItf, i, &keySize);
+ RET_ERR_IF_ERR(mapError(res, ETrue));
+
+ XAMetadataInfo *key = (XAMetadataInfo *)calloc(keySize,1);
+ if(key) {
+ res = (*mMetadataExtItf)->GetKey(mMetadataExtItf, i, keySize, key);
+ RET_ERR_IF_ERR(mapError(res, ETrue));
+
+ if(key->encoding == XA_CHARACTERENCODING_ASCII) { //only handle ASCII keys ignore others
+ QtMultimediaKit::MetaData qtKey;
+ if(mapMetaDataKey((const char*)key->data, qtKey) == KErrNone)//qt metadata
+ keyMap[qtKey] = i;
+ else //extended metadata
+ extendedKeyMap[(const char*)key->data] = i;
+ }
+
+ free(key);
+ }
+ }
+
+ //check for seek property to generate seekable signal
+ QVariant var = extendedMetaData("Seekable");
+ if(!var.isValid() || (var.toString() == "1"))
+ mParent.cbSeekableChanged(ETrue);
+ else
+ mParent.cbSeekableChanged(EFalse);
+
+ }
+
+ return KErrGeneral;
+}
+
+//Volume
+TInt XAPlaySessionImpl::volume(TInt& v)
+{
+ if(mbVolEnabled) {
+ XAresult res = (*mNokiaLinearVolumeItf)->GetVolumeLevel(mNokiaLinearVolumeItf, (XAuint32 *)&v);
+ return mapError(res, ETrue);
+ }
+
+ return KErrNotFound;
+}
+
+TInt XAPlaySessionImpl::setVolume(TInt v)
+{
+ if(mbVolEnabled) {
+ XAresult res = (*mNokiaLinearVolumeItf)->SetVolumeLevel(mNokiaLinearVolumeItf, (XAuint32*)&v);
+ return mapError(res, ETrue);
+ }
+
+ return KErrNotFound;
+}
+
+TInt XAPlaySessionImpl::setMute(TBool bMute)
+{
+ if(mbMuteEnabled) {
+ XAresult res = (*mNokiaVolumeExtItf)->SetMute(mNokiaVolumeExtItf, (XAboolean)bMute);
+ return mapError(res, ETrue);
+ }
+
+ return KErrNotFound;
+
+}
+
+TInt XAPlaySessionImpl::getMute(TBool& bIsMute)
+{
+ if(mbMuteEnabled) {
+ XAboolean xaMute;
+ XAresult res = (*mNokiaVolumeExtItf)->GetMute(mNokiaVolumeExtItf, &xaMute);
+ bIsMute = xaMute;
+ return mapError(res, ETrue);
+ }
+
+ return KErrNotFound;
+}
+
+
+TInt XAPlaySessionImpl::bufferStatus(TInt &bs)
+{
+ TInt ret = KErrNotFound;
+
+ if(mbPrefetchStatusChange) {
+ XApermille satusPerThousand;
+ XAresult res = (*mPrefetchStatusItf)->GetFillLevel(mPrefetchStatusItf, &satusPerThousand);
+ ret = mapError(res, ETrue);
+ if(ret == KErrNone)
+ bs = satusPerThousand/10.0; //convert to parts per hundred
+ }
+ return ret;
+}
+
+QMediaStreamsControl::StreamType XAPlaySessionImpl::mapStreamType(XAuint32& alStreamType)
+{
+ switch(alStreamType) {
+ case XA_DOMAINTYPE_AUDIO:
+ return QMediaStreamsControl::AudioStream;
+ case XA_DOMAINTYPE_VIDEO:
+ return QMediaStreamsControl::VideoStream;
+ case XA_DOMAINTYPE_IMAGE:
+ return QMediaStreamsControl::DataStream;
+ }
+ return QMediaStreamsControl::UnknownStream;
+}
+
+
+TInt XAPlaySessionImpl::numMediaStreams(TUint& numStreams)
+{
+ TInt ret = KErrNotFound;
+ numStreams = 0;
+ if(mbStreamInfoAvailable) {
+ XAMediaContainerInformation mediaContainerInfo;
+ XAresult res = (*mStreamInformationItf)->QueryMediaContainerInformation(mStreamInformationItf, &mediaContainerInfo);
+ ret = mapError(res, ETrue);
+ if(ret == KErrNone)
+ numStreams = mediaContainerInfo.numStreams;
+ }
+ return ret;
+}
+
+TInt XAPlaySessionImpl::streamType(TUint index, QMediaStreamsControl::StreamType& type)
+{
+ TInt ret = KErrNotFound;
+ type = QMediaStreamsControl::UnknownStream;
+ if(mbStreamInfoAvailable) {
+ XAuint32 strType;
+ XAresult res = (*mStreamInformationItf)->QueryStreamType(mStreamInformationItf, (XAuint32)(index+1), &strType);
+ ret = mapError(res, ETrue);
+ if(ret == KErrNone)
+ type = mapStreamType(strType);
+ }
+ return ret;
+}
+
+TInt XAPlaySessionImpl::isStreamActive(TUint index, TBool& isActive)
+{
+ TUint numStreams;
+ TInt ret = numMediaStreams(numStreams);
+ if((ret == KErrNone) && (index < numStreams)) {
+ isActive = EFalse;
+ if(numStreams > 0) {
+ //create array of bools
+ XAboolean *activeStreams = new XAboolean[numStreams+1];
+ XAresult res = (*mStreamInformationItf)->QueryActiveStreams(mStreamInformationItf, (XAuint32*)&numStreams, activeStreams);
+ ret = mapError(res, ETrue);
+ if(ret == KErrNone)
+ isActive = activeStreams[index+1];
+ delete[] activeStreams;
+ }
+ }
+ return ret;
+}
+
+TInt XAPlaySessionImpl::getPlaybackRate(TReal32 &rate)
+{
+ TInt ret = KErrNotFound;
+
+ if(mbPlaybackRateItfAvailable) {
+ XApermille perMilleRate = 0;
+ ret = (*mPlaybackRateItf)->GetRate(mPlaybackRateItf, &perMilleRate);
+ rate = perMilleRate / 1000.0;
+ }
+ return ret;
+}
+
+TInt XAPlaySessionImpl::setPlaybackRate(TReal32 rate)
+{
+ TInt ret = KErrNotFound;
+ if(mbPlaybackRateItfAvailable)
+ ret = (*mPlaybackRateItf)->SetRate(mPlaybackRateItf, (XApermille)(rate * 1000.0));
+ return ret;
+}
+
+
+/* Local function implementation */
+void MediaPlayerCallback( XAObjectItf caller,
+ const void *pContext,
+ XAuint32 event,
+ XAresult result,
+ XAuint32 param,
+ void *pInterface)
+{
+ if (pContext)
+ ((XAPlaySessionImpl*)pContext)->cbMediaPlayer( caller,
+ pContext,
+ event,
+ result,
+ param,
+ pInterface);
+}
+
+void PlayItfCallback( XAPlayItf caller,
+ void *pContext,
+ XAuint32 event)
+{
+ if (pContext)
+ ((XAPlaySessionImpl*)pContext)->cbPlayItf(caller,
+ pContext,
+ event);
+}
+
+void PrefetchItfCallback( XAPrefetchStatusItf /*caller*/,
+ void *pContext,
+ XAuint32 event)
+{
+ if (pContext)
+ ((XAPlaySessionImpl*)pContext)->cbPrefetchItf(event);
+}
+
+void StreamInformationItfCallback( XAStreamInformationItf /*caller*/,
+ XAuint32 eventId,
+ XAuint32 streamIndex,
+ void * pEventData,
+ void * pContext)
+{
+ if (pContext)
+ ((XAPlaySessionImpl*)pContext)->cbStreamInformationItf( eventId,
+ streamIndex,
+ pEventData);
+}
+
+
+
+// End of file
diff --git a/src/plugins/symbian/openmaxal/mediaplayer/xaplaysessionimpl.h b/src/plugins/symbian/openmaxal/mediaplayer/xaplaysessionimpl.h
new file mode 100644
index 000000000..30144712a
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediaplayer/xaplaysessionimpl.h
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** 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$
+** 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 XAPLAYSESSIONIMPL_H
+#define XAPLAYSESSIONIMPL_H
+
+#include <OpenMAXAL.h>
+#include <xanokiavolumeextitf.h>
+#include <xanokialinearvolumeitf.h>
+#ifdef USE_VIDEOPLAYERUTILITY
+#include <VideoPlayer2.h>
+#endif
+
+#include "qtmedianamespace.h"
+#include "qmediastreamscontrol.h"
+
+class XAPlayObserver;
+class RWindow;
+class RWsSession;
+
+class XAPlaySessionImpl
+#ifdef USE_VIDEOPLAYERUTILITY
+ : public MVideoPlayerUtilityObserver
+#endif
+{
+public:
+ XAPlaySessionImpl(XAPlayObserver& parent);
+ ~XAPlaySessionImpl();
+ TInt postConstruct();
+ TInt addNativeDisplay(RWindow* window, RWsSession* wssession);
+ TInt updateNativeDisplay(RWindow* window, RWsSession* wssession);
+ TInt removeNativeDisplay(RWindow* window, RWsSession* wssession);
+ TInt load(const TDesC& aURI);
+ void unload();
+ TInt play();
+ TInt pause();
+ TInt stop();
+ TInt duration(TInt64& aDur);
+ TInt position(TInt64& aPos);
+ TInt getSeekable(TBool& seekable);
+ TInt seek(TInt64 pos);
+
+ //Metadata
+ QStringList availableExtendedMetaData () const;
+ QList<QtMultimediaKit::MetaData> availableMetaData () const;
+ QVariant extendedMetaData(const QString & key ) const;
+ bool isMetaDataAvailable() const;
+ bool isWritable() const;
+ QVariant metaData( QtMultimediaKit::MetaData key ) const;
+ void setExtendedMetaData( const QString & key, const QVariant & value );
+ void setMetaData( QtMultimediaKit::MetaData key, const QVariant & value );
+
+ TInt volume(TInt&);
+ TInt setVolume(TInt);
+ TInt setMute(TBool);
+ TInt getMute(TBool&);
+
+ TInt bufferStatus(TInt &);
+
+
+ TInt numMediaStreams(TUint& numStreams);
+ TInt streamType(TUint index, QMediaStreamsControl::StreamType& type);
+ TInt isStreamActive(TUint index, TBool& isActive);
+
+ TInt getPlaybackRate(TReal32 &rate);
+ TInt setPlaybackRate(TReal32 rate);
+
+ //AspectRatioMode
+ void setAspectRatioMode(Qt::AspectRatioMode);
+ Qt::AspectRatioMode getAspectRatioMode();
+
+public:
+ void cbMediaPlayer( XAObjectItf caller,
+ const void *pContext,
+ XAuint32 event,
+ XAresult result,
+ XAuint32 param,
+ void *pInterface);
+
+ void cbPlayItf(XAPlayItf caller,
+ void *pContext,
+ XAuint32 event);
+
+
+ void cbPrefetchItf(XAuint32);
+
+ void cbStreamInformationItf(XAuint32, XAuint32, void*);
+
+#ifdef USE_VIDEOPLAYERUTILITY
+ //MVideoPlayerUtilityObserver
+ void MvpuoOpenComplete(TInt aError);
+ void MvpuoPrepareComplete(TInt aError);
+ void MvpuoFrameReady(CFbsBitmap& aFrame,TInt aError);
+ void MvpuoPlayComplete(TInt aError);
+ void MvpuoEvent(const TMMFEvent& aEvent);
+#endif
+
+private:
+ TInt mapError(XAresult xa_err,
+ TBool debPrn);
+ void setupALKeyMap();
+ TInt setupMetaData();
+ TInt mapMetaDataKey(const char* asckey, QtMultimediaKit::MetaData& key);
+ QVariant getMetaData( int alIndex ) const;
+
+ QMediaStreamsControl::StreamType mapStreamType(XAuint32& alStreamType);
+
+
+private:
+ XAPlayObserver& mParent;
+ XAObjectItf mEOEngine;
+ XAObjectItf mMOPlayer;
+ XAPlayItf mPlayItf;
+ XASeekItf mSeekItf;
+ HBufC8* mURIName;
+ HBufC8* mWAVMime;
+ // Audio Source
+ XADataSource mDataSource;
+ XADataFormat_MIME mMime;
+ XADataLocator_URI mUri;
+ //Audio Sink
+ XADataSink mAudioSink;
+ XADataLocator_IODevice mLocatorOutputDevice;
+ //Video Sink
+ XADataSink mVideoSink;
+ XADataLocator_NativeDisplay mNativeDisplay;
+
+ //Metadata
+ TBool mbMetadataAvailable;
+ XAMetadataExtractionItf mMetadataExtItf;
+ QHash<QString, QtMultimediaKit::MetaData> alKeyMap;
+ QHash<QtMultimediaKit::MetaData, int> keyMap;
+ QHash<QString,int> extendedKeyMap;
+
+ //Volume
+ XANokiaLinearVolumeItf mNokiaLinearVolumeItf;
+ TBool mbVolEnabled;
+ XANokiaVolumeExtItf mNokiaVolumeExtItf;
+ TBool mbMuteEnabled;
+
+ //buffer status
+ XAPrefetchStatusItf mPrefetchStatusItf;
+ TBool mbPrefetchStatusChange;
+
+ //stream information
+ XAStreamInformationItf mStreamInformationItf;
+ TBool mbStreamInfoAvailable;
+ TBool mbAudioStream;
+ TBool mbVideoStream;
+ TInt mNumStreams;
+
+ //Playbackrate
+ XAPlaybackRateItf mPlaybackRateItf;
+ TBool mbPlaybackRateItfAvailable;
+
+ XAVideoPostProcessingItf mVideoPostProcessingItf;
+ TBool mbScalable;
+ Qt::AspectRatioMode mCurrAspectRatioMode;
+
+ //internal
+ TInt64 mCurPosition; // in milliseconds
+ TInt64 mDuration; // in milliseconds
+
+ TBool mbMediaPlayerUnrealized;
+#ifdef USE_VIDEOPLAYERUTILITY
+ CVideoPlayerUtility2* mVideoPlayUtil;
+ CActiveSchedulerWait* mActiveSchedulerWait;
+ TInt m_VPError;
+#endif
+};
+
+#endif /* XAPLAYSESSIONIMPL_H */
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/mediarecorder.pri b/src/plugins/symbian/openmaxal/mediarecorder/mediarecorder.pri
new file mode 100644
index 000000000..ee78e8348
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/mediarecorder.pri
@@ -0,0 +1,24 @@
+INCLUDEPATH += $$PWD
+
+# Input
+HEADERS += \
+ $$PWD/qxarecordmediaservice.h \
+ $$PWD/qxarecordsession.h \
+ $$PWD/qxaaudioendpointselector.h \
+ $$PWD/qxaaudioencodercontrol.h \
+ $$PWD/qxamediacontainercontrol.h \
+ $$PWD/qxamediarecordercontrol.h \
+ $$PWD/xarecordsessionimpl.h \
+ $$PWD/xarecordsessioncommon.h
+
+SOURCES += \
+ $$PWD/qxarecordmediaservice.cpp \
+ $$PWD/qxarecordsession.cpp \
+ $$PWD/qxaaudioendpointselector.cpp \
+ $$PWD/qxaaudioencodercontrol.cpp \
+ $$PWD/qxamediacontainercontrol.cpp \
+ $$PWD/qxamediarecordercontrol.cpp \
+ $$PWD/xarecordsessionimpl.cpp
+
+LIBS += \
+ -lbafl
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.cpp b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.cpp
new file mode 100644
index 000000000..2826f79a2
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.cpp
@@ -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$
+** 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 "qxaaudioencodercontrol.h"
+#include "qxarecordsession.h"
+#include "qxacommon.h"
+
+QXAAudioEncoderControl::QXAAudioEncoderControl(QXARecordSession *session, QObject *parent)
+:QAudioEncoderControl(parent), m_session(session)
+{
+}
+
+QXAAudioEncoderControl::~QXAAudioEncoderControl()
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+}
+
+QStringList QXAAudioEncoderControl::supportedAudioCodecs() const
+{
+ if (m_session)
+ return m_session->supportedAudioCodecs();
+ return QStringList();
+}
+
+QString QXAAudioEncoderControl::codecDescription(const QString &codecName) const
+{
+ if (m_session)
+ return m_session->codecDescription(codecName);
+ return QString();
+}
+
+QList<int> QXAAudioEncoderControl::supportedSampleRates(
+ const QAudioEncoderSettings &settings,
+ bool *continuous) const
+{
+ if (m_session)
+ return m_session->supportedSampleRates(settings, continuous);
+ return QList<int>();
+}
+
+QAudioEncoderSettings QXAAudioEncoderControl::audioSettings() const
+{
+ if (m_session)
+ return m_session->audioSettings();
+ return QAudioEncoderSettings();
+}
+
+void QXAAudioEncoderControl::setAudioSettings(const QAudioEncoderSettings &settings)
+{
+ if (m_session)
+ m_session->setAudioSettings(settings);
+}
+
+QStringList QXAAudioEncoderControl::supportedEncodingOptions(const QString &codec) const
+{
+ if (m_session)
+ return m_session->supportedEncodingOptions(codec);
+ return QStringList();
+}
+
+QVariant QXAAudioEncoderControl::encodingOption(const QString &codec, const QString &name) const
+{
+ if (m_session)
+ return m_session->encodingOption(codec, name);
+ return QVariant();
+}
+
+void QXAAudioEncoderControl::setEncodingOption(
+ const QString &codec, const QString &name, const QVariant &value)
+{
+ if (m_session)
+ m_session->setEncodingOption(codec, name, value);
+}
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.h b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.h
new file mode 100644
index 000000000..117d36fdc
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioencodercontrol.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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$
+** 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 QXAAUDIOENCODERCONTROL_H
+#define QXAAUDIOENCODERCONTROL_H
+
+#include <qaudioencodercontrol.h>
+
+QT_USE_NAMESPACE
+
+/*
+ * This class implements QAudioEncoderControl interface.
+ */
+class QXARecordSession;
+
+class QXAAudioEncoderControl : public QAudioEncoderControl
+{
+ Q_OBJECT
+
+public:
+ QXAAudioEncoderControl(QXARecordSession *session, QObject *parent = 0);
+ virtual ~QXAAudioEncoderControl();
+
+ QStringList supportedAudioCodecs() const;
+ QString codecDescription(const QString &codecName) const;
+
+ QList<int> supportedSampleRates(const QAudioEncoderSettings &settings,
+ bool *continuous = 0) const;
+
+ QAudioEncoderSettings audioSettings() const;
+ void setAudioSettings(const QAudioEncoderSettings &settings);
+
+ QStringList supportedEncodingOptions(const QString &codec) const;
+ QVariant encodingOption(const QString &codec, const QString &name) const;
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
+
+private:
+ QXARecordSession *m_session;
+};
+
+#endif /* QXAAUDIOENCODERCONTROL_H */
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.cpp b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.cpp
new file mode 100644
index 000000000..7e546595c
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qxaaudioendpointselector.h"
+#include "qxarecordsession.h"
+#include "qxacommon.h"
+
+QXAAudioEndpointSelector::QXAAudioEndpointSelector(QXARecordSession *session, QObject *parent)
+:QAudioEndpointSelector(parent), m_session(session)
+{
+ connect(m_session, SIGNAL(availableAudioInputsChanged()),
+ this, SLOT(availableAudioInputsChanged()));
+ connect(m_session, SIGNAL(activeEndpointChanged(QString)),
+ this, SIGNAL(activeEndpointChanged(QString)));
+}
+
+QXAAudioEndpointSelector::~QXAAudioEndpointSelector()
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+}
+
+QList<QString> QXAAudioEndpointSelector::availableEndpoints() const
+{
+ if (m_session)
+ return m_session->availableEndpoints();
+ return QList<QString>();
+}
+
+QString QXAAudioEndpointSelector::endpointDescription(const QString &name) const
+{
+ if (m_session)
+ return m_session->endpointDescription(name);
+ return QString();
+}
+
+QString QXAAudioEndpointSelector::defaultEndpoint() const
+{
+ if (m_session)
+ return m_session->defaultEndpoint();
+ return QString();
+}
+
+QString QXAAudioEndpointSelector::activeEndpoint() const
+{
+ if (m_session)
+ return m_session->activeEndpoint();
+ return QString();
+}
+
+void QXAAudioEndpointSelector::setActiveEndpoint(const QString &name)
+{
+ if (m_session)
+ m_session->setActiveEndpoint(name);
+}
+
+void QXAAudioEndpointSelector::availableAudioInputsChanged()
+ {
+ emit availableEndpointsChanged();
+ }
+
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.h b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.h
new file mode 100644
index 000000000..5fbadbc64
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/qxaaudioendpointselector.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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$
+** 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 QXAAUDIOENDPOINTSELECTOR_H
+#define QXAAUDIOENDPOINTSELECTOR_H
+
+#include <qaudioendpointselector.h>
+
+QT_USE_NAMESPACE
+
+/*
+ * This class implements QAudioEncoderControl interface.
+ */
+class QXARecordSession;
+
+class QXAAudioEndpointSelector : public QAudioEndpointSelector
+{
+ Q_OBJECT
+
+public:
+ QXAAudioEndpointSelector(QXARecordSession *session, QObject *parent);
+ ~QXAAudioEndpointSelector();
+
+ QList<QString> availableEndpoints() const;
+ QString endpointDescription(const QString &name) const;
+ QString defaultEndpoint() const;
+ QString activeEndpoint() const;
+
+public Q_SLOTS:
+ void setActiveEndpoint(const QString &name);
+
+private Q_SLOTS:
+ void availableAudioInputsChanged();
+
+private:
+ QXARecordSession *m_session;
+};
+
+#endif /* QXAAUDIOENDPOINTSELECTOR_H */
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.cpp b/src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.cpp
new file mode 100644
index 000000000..0d97fd5e5
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qxamediacontainercontrol.h"
+#include "qxarecordsession.h"
+#include "qxacommon.h"
+
+QXAMediaContainerControl::QXAMediaContainerControl(QXARecordSession *session, QObject *parent)
+:QMediaContainerControl(parent), m_session(session)
+{
+}
+
+QXAMediaContainerControl::~QXAMediaContainerControl()
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+}
+
+QStringList QXAMediaContainerControl::supportedContainers() const
+{
+ if (m_session)
+ return m_session->supportedContainers();
+ return QStringList();
+}
+
+QString QXAMediaContainerControl::containerMimeType() const
+{
+ if (m_session)
+ return m_session->containerMimeType();
+ return QString();
+}
+
+void QXAMediaContainerControl::setContainerMimeType(const QString &formatMimeType)
+{
+ if (m_session)
+ m_session->setContainerMimeType(formatMimeType);
+}
+
+QString QXAMediaContainerControl::containerDescription(const QString &formatMimeType) const
+{
+ if (m_session)
+ return m_session->containerDescription(formatMimeType);
+ return QString();
+}
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.h b/src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.h
new file mode 100644
index 000000000..4b05fc190
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/qxamediacontainercontrol.h
@@ -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$
+** 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 QXAMEDIACONTAINERCONTROL_H
+#define QXAMEDIACONTAINERCONTROL_H
+
+#include <qmediacontainercontrol.h>
+
+QT_USE_NAMESPACE
+
+/*
+ * This class implements QMediaContainerControl interface.
+ */
+class QXARecordSession;
+
+class QXAMediaContainerControl : public QMediaContainerControl
+{
+ Q_OBJECT
+
+public:
+ QXAMediaContainerControl(QXARecordSession *session, QObject *parent = 0);
+ virtual ~QXAMediaContainerControl();
+
+ QStringList supportedContainers() const;
+ QString containerMimeType() const;
+ void setContainerMimeType(const QString &formatMimeType);
+ QString containerDescription(const QString &formatMimeType) const;
+
+private:
+ QXARecordSession *m_session;
+};
+
+#endif /* QXAMEDIACONTAINERCONTROL_H */
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.cpp b/src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.cpp
new file mode 100644
index 000000000..330edf008
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qxamediarecordercontrol.h"
+#include "qxarecordsession.h"
+#include "qxacommon.h"
+
+QXAMediaRecoderControl::QXAMediaRecoderControl(QXARecordSession *session, QObject *parent)
+:QMediaRecorderControl(parent), m_session(session)
+{
+ connect(m_session, SIGNAL(stateChanged(QMediaRecorder::State)),
+ this, SIGNAL(stateChanged(QMediaRecorder::State)));
+ connect(m_session, SIGNAL(error(int,QString)),
+ this,SIGNAL(error(int,QString)));
+ connect(m_session, SIGNAL(durationChanged(qint64)),
+ this, SIGNAL(durationChanged(qint64)));
+}
+
+QXAMediaRecoderControl::~QXAMediaRecoderControl()
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+}
+
+QUrl QXAMediaRecoderControl::outputLocation() const
+{
+ if (m_session)
+ return m_session->outputLocation();
+ return QUrl();
+}
+
+bool QXAMediaRecoderControl::setOutputLocation(const QUrl &location)
+{
+ if (m_session)
+ return m_session->setOutputLocation(location);
+ return false;
+}
+
+QMediaRecorder::State QXAMediaRecoderControl::state() const
+{
+ if (m_session)
+ return m_session->state();
+ return QMediaRecorder::StoppedState;
+}
+
+qint64 QXAMediaRecoderControl::duration() const
+{
+ if (m_session)
+ return m_session->duration();
+ return 0;
+}
+
+void QXAMediaRecoderControl::record()
+{
+ if (m_session)
+ m_session->record();
+}
+
+void QXAMediaRecoderControl::pause()
+{
+ if (m_session)
+ m_session->pause();
+}
+
+void QXAMediaRecoderControl::stop()
+{
+ if (m_session)
+ m_session->stop();
+}
+
+void QXAMediaRecoderControl::applySettings()
+{
+ if (m_session)
+ m_session->applySettings();
+}
+
+bool QXAMediaRecoderControl::isMuted() const
+{
+ return false;
+}
+
+void QXAMediaRecoderControl::setMuted(bool)
+{
+
+}
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.h b/src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.h
new file mode 100644
index 000000000..c6495f2e4
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/qxamediarecordercontrol.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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$
+** 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 QXAMEDIARECORDERCONTROL_H
+#define QXAMEDIARECORDERCONTROL_H
+
+#include <qmediarecorder.h>
+#include <qmediarecordercontrol.h>
+
+QT_USE_NAMESPACE
+
+/*
+ * This class implements QMediaRecorderControl interface.
+ */
+
+class QXARecordSession;
+
+class QXAMediaRecoderControl : public QMediaRecorderControl
+{
+ Q_OBJECT
+
+public:
+ QXAMediaRecoderControl(QXARecordSession *session, QObject *parent = 0);
+ virtual ~QXAMediaRecoderControl();
+
+ QUrl outputLocation() const;
+ bool setOutputLocation(const QUrl &location);
+
+ QMediaRecorder::State state() const;
+
+ qint64 duration() const;
+ bool isMuted() const;
+ void applySettings();
+
+public Q_SLOTS:
+ void record();
+ void pause();
+ void stop();
+ void setMuted(bool);
+
+private:
+ QXARecordSession *m_session;
+};
+
+#endif /* QXAMEDIARECORDERCONTROL_H */
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.cpp b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.cpp
new file mode 100644
index 000000000..05c57feb7
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <QString>
+
+#include "qxarecordmediaservice.h"
+#include "qxarecordsession.h"
+#include "qxamediarecordercontrol.h"
+#include "qxaaudioendpointselector.h"
+#include "qxaaudioencodercontrol.h"
+#include "qxamediacontainercontrol.h"
+#include "qxacommon.h"
+
+QXARecodMediaService::QXARecodMediaService(QObject *parent)
+:QMediaService(parent)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ m_session = new QXARecordSession(this);
+ m_control = new QXAMediaRecoderControl(m_session, this);
+ m_endpoint = new QXAAudioEndpointSelector(m_session, this);
+ m_encoder = new QXAAudioEncoderControl(m_session, this);
+ m_container = new QXAMediaContainerControl(m_session, this);
+}
+
+QXARecodMediaService::~QXARecodMediaService()
+{
+ QT_TRACE_FUNCTION_ENTRY_EXIT;
+}
+
+QMediaControl* QXARecodMediaService::requestControl(const char *name)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ if (qstrcmp(name, QMediaRecorderControl_iid) == 0)
+ return m_control;
+ else if (qstrcmp(name, QAudioEndpointSelector_iid) == 0)
+ return m_endpoint;
+ else if (qstrcmp(name, QAudioEncoderControl_iid) == 0)
+ return m_encoder;
+ else if (qstrcmp(name, QMediaContainerControl_iid) == 0)
+ return m_container;
+ QT_TRACE_FUNCTION_EXIT;
+ return 0;
+}
+
+void QXARecodMediaService::releaseControl(QMediaControl *control)
+{
+ Q_UNUSED(control)
+}
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.h b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.h
new file mode 100644
index 000000000..98f5136e8
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordmediaservice.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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$
+** 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 QXARECORDMEDIASERVICE_H
+#define QXARECORDMEDIASERVICE_H
+
+#include <QtCore/qobject.h>
+#include <qmediaservice.h>
+
+QT_USE_NAMESPACE
+
+/*
+ * This class implements QMediaService interface.
+ */
+
+class QXARecordSession;
+class QXAMediaRecoderControl;
+class QXAAudioEndpointSelector;
+class QXAAudioEncoderControl;
+class QXAMediaContainerControl;
+
+class QXARecodMediaService : public QMediaService
+{
+
+ Q_OBJECT
+
+public:
+ QXARecodMediaService(QObject *parent = 0);
+ ~QXARecodMediaService();
+ QMediaControl *requestControl(const char *name);
+ void releaseControl( QMediaControl *control);
+private:
+ QXARecordSession *m_session;
+ QXAMediaRecoderControl *m_control;
+ QXAAudioEndpointSelector *m_endpoint;
+ QXAAudioEncoderControl *m_encoder;
+ QXAMediaContainerControl *m_container;
+};
+
+#endif /* QXARECORDMEDIASERVICE_H */
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.cpp b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.cpp
new file mode 100644
index 000000000..76cdfc3da
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.cpp
@@ -0,0 +1,766 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QVariant>
+#include <QtCore/qdir.h>
+#include <qtmedianamespace.h>
+#include "qxarecordsession.h"
+#include "xarecordsessionimpl.h"
+#include "qxacommon.h"
+
+/* The following declaration is required to allow QList<int> to be added to
+ * QVariant
+ */
+Q_DECLARE_METATYPE(QList<uint>)
+
+/* This macro checks for m_impl null pointer. If it is, emits an error signal
+ * error(QMediaRecorder::ResourceError, tr("Service has not been started"));
+ * and returns from function immediately with value 's'.
+ */
+
+#define RETURN_s_IF_m_impl_IS_NULL(s) \
+ if (!m_impl) { \
+ emit error(QMediaRecorder::ResourceError, QXARecordSession::tr("Service has not been started")); \
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Service has not been started\"))"); \
+ return s; \
+ }
+
+/* This macro checks for m_impl null pointer. If it is, emits an error signal
+ * error(QMediaRecorder::ResourceError, tr("Service has not been started"));
+ * and returns from function immediately.
+ */
+#define RETURN_IF_m_impl_IS_NULL \
+ if (!m_impl) { \
+ emit error(QMediaRecorder::ResourceError, QXARecordSession::tr("Service has not been started")); \
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Service has not been started\"))"); \
+ return; \
+ }
+
+QXARecordSession::QXARecordSession(QObject *parent)
+:QObject(parent),
+m_state(QMediaRecorder::StoppedState),
+m_previousState(QMediaRecorder::StoppedState)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ m_impl = NULL;
+ m_impl = new XARecordSessionImpl(*this);
+ if (m_impl) {
+ if (m_impl->postConstruct() == KErrNone) {
+ initCodecsList();
+ initContainersList();
+ m_containerMimeType = QString("audio/wav");
+ m_audioencodersettings.setCodec("pcm");
+ m_audioencodersettings.setBitRate(0);
+ m_audioencodersettings.setChannelCount(-1);
+ m_audioencodersettings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding);
+ m_audioencodersettings.setQuality(QtMultimediaKit::NormalQuality);
+ m_audioencodersettings.setSampleRate(-1);
+ setEncoderSettingsToImpl();
+ m_URItoImplSet = false;
+ QT_TRACE1("Initialized implementation");
+ }
+ else {
+ delete m_impl;
+ m_impl = NULL;
+ QT_TRACE1("Error initializing implementation");
+ }
+ }
+ else {
+ emit error(QMediaRecorder::ResourceError, tr("Unable to start Service"));
+ }
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+QXARecordSession::~QXARecordSession()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ delete m_impl;
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+QUrl QXARecordSession::outputLocation()
+{
+ return m_outputLocation;
+}
+
+bool QXARecordSession::setOutputLocation(const QUrl &location)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ RETURN_s_IF_m_impl_IS_NULL(false);
+
+ // Location can be set only when recorder is in stopped state.
+ if (state() != QMediaRecorder::StoppedState)
+ return false;
+
+ // Validate URL
+ if (!location.isValid())
+ return false;
+
+ // If old and new locations are same, do nothing.
+ QString newUrlStr = (QUrl::fromUserInput(location.toString())).toString();
+ QString curUrlStr = (QUrl::fromUserInput(m_outputLocation.toString())).toString();
+ if (curUrlStr.compare(newUrlStr) == KErrNone)
+ return true;
+
+ QT_TRACE2("Location:", newUrlStr);
+ m_outputLocation = location;
+ /* New file, so user can set new settings */
+ m_previousState = QMediaRecorder::StoppedState;
+ m_URItoImplSet = false;
+
+ QT_TRACE_FUNCTION_EXIT;
+ return true;
+}
+
+QMediaRecorder::State QXARecordSession::state()
+{
+ return m_state;
+}
+
+qint64 QXARecordSession::duration()
+{
+ TInt64 dur(0);
+
+ QT_TRACE_FUNCTION_ENTRY;
+
+ RETURN_s_IF_m_impl_IS_NULL(dur);
+
+ m_impl->duration(dur);
+
+ QT_TRACE_FUNCTION_EXIT;
+ return (qint64)dur;
+}
+
+void QXARecordSession::applySettings()
+{
+ /* Settings can only be applied when the recorder is in the stopped
+ * state after creation. */
+ if ((state() == QMediaRecorder::StoppedState) && (m_state == m_previousState)) {
+ if (m_appliedaudioencodersettings != m_audioencodersettings)
+ setEncoderSettingsToImpl();
+ }
+ else {
+ emit error(QMediaRecorder::FormatError, tr("Settings cannot be changed once recording started"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Settings cannot be changed once recording started\"))");
+ }
+}
+
+void QXARecordSession::record()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ RETURN_IF_m_impl_IS_NULL;
+
+ /* No op if object is already in recording state */
+ if (state() == QMediaRecorder::RecordingState)
+ return;
+
+ /* 1. Set encoder settings here */
+ if (m_appliedaudioencodersettings != m_audioencodersettings)
+ RET_IF_FALSE(setEncoderSettingsToImpl());
+
+ /* 2. Set URI to impl */
+ RET_IF_FALSE(setURIToImpl());
+
+ /* 3. Start recording...
+ * If successful, setRecorderState(QMediaRecorder::RecordingState);
+ * will be called from the callback cbRecordingStarted()
+ */
+ if (m_impl->record() != KErrNone) {
+ emit error(QMediaRecorder::ResourceError, tr("Generic error"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Generic error\"))");
+ }
+
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXARecordSession::pause()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ RETURN_IF_m_impl_IS_NULL;
+
+ /* No op if object is already in paused/stopped state */
+ if ((state() == QMediaRecorder::PausedState) || (state() == QMediaRecorder::StoppedState)) {
+ return;
+ }
+
+ if (m_impl->pause() == KErrNone) {
+ setRecorderState(QMediaRecorder::PausedState);
+ }
+ else {
+ emit error(QMediaRecorder::ResourceError, tr("Unable to pause"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Unable to pause\"))");
+ }
+
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXARecordSession::stop()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ RETURN_IF_m_impl_IS_NULL;
+
+ /* No op if object is already in paused state */
+ if (state() == QMediaRecorder::StoppedState)
+ return;
+
+ if ((m_impl->stop() == KErrNone)) {
+ setRecorderState(QMediaRecorder::StoppedState);
+ }
+ else {
+ emit error(QMediaRecorder::ResourceError, tr("Unable to stop"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Unable to stop\"))");
+ }
+
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXARecordSession::cbDurationChanged(TInt64 new_pos)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ emit durationChanged((qint64)new_pos);
+ SIGNAL_EMIT_TRACE1("emit durationChanged((qint64)new_pos);");
+
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXARecordSession::cbAvailableAudioInputsChanged()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ emit availableAudioInputsChanged();
+ SIGNAL_EMIT_TRACE1("emit availableAudioInputsChanged();");
+
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXARecordSession::cbRecordingStarted()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ setRecorderState(QMediaRecorder::RecordingState);
+
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXARecordSession::cbRecordingStopped()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ emit error(QMediaRecorder::ResourceError, tr("Resources Unavailable"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Resources Unavailable\"))");
+ setRecorderState(QMediaRecorder::StoppedState);
+ /* Set record state to Stopped */
+ if (m_impl)
+ m_impl->stop();
+
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+/* For QAudioEndpointSelector begin */
+QList<QString> QXARecordSession::availableEndpoints()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ QList<QString> strList;
+
+ RETURN_s_IF_m_impl_IS_NULL(strList);
+
+ QString str;
+ RArray<TPtrC> names;
+ m_impl->getAudioInputDeviceNames(names);
+ for (TInt index = 0; index < names.Count(); index++) {
+ str = QString((QChar*)names[index].Ptr(), names[index].Length());
+ strList.append(str);
+ }
+
+ QT_TRACE_FUNCTION_EXIT;
+ return strList;
+}
+
+QString QXARecordSession::endpointDescription(const QString &name)
+{
+ /* From AL we get only device name */
+ return name;
+}
+
+QString QXARecordSession::defaultEndpoint()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ QString str;
+
+ RETURN_s_IF_m_impl_IS_NULL(str);
+
+ TPtrC name;
+ if(m_impl->defaultAudioInputDevice(name) == KErrNone)
+ str = QString((QChar*)name.Ptr(), name.Length());
+
+ QT_TRACE_FUNCTION_EXIT;
+ return str;
+}
+
+QString QXARecordSession::activeEndpoint()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ QString str;
+
+ RETURN_s_IF_m_impl_IS_NULL(str);
+
+ TPtrC name;
+ if(m_impl->activeAudioInputDevice(name) == KErrNone)
+ str = QString((QChar*)name.Ptr(), name.Length());
+
+ QT_TRACE_FUNCTION_EXIT;
+ return str;
+}
+
+void QXARecordSession::setActiveEndpoint(const QString &name)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ RETURN_IF_m_impl_IS_NULL;
+
+ if (name.isNull() || name.isEmpty())
+ return;
+
+ TPtrC16 tempPtr(reinterpret_cast<const TUint16*>(name.utf16()));
+ if (m_impl->setAudioInputDevice(tempPtr) == true) {
+ emit activeEndpointChanged(name);
+ SIGNAL_EMIT_TRACE1("emit activeEndpointChanged(name)");
+ }
+ else {
+ emit error(QMediaRecorder::ResourceError, tr("Invalid endpoint"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Invalid endpoint\"))");
+ }
+
+ QT_TRACE_FUNCTION_EXIT;
+}
+/* For QAudioEndpointSelector end */
+
+/* For QAudioEncoderControl begin */
+QStringList QXARecordSession::supportedAudioCodecs()
+{
+ return m_codecs;
+}
+
+QString QXARecordSession::codecDescription(const QString &codecName)
+{
+ if (m_codecs.contains(codecName))
+ return QString(codecName);
+ return QString();
+}
+
+QList<int> QXARecordSession::supportedSampleRates(
+ const QAudioEncoderSettings &settings,
+ bool *continuous)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ QList<int> srList;
+
+ RETURN_s_IF_m_impl_IS_NULL(srList);
+
+ QString selectedCodec = settings.codec();
+ if (selectedCodec.isNull() || selectedCodec.isEmpty())
+ selectedCodec = QString("pcm");
+
+ if (m_codecs.indexOf(selectedCodec) >= 0) {
+ RArray<TInt32> sampleRates;
+ TBool isContinuous;
+ TPtrC16 tempPtr(reinterpret_cast<const TUint16*>(selectedCodec.utf16()));
+ if (m_impl->getSampleRates(tempPtr, sampleRates, isContinuous) == KErrNone) {
+ for (TInt index = 0; index < sampleRates.Count(); index++)
+ srList.append(sampleRates[index]);
+ sampleRates.Close();
+ if (continuous)
+ {
+ *continuous = false;
+ if (isContinuous == true)
+ *continuous = true;
+ }
+ }
+ }
+
+ QT_TRACE_FUNCTION_EXIT;
+ return srList;
+}
+
+QAudioEncoderSettings QXARecordSession::audioSettings()
+{
+ return m_appliedaudioencodersettings;
+}
+
+void QXARecordSession::setAudioSettings(const QAudioEncoderSettings &settings)
+{
+ /* Settings can only be set when the recorder is in the stopped
+ * state after creation. */
+ if ((state() == QMediaRecorder::StoppedState) && (m_state == m_previousState)) {
+ /* Validate and ignore rest of the settings */
+ m_audioencodersettings = settings;
+ }
+ else {
+ emit error(QMediaRecorder::FormatError, tr("Settings cannot be changed once recording started"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Settings cannot be changed once recording started\"))");
+ }
+}
+
+QStringList QXARecordSession::supportedEncodingOptions(const QString &codec)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ Q_UNUSED(codec);
+ QStringList options;
+ if ((codec.compare("aac") == 0) ||
+ (codec.compare("amr") == 0))
+ {
+ options << "bitrate" << "quality";
+ }
+
+
+ QT_TRACE_FUNCTION_EXIT;
+ return options;
+}
+
+QVariant QXARecordSession::encodingOption(const QString &codec, const QString &name)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ QVariant encodingOption;
+ QMap<QString, QVariant> map;
+ RETURN_s_IF_m_impl_IS_NULL(encodingOption);
+
+ if (name.compare("bitrate") == 0) {
+ TPtrC16 tempPtr(reinterpret_cast<const TUint16*>(codec.utf16()));
+ QList<uint> bitrateList;
+ RArray<TUint32> bitrates;
+ TBool continuous;
+ if (m_impl->getBitrates(tempPtr, bitrates, continuous) == KErrNone) {
+ for (TInt index = 0; index < bitrates.Count(); index++)
+ bitrateList.append(bitrates[index]);
+ bitrates.Close();
+ }
+ encodingOption.setValue(bitrateList);
+ map.insert("continuous", QVariant(continuous));
+ map.insert("bitrates", encodingOption);
+ }
+
+ QT_TRACE_FUNCTION_EXIT;
+ return map;
+}
+
+void QXARecordSession::setEncodingOption(
+ const QString &codec,
+ const QString &name,
+ const QVariant &value)
+{
+ /*
+ * Currently nothing can be set via this function.
+ * Bitrate is set via QAudioEncoderSettings::setBitrate().
+ */
+ Q_UNUSED(codec);
+ Q_UNUSED(name);
+ Q_UNUSED(value);
+}
+/* For QAudioEncoderControl end */
+
+QStringList QXARecordSession::supportedContainers()
+{
+ return m_containers;
+}
+
+QString QXARecordSession::containerMimeType()
+{
+ return m_containerMimeType;
+}
+
+void QXARecordSession::setContainerMimeType(const QString &formatMimeType)
+{
+ if (formatMimeType.isNull() || formatMimeType.isEmpty())
+ return;
+ else if (m_containers.indexOf(formatMimeType) >= 0 )
+ m_containerMimeType = formatMimeType;
+ else {
+ emit error(QMediaRecorder::FormatError, tr("Invalid container"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid container\"))");
+ }
+}
+
+QString QXARecordSession::containerDescription(const QString &formatMimeType)
+{
+ int index = m_containers.indexOf(formatMimeType);
+ if (index >= 0) {
+ return m_containersDesc.at(index);
+ }
+ else {
+ emit error(QMediaRecorder::FormatError, tr("Invalid container"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid container\"))");
+ }
+ return QString();
+}
+
+void QXARecordSession::setRecorderState(QMediaRecorder::State state)
+{
+ if (state != m_state) {
+ m_previousState = m_state;
+ m_state = state;
+ emit stateChanged(m_state);
+ SIGNAL_EMIT_TRACE1("emit stateChanged(m_state);");
+ }
+}
+
+void QXARecordSession::initCodecsList()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ RETURN_IF_m_impl_IS_NULL;
+
+ m_codecs.clear();
+
+ const RArray<TPtrC>& names = m_impl->getAudioEncoderNames();
+ QString str;
+
+ for (TInt index = 0; index < names.Count(); index++) {
+ str = QString((QChar*)names[index].Ptr(), names[index].Length());
+ m_codecs.append(str);
+ }
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+void QXARecordSession::initContainersList()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ RETURN_IF_m_impl_IS_NULL;
+
+ m_containers.clear();
+ m_containersDesc.clear();
+
+ const RArray<TPtrC>& names = m_impl->getContainerNames();
+ const RArray<TPtrC>& descs = m_impl->getContainerDescs();
+ QString str;
+
+ for (TInt32 index = 0; index < names.Count(); index++) {
+ str = QString((QChar*)names[index].Ptr(), names[index].Length());
+ m_containers.append(str);
+ str = QString((QChar*)descs[index].Ptr(), descs[index].Length());
+ m_containersDesc.append(str);
+ }
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+bool QXARecordSession::setEncoderSettingsToImpl()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+
+ RETURN_s_IF_m_impl_IS_NULL(false);
+
+ m_impl->resetEncoderAttributes();
+
+ /* m_containerMimeType is alredy validated in ::setContainerMimeType() */
+ QString tempStr = m_containerMimeType;
+ TPtrC16 tempPtr(reinterpret_cast<const TUint16 *>(tempStr.utf16()));
+ m_impl->setContainerType(tempPtr);
+
+ /* vaidate and assign codec */
+ if (m_audioencodersettings.codec().isNull() || m_audioencodersettings.codec().isEmpty()) {
+ m_audioencodersettings.setCodec(m_appliedaudioencodersettings.codec());
+ }
+ tempStr = m_audioencodersettings.codec();
+ if (m_codecs.indexOf(tempStr) >= 0) {
+ tempPtr.Set(reinterpret_cast<const TUint16*>(tempStr.utf16()));
+ /* We already did validation above, so function always returns true */
+ m_impl->setCodec(tempPtr);
+ }
+ else {
+ QT_TRACE2("Codec selected is :", m_audioencodersettings.codec());
+ emit error(QMediaRecorder::FormatError, tr("Invalid codec"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid codec\"));");
+ return false;
+ }
+
+ /* Validate and set bitrate only if encoding mode is other than quality encoding and container type is not wav*/
+ if ((m_audioencodersettings.encodingMode() != QtMultimediaKit::ConstantQualityEncoding) &&
+ (m_containerMimeType.compare("audio/wav") != 0)) {
+ m_impl->setBitRate(m_audioencodersettings.bitRate());
+ m_audioencodersettings.setBitRate(m_impl->getBitRate());
+ }
+
+ if (m_audioencodersettings.channelCount() == -1) {
+ m_impl->setOptimalChannelCount();
+ }
+ else {
+ m_impl->setChannels(m_audioencodersettings.channelCount());
+ m_audioencodersettings.setChannelCount(m_impl->getChannels());
+ }
+
+ switch (m_audioencodersettings.encodingMode()) {
+ case QtMultimediaKit::ConstantQualityEncoding: {
+ switch (m_audioencodersettings.quality()) {
+ case QtMultimediaKit::VeryLowQuality:
+ m_impl->setVeryLowQuality();
+ m_audioencodersettings.setBitRate(m_impl->getBitRate());
+ break;
+ case QtMultimediaKit::LowQuality:
+ m_impl->setLowQuality();
+ m_audioencodersettings.setBitRate(m_impl->getBitRate());
+ break;
+ case QtMultimediaKit::NormalQuality:
+ m_impl->setNormalQuality();
+ m_audioencodersettings.setBitRate(m_impl->getBitRate());
+ break;
+ case QtMultimediaKit::HighQuality:
+ m_impl->setHighQuality();
+ m_audioencodersettings.setBitRate(m_impl->getBitRate());
+ break;
+ case QtMultimediaKit::VeryHighQuality:
+ m_impl->setVeryHighQuality();
+ m_audioencodersettings.setBitRate(m_impl->getBitRate());
+ break;
+ default:
+ break;
+ }; /* end of switch (m_audioencodersettings.quality())*/
+ }
+ break;
+ case QtMultimediaKit::ConstantBitRateEncoding: {
+ TInt32 status = m_impl->setCBRMode();
+ if (status == KErrNotSupported) {
+ emit error(QMediaRecorder::FormatError, tr("Invalid encoding mode setting"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid encoding mode setting\"));");
+ return false;
+ }
+ else if (status != KErrNone) {
+ emit error(QMediaRecorder::ResourceError, tr("Internal error"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Internal error\"));");
+ return false;
+ }
+ }
+ break;
+ case QtMultimediaKit::AverageBitRateEncoding: {
+ TInt32 status = m_impl->setVBRMode();
+ if (status == KErrNotSupported) {
+ emit error(QMediaRecorder::FormatError, tr("Invalid encoding mode setting"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid encoding mode setting\"));");
+ return false;
+ }
+ else if (status != KErrNone) {
+ emit error(QMediaRecorder::ResourceError, tr("Internal error"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Internal error\"));");
+ return false;
+ }
+ }
+ break;
+ case QtMultimediaKit::TwoPassEncoding:
+ // fall through
+ default: {
+ emit error(QMediaRecorder::FormatError, tr("Invalid encoding mode setting"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::FormatError, tr(\"Invalid encoding mode setting\"));");
+ return false;
+ }
+ }; /* switch (m_audioencodersettings.encodingMode()) */
+
+ if (m_audioencodersettings.sampleRate() == -1) {
+ m_impl->setOptimalSampleRate();
+ }
+ else {
+ m_impl->setSampleRate(m_audioencodersettings.sampleRate());
+ m_audioencodersettings.setSampleRate(m_impl->getSampleRate());
+ }
+ m_appliedaudioencodersettings = m_audioencodersettings;
+
+ QT_TRACE_FUNCTION_EXIT;
+ return true;
+}
+
+bool QXARecordSession::setURIToImpl()
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ if (m_URItoImplSet)
+ return true;
+
+ /* If m_outputLocation is null, set a default location */
+ if (m_outputLocation.isEmpty()) {
+ QDir outputDir(QDir::rootPath());
+
+ int lastImage = 0;
+ int fileCount = 0;
+ foreach(QString fileName, outputDir.entryList(QStringList() << "recordclip_*")) {
+ int imgNumber = fileName.mid(5, fileName.size() - 9).toInt();
+ lastImage = qMax(lastImage, imgNumber);
+ if (outputDir.exists(fileName))
+ fileCount += 1;
+ }
+ lastImage += fileCount;
+ m_outputLocation = QUrl(QDir::toNativeSeparators(outputDir.canonicalPath() + QString("/recordclip_%1").arg(lastImage + 1, 4, 10, QLatin1Char('0'))));
+ }
+
+ QString newUrlStr = (QUrl::fromUserInput(m_outputLocation.toString())).toString();
+ // append file prefix if required
+ if (newUrlStr.lastIndexOf('.') == -1) {
+ QString fileExtension;
+ if ((m_containerMimeType.compare("audio/wav")) == KErrNone) {
+ fileExtension = QString(".wav");
+ }
+ else if ((m_containerMimeType.compare("audio/amr")) == KErrNone) {
+ fileExtension = QString(".amr");
+ }
+ else if ((m_containerMimeType.compare("audio/mpeg")) == KErrNone) {
+ fileExtension = QString(".mp4");
+ }
+ newUrlStr.append(fileExtension);
+ }
+
+ QT_TRACE2("Filename selected is :", newUrlStr);
+ TPtrC16 tempPtr(reinterpret_cast<const TUint16 *>(newUrlStr.utf16()));
+ if (m_impl->setURI(tempPtr) != 0) {
+ emit error(QMediaRecorder::ResourceError, tr("Generic error"));
+ SIGNAL_EMIT_TRACE1("emit error(QMediaRecorder::ResourceError, tr(\"Generic error\"))");
+ return false;
+ }
+ m_URItoImplSet = true;
+ m_outputLocation = QUrl(newUrlStr);
+ QT_TRACE_FUNCTION_EXIT;
+ return true;
+}
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.h b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.h
new file mode 100644
index 000000000..cabe58fc9
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/qxarecordsession.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** 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$
+** 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 QXARECORDSESSION_H
+#define QXARECORDSESSION_H
+
+#include <QObject>
+#include <QUrl>
+#include "qmediarecorder.h"
+#include "xarecordsessioncommon.h"
+
+QT_USE_NAMESPACE
+
+class XARecordSessionImpl;
+
+/*
+ * This is a backend class for all QXXXControl objects.
+ * This class contains actual implementation of recording functionality
+ * from the control object's perspective.
+ */
+
+
+class QXARecordSession : public QObject,
+ public XARecordObserver
+{
+Q_OBJECT
+
+public:
+ QXARecordSession(QObject *parent);
+ virtual ~QXARecordSession();
+
+ /* For QMediaRecorderControl begin */
+ QUrl outputLocation();
+ bool setOutputLocation(const QUrl &location);
+ QMediaRecorder::State state();
+ qint64 duration();
+ void applySettings();
+
+ void record();
+ void pause();
+ void stop();
+
+ void cbDurationChanged(TInt64 new_pos);
+ void cbAvailableAudioInputsChanged();
+ void cbRecordingStarted();
+ void cbRecordingStopped();
+ /* For QMediaRecorderControl end */
+
+ /* For QAudioEndpointSelector begin */
+ QList<QString> availableEndpoints();
+ QString endpointDescription(const QString &name);
+ QString defaultEndpoint();
+ QString activeEndpoint();
+ void setActiveEndpoint(const QString &name);
+ /* For QAudioEndpointSelector end */
+
+ /* For QAudioEncoderControl begin */
+ QStringList supportedAudioCodecs();
+ QString codecDescription(const QString &codecName);
+ QList<int> supportedSampleRates(
+ const QAudioEncoderSettings &settings,
+ bool *continuous);
+ QAudioEncoderSettings audioSettings();
+ void setAudioSettings(const QAudioEncoderSettings &settings);
+ QStringList supportedEncodingOptions(const QString &codec);
+ QVariant encodingOption(const QString &codec, const QString &name);
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value);
+ /* For QAudioEncoderControl end */
+
+ /* For QMediaContainerControl begin */
+ QStringList supportedContainers();
+ QString containerMimeType();
+ void setContainerMimeType(const QString &formatMimeType);
+ QString containerDescription(const QString &formatMimeType);
+ /* For QMediaContainerControl end */
+
+Q_SIGNALS:
+ void stateChanged(QMediaRecorder::State state);
+ void durationChanged(qint64 duration);
+ void error(int error, const QString &errorString);
+ void activeEndpointChanged(const QString& name);
+ void availableAudioInputsChanged();
+
+private:
+ void setRecorderState(QMediaRecorder::State state);
+ void initCodecsList();
+ void initContainersList();
+ bool setEncoderSettingsToImpl();
+ bool setURIToImpl();
+
+private:
+ /* Own */
+ XARecordSessionImpl *m_impl;
+ QUrl m_outputLocation;
+ bool m_URItoImplSet;
+ QMediaRecorder::State m_state;
+ QMediaRecorder::State m_previousState;
+ QStringList m_codecs;
+ QAudioEncoderSettings m_audioencodersettings;
+ QAudioEncoderSettings m_appliedaudioencodersettings;
+ QStringList m_containers;
+ QStringList m_containersDesc;
+ QString m_containerMimeType;
+};
+
+#endif /* QXARECORDSESSION_H */
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessioncommon.h b/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessioncommon.h
new file mode 100644
index 000000000..cdf8c1886
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessioncommon.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** 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$
+** 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 XARECORDSESSIONCOMMON_H
+#define XARECORDSESSIONCOMMON_H
+
+#include <e32base.h>
+#include "xacommon.h"
+
+#define MAX_NUMBER_INTERFACES 20
+#define MAX_NUMBER_INPUT_DEVICES 10
+#define MAX_NUMBER_ENCODERS 10
+
+//const TInt32 KExtErr = (TInt32)(-2147483648);
+const TInt32 KExtErr = -32768;
+const TInt32 KExtErrUnspecifiedCodecForContainer = (KExtErr+1);
+const TInt32 KExtErrUnsupportedCodecForContainer = (KExtErr+2);
+const TInt32 KExtErrUnsupportedURISuffixForContainer = (KExtErr+3);
+
+class XARecordObserver
+{
+public:
+ virtual void cbDurationChanged(TInt64 new_pos) = 0;
+ virtual void cbAvailableAudioInputsChanged() = 0;
+ virtual void cbRecordingStarted() = 0;
+ virtual void cbRecordingStopped() = 0;
+};
+
+#endif /* XARECORDSESSIONCOMMON_H */
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.cpp b/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.cpp
new file mode 100644
index 000000000..d18c781d4
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.cpp
@@ -0,0 +1,1378 @@
+/****************************************************************************
+ **
+ ** 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$
+ ** 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 "xarecordsessionimpl.h"
+#include "xarecordsessioncommon.h"
+_LIT8(K8WAVMIMETYPE, "audio/x-wav");
+/*
+ * These codec names are not part of AL. Hence we need to define names here.
+ * */
+_LIT(KAUDIOCODECPCM, "pcm");
+_LIT(KAUDIOCODECAMR, "amr");
+_LIT(KAUDIOCODECAAC, "aac");
+_LIT(KCONTAINERWAV, "audio/wav");
+_LIT(KCONTAINERWAVDESC, "wav container");
+_LIT(KCONTAINERAMR, "audio/amr");
+_LIT(KCONTAINERAMRDESC, "amr File format");
+_LIT(KCONTAINERMP4, "audio/mpeg");
+_LIT(KCONTAINERMP4DESC, "mpeg container");
+
+const TUint KRecordPosUpdatePeriod = 1000;
+const TUint KMilliToHz = 1000;
+const TUint KMaxNameLength = 256;
+
+/* Local functions for callback registation */
+void cbXAObjectItf(
+ XAObjectItf caller,
+ const void *pContext,
+ XAuint32 event,
+ XAresult result,
+ XAuint32 param,
+ void *pInterface);
+
+void cbXARecordItf(
+ XARecordItf caller,
+ void *pContext,
+ XAuint32 event);
+
+void cbXAAvailableAudioInputsChanged(
+ XAAudioIODeviceCapabilitiesItf caller,
+ void *pContext,
+ XAuint32 deviceID,
+ XAint32 numInputs,
+ XAboolean isNew);
+
+XARecordSessionImpl::XARecordSessionImpl(XARecordObserver &parent) :
+ m_Parent(parent),
+ m_EOEngine(NULL),
+ m_MORecorder(NULL),
+ m_RecordItf(NULL),
+ m_AudioEncItf(NULL),
+ m_WAVMime(NULL),
+ m_URIName(NULL),
+ m_InputDeviceId(0),
+ m_ContainerType(0),
+ m_BitRate(0),
+ m_RateControl(0),
+ m_ChannelsOut(1),
+ m_SampleRate(0),
+ m_AudioIODevCapsItf(NULL),
+ m_AudioInputDeviceNames(NULL),
+ m_DefaultAudioInputDeviceNames(NULL),
+ m_AudioEncCapsItf(NULL)
+{
+ TRACE_FUNCTION_ENTRY_EXIT;
+}
+
+XARecordSessionImpl::~XARecordSessionImpl()
+{
+ TRACE_FUNCTION_ENTRY;
+
+ if (m_MORecorder)
+ (*m_MORecorder)->Destroy(m_MORecorder);
+
+ if (m_EOEngine)
+ (*m_EOEngine)->Destroy(m_EOEngine);
+
+ delete m_WAVMime;
+ delete m_URIName;
+
+ m_InputDeviceIDs.Close();
+ if (m_AudioInputDeviceNames)
+ m_AudioInputDeviceNames->Reset();
+ delete m_AudioInputDeviceNames;
+ m_DefaultInputDeviceIDs.Close();
+ if (m_DefaultAudioInputDeviceNames)
+ m_DefaultAudioInputDeviceNames->Reset();
+ delete m_DefaultAudioInputDeviceNames;
+ m_EncoderIds.Close();
+ m_EncoderNames.Close();
+ m_ContainerNames.Close();
+ m_ContainerDescs.Close();
+
+ TRACE_FUNCTION_EXIT;
+}
+
+TInt32 XARecordSessionImpl::postConstruct()
+{
+ TRACE_FUNCTION_ENTRY;
+
+ XAEngineOption engineOption[] = { (XAuint32) XA_ENGINEOPTION_THREADSAFE, (XAuint32) XA_BOOLEAN_TRUE};
+
+ /* Create and realize Engine object */
+ TRACE_LOG(_L("XARecordSessionImpl: Creating Engine..."));
+ XAresult xa_result = xaCreateEngine(&m_EOEngine, 1, engineOption, 0, NULL, NULL);
+ TInt returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+ TRACE_LOG(_L("XARecordSessionImpl: Realizing engine..."));
+ xa_result = (*m_EOEngine)->Realize(m_EOEngine, XA_BOOLEAN_FALSE);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+ TRACE_LOG(_L("XARecordSessionImpl: OMX AL Engine realized successfully"));
+
+ XAEngineItf engineItf;
+ xa_result = (*m_EOEngine)->GetInterface(m_EOEngine, XA_IID_ENGINE, (void**) &engineItf);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ xa_result = (*m_EOEngine)->GetInterface(m_EOEngine,
+ XA_IID_AUDIOIODEVICECAPABILITIES,
+ (void**) &m_AudioIODevCapsItf);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+ xa_result = (*m_AudioIODevCapsItf)->RegisterAvailableAudioInputsChangedCallback(
+ m_AudioIODevCapsItf,
+ cbXAAvailableAudioInputsChanged,
+ (void*)this);
+
+ xa_result = (*m_EOEngine)->GetInterface(
+ m_EOEngine,
+ XA_IID_AUDIOENCODERCAPABILITIES,
+ (void**) &m_AudioEncCapsItf);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ TRAP(returnValue, m_WAVMime = HBufC8::NewL(K8WAVMIMETYPE().Length() + 1));
+ RET_ERR_IF_ERR(returnValue);
+ TPtr8 ptr = m_WAVMime->Des();
+ ptr = K8WAVMIMETYPE(); // copy uri name into local variable
+ ptr.PtrZ(); // append zero terminator to end of URI
+
+ m_AudioInputDeviceNames = new CDesC16ArrayFlat(2);
+ if (m_AudioInputDeviceNames == NULL)
+ returnValue = KErrNoMemory;
+ RET_ERR_IF_ERR(returnValue);
+
+ m_DefaultAudioInputDeviceNames = new CDesC16ArrayFlat(2);
+ if (m_DefaultAudioInputDeviceNames == NULL)
+ returnValue = KErrNoMemory;
+ RET_ERR_IF_ERR(returnValue);
+
+ returnValue = initContainersList();
+ RET_ERR_IF_ERR(returnValue);
+ returnValue = initAudioEncodersList();
+ RET_ERR_IF_ERR(returnValue);
+ returnValue = initAudioInputDevicesList();
+ RET_ERR_IF_ERR(returnValue);
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+TInt32 XARecordSessionImpl::setURI(const TDesC &aURI)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ /* This function will only get called when aURI is different than m_URIName
+ * and only when recorder is in stopped state.
+ * If the recorder object was created for a different URI (than aURI), we
+ * need to tear it down here.
+ */
+ if (m_MORecorder) {
+ (*m_MORecorder)->Destroy(m_MORecorder);
+ m_MORecorder = NULL;
+ m_RecordItf = NULL;
+ }
+
+ delete m_URIName;
+ m_URIName = NULL;
+ TRAPD(returnValue, m_URIName = HBufC8::NewL(aURI.Length()+1));
+ RET_ERR_IF_ERR(returnValue);
+
+ TPtr8 uriPtr = m_URIName->Des();
+ /* copy uri name into local variable */
+ uriPtr.Copy(aURI);
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+TInt32 XARecordSessionImpl::record()
+{
+ TRACE_FUNCTION_ENTRY;
+
+ TInt32 returnValue(KErrGeneral);
+ if (!m_MORecorder || !m_RecordItf) {
+ TRACE_LOG(_L("XARecordSessionImpl::Record: MORecorder/RecordItf is not created"));
+ returnValue = createMediaRecorderObject();
+ RET_ERR_IF_ERR(returnValue);
+
+ returnValue = setEncoderSettingsToMediaRecorder();
+ RET_ERR_IF_ERR(returnValue);
+ }
+
+ XAuint32 state;
+ XAresult xa_result = (*m_RecordItf)->GetRecordState(m_RecordItf, &state);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ if ((state == XA_RECORDSTATE_STOPPED)
+ || (state == XA_RECORDSTATE_PAUSED)) {
+ TRACE_LOG(_L("XARecordSessionImpl::Record: Setting State to Recording..."));
+ xa_result = (*m_RecordItf)->SetRecordState(m_RecordItf, XA_RECORDSTATE_RECORDING);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+ TRACE_LOG(_L("XARecordSessionImpl::Record: SetState to Recording"));
+ }
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+TInt32 XARecordSessionImpl::pause()
+{
+ TRACE_FUNCTION_ENTRY;
+
+ TInt32 returnValue(KErrGeneral);
+ if (!m_MORecorder || !m_RecordItf) {
+ TRACE_LOG(_L("XARecordSessionImpl::Record: MORecorder/RecordItf is not created"));
+ return returnValue;
+ }
+
+ XAuint32 state;
+ XAresult xa_result = (*m_RecordItf)->GetRecordState(m_RecordItf, &state);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ if ((state == XA_RECORDSTATE_STOPPED)
+ || (state == XA_RECORDSTATE_RECORDING)) {
+ TRACE_LOG(_L("XARecordSessionImpl::Record: Setting State to Paused..."));
+ xa_result = (*m_RecordItf)->SetRecordState(m_RecordItf, XA_RECORDSTATE_PAUSED);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+ TRACE_LOG(_L("XARecordSessionImpl::Record: SetState to Paused"));
+ }
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+TInt32 XARecordSessionImpl::stop()
+{
+ TRACE_FUNCTION_ENTRY;
+
+ TInt32 returnValue(KErrGeneral);
+ if (!m_MORecorder || !m_RecordItf) {
+ TRACE_LOG(_L("XARecordSessionImpl::Record: MORecorder/RecordItf is not created"));
+ return returnValue;
+ }
+
+ XAuint32 state;
+ XAresult xa_result = (*m_RecordItf)->GetRecordState(m_RecordItf, &state);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ if ((state == XA_RECORDSTATE_PAUSED)
+ || (state == XA_RECORDSTATE_RECORDING)) {
+ TRACE_LOG(_L("XARecordSessionImpl::Record: Setting State to Stopped..."));
+ xa_result = (*m_RecordItf)->SetRecordState(m_RecordItf, XA_RECORDSTATE_STOPPED);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+ TRACE_LOG(_L("XARecordSessionImpl::Record: SetState to Stopped"));
+ }
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+TInt32 XARecordSessionImpl::duration(TInt64 &aDur)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ TInt32 returnValue(KErrGeneral);
+
+ if (!m_MORecorder || !m_RecordItf) {
+ TRACE_LOG(_L("XARecordSessionImpl::Duration: MORecoder/RecordItf is not created"));
+ return returnValue;
+ }
+
+ XAmillisecond milliSec;
+ XAresult xa_result = (*m_RecordItf)->GetPosition(m_RecordItf, &milliSec);
+ returnValue = mapError(xa_result, ETrue);
+ if (returnValue == KErrNone)
+ aDur = (TInt64)milliSec;
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+void XARecordSessionImpl::cbMediaRecorder(
+ XAObjectItf /*caller*/,
+ const void */*pContext*/,
+ XAuint32 event,
+ XAresult result,
+ XAuint32 /*param*/,
+ void */*pInterface*/)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ switch (event) {
+ case XA_OBJECT_EVENT_RESOURCES_LOST:
+ m_Parent.cbRecordingStopped();
+ break;
+ case XA_OBJECT_EVENT_RUNTIME_ERROR: {
+ switch (result) {
+ case XA_RESULT_RESOURCE_LOST:
+ m_Parent.cbRecordingStopped();
+ break;
+ default:
+ break;
+ }; /* of switch (result) */
+ }
+ default:
+ break;
+ } /* of switch (event) */
+
+ TRACE_FUNCTION_EXIT;
+}
+
+void XARecordSessionImpl::cbRecordItf(
+ XARecordItf /*caller*/,
+ void */*pContext*/,
+ XAuint32 event)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ switch(event) {
+ case XA_RECORDEVENT_HEADATLIMIT:
+ TRACE_LOG(_L("XA_RECORDEVENT_HEADATLIMIT"));
+ break;
+ case XA_RECORDEVENT_HEADATMARKER:
+ TRACE_LOG(_L("XA_RECORDEVENT_HEADATMARKER"));
+ break;
+ case XA_RECORDEVENT_HEADATNEWPOS: {
+ TInt32 returnValue;
+ XAresult xa_result;
+ XAmillisecond milliSec;
+ xa_result = (*m_RecordItf)->GetPosition(m_RecordItf, &milliSec);
+ returnValue = mapError(xa_result, ETrue);
+ if (returnValue == KErrNone)
+ m_Parent.cbDurationChanged((TInt64) milliSec);
+ }
+ break;
+ case XA_RECORDEVENT_HEADMOVING:
+ TRACE_LOG(_L("XA_RECORDEVENT_HEADMOVING"));
+ m_Parent.cbRecordingStarted();
+ break;
+ case XA_RECORDEVENT_HEADSTALLED:
+ TRACE_LOG(_L("XA_RECORDEVENT_HEADSTALLED"));
+ break;
+ case XA_RECORDEVENT_BUFFER_FULL:
+ TRACE_LOG(_L("XA_RECORDEVENT_BUFFER_FULL"));
+ break;
+ default:
+ TRACE_LOG(_L("UNKNOWN RECORDEVENT EVENT"));
+ break;
+ } /* of switch(event) */
+
+ TRACE_FUNCTION_EXIT;
+}
+
+/* For QAudioEndpointSelector begin */
+void XARecordSessionImpl::getAudioInputDeviceNames(RArray<TPtrC> &aArray)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ for (TInt index = 0; index < m_AudioInputDeviceNames->MdcaCount(); index++)
+ aArray.Append(m_AudioInputDeviceNames->MdcaPoint(index));
+ TRACE_FUNCTION_EXIT;
+}
+
+TInt32 XARecordSessionImpl::defaultAudioInputDevice(TPtrC &endPoint)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ TInt32 err(KErrGeneral);
+ if (m_DefaultAudioInputDeviceNames->MdcaCount() >= 0) {
+ endPoint.Set(m_DefaultAudioInputDeviceNames->MdcaPoint(0));
+ err = KErrNone;
+ }
+
+ TRACE_FUNCTION_EXIT;
+ return err;
+}
+
+TInt32 XARecordSessionImpl::activeAudioInputDevice(TPtrC &endPoint)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ TInt32 returnValue(KErrGeneral);
+ TBool found(EFalse);
+ TInt index = 0;
+ for (; index < m_InputDeviceIDs.Count(); index++) {
+ if (m_InputDeviceIDs[index] == m_InputDeviceId) {
+ found = ETrue;
+ break;
+ }
+ }
+
+ /* Comparing found with ETrue produces linker error */
+ if (found == true) {
+ endPoint.Set(m_AudioInputDeviceNames->MdcaPoint(index));
+ returnValue = KErrNone;
+ }
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+TBool XARecordSessionImpl::setAudioInputDevice(const TDesC &aDevice)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ /* validate if we can set input device id */
+ TBool found(EFalse);
+ m_InputDeviceId = 0;
+ TInt index = 0;
+ for (; index < m_AudioInputDeviceNames->MdcaCount(); index++) {
+ if (m_AudioInputDeviceNames->MdcaPoint(index).Compare(aDevice) == 0) {
+ found = ETrue;
+ break;
+ }
+ }
+ if (found == true) {
+ m_InputDeviceId = m_InputDeviceIDs[index];
+ }
+
+ TRACE_FUNCTION_EXIT;
+ return found;
+}
+
+void XARecordSessionImpl::cbAvailableAudioInputsChanged(
+ XAAudioIODeviceCapabilitiesItf /*caller*/,
+ void */*pContext*/,
+ XAuint32 deviceID,
+ XAint32 /*numInputs*/,
+ XAboolean isNew)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ /* If a new device is added into the system, append it to available input list */
+ if (isNew == XA_BOOLEAN_TRUE) {
+ XAAudioInputDescriptor audioInputDescriptor;
+ m_InputDeviceIDs.Append(deviceID);
+
+ XAresult xa_result = (*m_AudioIODevCapsItf)->QueryAudioInputCapabilities(
+ m_AudioIODevCapsItf,
+ deviceID,
+ &audioInputDescriptor);
+
+ if ((mapError(xa_result, ETrue)) == KErrNone) {
+ TUint8* inDevNamePtr = audioInputDescriptor.deviceName;
+ TUint8* tempPtr = audioInputDescriptor.deviceName;
+ TInt32 inDevNameLength = 0;
+ while (*tempPtr++)
+ inDevNameLength++;
+ TPtrC8 ptr(inDevNamePtr, inDevNameLength);
+ /* Convert 8 bit to 16 bit */
+ TBuf16<KMaxNameLength> name;
+ name.Copy(ptr);
+ /* Using TRAP with returnValue results in compiler error */
+ TRAP_IGNORE(m_AudioInputDeviceNames->AppendL(name));
+ }
+ }
+ else {
+ /* an available device has been removed from the the system, remove it from
+ * available input list and also default list */
+ TBool found(EFalse);
+ TInt index = 0;
+ for (; index < m_InputDeviceIDs.Count(); index++) {
+ if (deviceID == m_InputDeviceIDs[index]) {
+ found = ETrue;
+ break;
+ }
+ }
+ if (found == true) {
+ m_InputDeviceIDs.Remove(index);
+ m_AudioInputDeviceNames->Delete(index);
+ }
+ if (deviceID == m_InputDeviceId)
+ m_InputDeviceId = 0;
+
+ found = EFalse;
+ for (index = 0; index < m_DefaultInputDeviceIDs.Count(); index++) {
+ if (deviceID == m_DefaultInputDeviceIDs[index]) {
+ found = ETrue;
+ break;
+ }
+ }
+ if (found == true) {
+ m_DefaultInputDeviceIDs.Remove(index);
+ m_DefaultAudioInputDeviceNames->Delete(index);
+ }
+ }
+ m_Parent.cbAvailableAudioInputsChanged();
+
+ TRACE_FUNCTION_EXIT;
+}
+/* For QAudioEndpointSelector end */
+
+/* For QAudioEncoderControl begin */
+const RArray<TPtrC>& XARecordSessionImpl::getAudioEncoderNames()
+{
+ TRACE_FUNCTION_ENTRY_EXIT;
+ return m_EncoderNames;
+}
+
+TInt32 XARecordSessionImpl::getSampleRates(
+ const TDesC& aEncoder,
+ RArray<TInt32> &aSampleRates,
+ TBool &aIsContinuous)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ aSampleRates.Reset();
+ aIsContinuous = EFalse;
+
+ XAuint32 encoderId = 0;
+ TBool found(EFalse);
+ for (TInt index = 0; index < m_EncoderIds.Count(); index++) {
+ if (m_EncoderNames[index].Compare(aEncoder) == 0) {
+ found = ETrue;
+ encoderId = m_EncoderIds[index];
+ break;
+ }
+ }
+
+ TInt32 returnValue(KErrGeneral);
+ if (found == false)
+ return returnValue;
+
+ returnValue = getSampleRatesByAudioCodecID(encoderId, aSampleRates);
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+TInt32 XARecordSessionImpl::getBitrates(
+ const TDesC& aEncoder,
+ RArray<TUint32> &aBitrates,
+ TBool& aContinuous)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ aBitrates.Reset();
+
+ XAuint32 encoderId = 0;
+ TBool found(EFalse);
+ for (TInt index = 0; index < m_EncoderIds.Count(); index++) {
+ if (m_EncoderNames[index].Compare(aEncoder) == 0) {
+ found = ETrue;
+ encoderId = m_EncoderIds[index];
+ break;
+ }
+ }
+
+ TInt32 returnValue(KErrNotSupported);
+ XAboolean cont;
+ if (found == false)
+ return returnValue;
+
+ returnValue = getBitratesByAudioCodecID(encoderId, aBitrates, cont);
+ aContinuous = cont;
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+/* For QAudioEncoderControl end */
+
+/* For QMediaContainerControl begin */
+const RArray<TPtrC>& XARecordSessionImpl::getContainerNames()
+{
+ TRACE_FUNCTION_ENTRY_EXIT;
+ return m_ContainerNames;
+}
+
+const RArray<TPtrC>& XARecordSessionImpl::getContainerDescs()
+{
+ TRACE_FUNCTION_ENTRY_EXIT;
+ return m_ContainerDescs;
+}
+
+/* For QMediaContainerControl end */
+
+void XARecordSessionImpl::resetEncoderAttributes()
+{
+ m_ContainerType = 0;
+ m_AudioEncoderId = 0;
+ m_ProfileSetting = 0;
+ m_BitRate = 0;
+ m_ChannelsOut = 1;
+ m_SampleRate = 0;
+ m_RateControl = 0;
+}
+
+void XARecordSessionImpl::setContainerType(const TDesC &aURI)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ if (aURI.Compare(KCONTAINERWAV()) == 0)
+ m_ContainerType = XA_CONTAINERTYPE_WAV;
+ else if (aURI.Compare(KCONTAINERAMR()) == 0)
+ m_ContainerType = XA_CONTAINERTYPE_AMR;
+ else if (aURI.Compare(KCONTAINERMP4()) == 0)
+ m_ContainerType = XA_CONTAINERTYPE_MP4;
+
+ TRACE_FUNCTION_EXIT;
+}
+
+TBool XARecordSessionImpl::setCodec(const TDesC &aCodec)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ TBool returnValue(EFalse);
+ if (aCodec.Compare(KAUDIOCODECPCM()) == 0) {
+ m_AudioEncoderId = XA_AUDIOCODEC_PCM;
+ m_ProfileSetting = XA_AUDIOPROFILE_PCM;
+ returnValue = ETrue;
+ }
+ else if (aCodec.Compare(KAUDIOCODECAAC()) == 0) {
+ m_AudioEncoderId = XA_AUDIOCODEC_AAC;
+ m_ProfileSetting = XA_AUDIOPROFILE_AAC_AAC;
+ returnValue = ETrue;
+ }
+ else if (aCodec.Compare(KAUDIOCODECAMR()) == 0) {
+ m_AudioEncoderId = XA_AUDIOCODEC_AMR;
+ m_ProfileSetting = XA_AUDIOPROFILE_AMR;
+ returnValue = ETrue;
+ }
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+TUint32 XARecordSessionImpl::getBitRate()
+{
+ return m_BitRate;
+}
+
+void XARecordSessionImpl::setBitRate(TUint32 aBitRate)
+{
+ TRACE_FUNCTION_ENTRY;
+ RArray<TUint32> bitrates;
+ XAboolean isContinuous;
+ m_BitRate = 0;
+ if (getBitratesByAudioCodecID(m_AudioEncoderId, bitrates, isContinuous) == KErrNone) {
+ bitrates.SortUnsigned();
+ TInt loopIndex(0);
+ while (loopIndex < bitrates.Count()
+ && aBitRate <= bitrates[loopIndex]) {
+ m_BitRate = bitrates[loopIndex];
+ loopIndex++;
+ }
+ bitrates.Close();
+ }
+ TRACE_LOG((_L("BitRate[%d]"), m_BitRate));
+ TRACE_FUNCTION_EXIT;
+}
+
+TUint32 XARecordSessionImpl::getChannels()
+{
+ return m_ChannelsOut;
+}
+
+void XARecordSessionImpl::setChannels(TUint32 aChannels)
+{
+ TRACE_FUNCTION_ENTRY;
+ switch (m_AudioEncoderId) {
+ case XA_AUDIOCODEC_PCM:
+ case XA_AUDIOCODEC_AAC:
+ m_ChannelsOut = 1;
+ if ((aChannels >= 1) && (aChannels <= 2))
+ m_ChannelsOut = aChannels;
+ break;
+ case XA_AUDIOCODEC_AMR:
+ m_ChannelsOut = 1;
+ break;
+ default:
+ break;
+ }
+ TRACE_LOG((_L("ChannelCount[%d]"), m_ChannelsOut));
+ TRACE_FUNCTION_EXIT;
+}
+
+void XARecordSessionImpl::setOptimalChannelCount()
+{
+ TRACE_FUNCTION_ENTRY;
+ m_ChannelsOut = 1;
+ TRACE_FUNCTION_EXIT;
+}
+
+TUint32 XARecordSessionImpl::getSampleRate()
+{
+ return m_SampleRate;
+}
+
+void XARecordSessionImpl::setSampleRate(TUint32 aSampleRate)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ m_SampleRate = 0;
+
+ RArray<TInt32> samplerates;
+ if (getSampleRatesByAudioCodecID(m_AudioEncoderId, samplerates) == KErrNone) {
+ samplerates.SortUnsigned();
+ TInt loopIndex(0);
+ while (loopIndex < samplerates.Count()) {
+ m_SampleRate = samplerates[loopIndex];
+ if (samplerates[loopIndex] > aSampleRate)
+ break;
+ loopIndex++;
+ }
+ samplerates.Close();
+ }
+
+ /* convert Hz to MilliHz */
+ m_SampleRate *= KMilliToHz;
+ TRACE_LOG((_L("SampleRate[%d]"), m_SampleRate));
+ TRACE_FUNCTION_EXIT;
+}
+
+void XARecordSessionImpl::setOptimalSampleRate()
+{
+ TRACE_FUNCTION_ENTRY;
+ m_SampleRate = 0;
+
+ if (m_AudioEncoderId == XA_AUDIOCODEC_AAC) {
+ m_SampleRate = 32000 * KMilliToHz;
+ }
+ else if (m_AudioEncoderId == XA_AUDIOCODEC_AMR) {
+ m_SampleRate = 8000 * KMilliToHz;
+ }
+ else {
+ RArray<TInt32> sampleRates;
+ TInt res = getSampleRatesByAudioCodecID(m_AudioEncoderId, sampleRates);
+ if ((res == KErrNone) && (sampleRates.Count() > 0)) {
+ /* Sort the array and pick the middle range sample rate */
+ sampleRates.SortUnsigned();
+ m_SampleRate = sampleRates[sampleRates.Count() / 2] * KMilliToHz;
+ }
+ sampleRates.Close();
+ }
+
+ TRACE_FUNCTION_EXIT;
+}
+
+TInt32 XARecordSessionImpl::setCBRMode()
+{
+ TRACE_FUNCTION_ENTRY;
+
+ m_RateControl = XA_RATECONTROLMODE_CONSTANTBITRATE;
+
+ TRACE_FUNCTION_EXIT;
+ return KErrNone;
+}
+
+TInt32 XARecordSessionImpl::setVBRMode()
+{
+ TRACE_FUNCTION_ENTRY;
+
+ m_RateControl = XA_RATECONTROLMODE_VARIABLEBITRATE;
+
+ TRACE_FUNCTION_EXIT;
+ return KErrNone;
+}
+
+void XARecordSessionImpl::setVeryLowQuality()
+{
+ /* Set to very low quality encoder preset */
+ RArray<TUint32> bitrates;
+ XAboolean continuous;
+ TInt res = getBitratesByAudioCodecID(m_AudioEncoderId, bitrates, continuous);
+ if ((res == KErrNone) && (bitrates.Count() > 0)) {
+ /* Sort the array and pick the lowest bit rate */
+ bitrates.SortUnsigned();
+ m_BitRate = bitrates[0];
+ }
+ bitrates.Close();
+}
+
+void XARecordSessionImpl::setLowQuality()
+{
+ /* Set to low quality encoder preset */
+ RArray<TUint32> bitrates;
+ XAboolean continuous;
+ TInt res = getBitratesByAudioCodecID(m_AudioEncoderId, bitrates, continuous);
+ if ((res == KErrNone) && (bitrates.Count() > 0)) {
+ /* Sort the array and pick the low quality bit rate */
+ bitrates.SortUnsigned();
+ if (continuous == XA_BOOLEAN_FALSE)
+ m_BitRate = bitrates[bitrates.Count() / 4];
+ else
+ m_BitRate = (bitrates[1] - bitrates[0]) / 4;
+ }
+ bitrates.Close();
+}
+
+void XARecordSessionImpl::setNormalQuality()
+{
+ /* Set to normal quality encoder preset */
+ RArray<TUint32> bitrates;
+ XAboolean continuous;
+ TInt res = getBitratesByAudioCodecID(m_AudioEncoderId, bitrates, continuous);
+ if ((res == KErrNone) && (bitrates.Count() > 0)) {
+ /* Sort the array and pick the middle range bit rate */
+ bitrates.SortUnsigned();
+ if (continuous == XA_BOOLEAN_FALSE)
+ m_BitRate = bitrates[bitrates.Count() / 2];
+ else
+ m_BitRate = (bitrates[1] - bitrates[0]) / 2;
+ }
+ bitrates.Close();
+}
+
+void XARecordSessionImpl::setHighQuality()
+{
+ /* Set to high quality encoder preset */
+ RArray<TUint32> bitrates;
+ XAboolean continuous;
+ TInt res = getBitratesByAudioCodecID(m_AudioEncoderId, bitrates, continuous);
+ if ((res == KErrNone) && (bitrates.Count() > 0)) {
+ /* Sort the array and pick the high quality bit rate */
+ bitrates.SortUnsigned();
+ if (continuous == XA_BOOLEAN_FALSE)
+ m_BitRate = bitrates[bitrates.Count() * 3 / 4];
+ else
+ m_BitRate = (bitrates[1] - bitrates[0]) * 3 / 4;
+ }
+ bitrates.Close();
+}
+
+void XARecordSessionImpl::setVeryHighQuality()
+{
+ /* Set to very high quality encoder preset */
+ RArray<TUint32> bitrates;
+ XAboolean continuous;
+ TInt res = getBitratesByAudioCodecID(m_AudioEncoderId, bitrates, continuous);
+ if ((res == KErrNone) && (bitrates.Count() > 0)) {
+ /* Sort the array and pick the highest bit rate */
+ bitrates.SortUnsigned();
+ m_BitRate = bitrates[bitrates.Count() - 1];
+ }
+ bitrates.Close();
+}
+
+/* Internal function */
+TInt32 XARecordSessionImpl::createMediaRecorderObject()
+{
+ TRACE_FUNCTION_ENTRY;
+
+ if (!m_EOEngine)
+ return KErrGeneral;
+
+ TInt32 returnValue(KErrNone);
+
+ TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject"));
+ if (!m_MORecorder && !m_RecordItf) {
+
+ /* Setup the data source */
+ m_LocatorMic.locatorType = XA_DATALOCATOR_IODEVICE;
+ m_LocatorMic.deviceType = XA_IODEVICE_AUDIOINPUT;
+ m_LocatorMic.deviceID = m_InputDeviceId;
+ m_LocatorMic.device = NULL;
+ m_DataSource.pLocator = (void*) &m_LocatorMic;
+ m_DataSource.pFormat = NULL;
+
+ /* Setup the data sink structure */
+ m_Uri.locatorType = XA_DATALOCATOR_URI;
+ /* append zero terminator to end of URI */
+ TPtr8 uriPtr = m_URIName->Des();
+ m_Uri.URI = (XAchar*) uriPtr.PtrZ();
+ m_Mime.formatType = XA_DATAFORMAT_MIME;
+ m_Mime.containerType = m_ContainerType;
+ TPtr8 mimeTypePtr(m_WAVMime->Des());
+ m_Mime.mimeType = (XAchar*) mimeTypePtr.Ptr();
+ m_DataSink.pLocator = (void*) &m_Uri;
+ m_DataSink.pFormat = (void*) &m_Mime;
+
+ /* Init arrays required[] and iidArray[] */
+ XAboolean required[MAX_NUMBER_INTERFACES];
+ XAInterfaceID iidArray[MAX_NUMBER_INTERFACES];
+ for (TInt32 i = 0; i < MAX_NUMBER_INTERFACES; i++) {
+ required[i] = XA_BOOLEAN_FALSE;
+ iidArray[i] = XA_IID_NULL;
+ }
+ XAuint32 noOfInterfaces = 0;
+ required[noOfInterfaces] = XA_BOOLEAN_FALSE;
+ iidArray[noOfInterfaces] = XA_IID_RECORD;
+ noOfInterfaces++;
+ required[noOfInterfaces] = XA_BOOLEAN_FALSE;
+ iidArray[noOfInterfaces] = XA_IID_AUDIOENCODER;
+ noOfInterfaces++;
+
+ XAEngineItf engineItf;
+ XAresult xa_result = (*m_EOEngine)->GetInterface(m_EOEngine, XA_IID_ENGINE, (void**) &engineItf);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: Create Media Recorder..."));
+
+ /* Create recorder with NULL for a the image/video source, since this is for audio-only recording */
+ xa_result = (*engineItf)->CreateMediaRecorder(
+ engineItf,
+ &m_MORecorder,
+ &m_DataSource,
+ NULL,
+ &m_DataSink,
+ noOfInterfaces,
+ iidArray,
+ required);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: Realize Media Recorder..."));
+ xa_result = (*m_MORecorder)->Realize(m_MORecorder, XA_BOOLEAN_FALSE);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: Register Callback on recorder..."));
+ xa_result = (*m_MORecorder)->RegisterCallback(m_MORecorder, cbXAObjectItf, (void*) this);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: Getting Record Interface..."));
+ xa_result = (*m_MORecorder)->GetInterface(m_MORecorder, XA_IID_RECORD, &m_RecordItf);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: Registering Callback on record Interface..."));
+ xa_result = (*m_RecordItf)->RegisterCallback(m_RecordItf, cbXARecordItf, (void*) this);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: SetPositionUpdatePeriod on record Interface..."));
+ xa_result = (*m_RecordItf)->SetPositionUpdatePeriod(m_RecordItf, (XAmillisecond)KRecordPosUpdatePeriod);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: SetCallbackEventsMask on record Interface..."));
+ xa_result = (*m_RecordItf)->SetCallbackEventsMask(m_RecordItf, XA_RECORDEVENT_HEADATNEWPOS |
+ XA_RECORDEVENT_HEADMOVING |
+ XA_RECORDEVENT_HEADSTALLED);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ TRACE_LOG(_L("XARecordSessionImpl::CreateMediaRecorderObject: Getting Audio Encoder Interface..."));
+ xa_result = (*m_MORecorder)->GetInterface(m_MORecorder, XA_IID_AUDIOENCODER, &m_AudioEncItf);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+ }
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+TInt32 XARecordSessionImpl::mapError(XAresult xa_err, TBool debPrn)
+{
+ TInt32 returnValue(KErrGeneral);
+ switch (xa_err) {
+ case XA_RESULT_SUCCESS:
+ returnValue = KErrNone;
+ break;
+ case XA_RESULT_PRECONDITIONS_VIOLATED:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_PRECONDITIONS_VIOLATED"));
+ break;
+ case XA_RESULT_PARAMETER_INVALID:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_PARAMETER_INVALID"));
+ break;
+ case XA_RESULT_MEMORY_FAILURE:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_MEMORY_FAILURE"));
+ break;
+ case XA_RESULT_RESOURCE_ERROR:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_RESOURCE_ERROR"));
+ break;
+ case XA_RESULT_RESOURCE_LOST:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_RESOURCE_LOST"));
+ break;
+ case XA_RESULT_IO_ERROR:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_IO_ERROR"));
+ break;
+ case XA_RESULT_BUFFER_INSUFFICIENT:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_BUFFER_INSUFFICIENT"));
+ break;
+ case XA_RESULT_CONTENT_CORRUPTED:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_CONTENT_CORRUPTED"));
+ break;
+ case XA_RESULT_CONTENT_UNSUPPORTED:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_CONTENT_UNSUPPORTED"));
+ break;
+ case XA_RESULT_CONTENT_NOT_FOUND:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_CONTENT_NOT_FOUND"));
+ break;
+ case XA_RESULT_PERMISSION_DENIED:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_PERMISSION_DENIED"));
+ break;
+ case XA_RESULT_FEATURE_UNSUPPORTED:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_FEATURE_UNSUPPORTED"));
+ break;
+ case XA_RESULT_INTERNAL_ERROR:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_INTERNAL_ERROR"));
+ break;
+ case XA_RESULT_UNKNOWN_ERROR:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_UNKNOWN_ERROR"));
+ break;
+ case XA_RESULT_OPERATION_ABORTED:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_OPERATION_ABORTED"));
+ break;
+ case XA_RESULT_CONTROL_LOST:
+ if (debPrn)
+ TRACE_LOG(_L("XA_RESULT_CONTROL_LOST"));
+ break;
+ default:
+ if (debPrn)
+ TRACE_LOG(_L("Unknown Error!!!"));
+ break;
+ }
+ return returnValue;
+}
+
+TInt32 XARecordSessionImpl::initContainersList()
+{
+ TRACE_FUNCTION_ENTRY;
+
+ m_ContainerNames.Reset();
+ m_ContainerDescs.Reset();
+
+ m_ContainerNames.Append(KCONTAINERWAV());
+ m_ContainerNames.Append(KCONTAINERAMR());
+ m_ContainerNames.Append(KCONTAINERMP4());
+
+ m_ContainerDescs.Append(KCONTAINERWAVDESC());
+ m_ContainerDescs.Append(KCONTAINERAMRDESC());
+ m_ContainerDescs.Append(KCONTAINERMP4DESC());
+
+ TRACE_FUNCTION_EXIT;
+ return KErrNone;
+}
+
+TInt32 XARecordSessionImpl::initAudioEncodersList()
+{
+ TRACE_FUNCTION_ENTRY;
+
+ m_EncoderIds.Reset();
+ m_EncoderNames.Reset();
+
+ XAuint32 encoderIds[MAX_NUMBER_ENCODERS];
+
+ for (TInt index = 0; index < MAX_NUMBER_ENCODERS; index++)
+ encoderIds[index] = 0;
+
+ XAuint32 numEncoders = MAX_NUMBER_ENCODERS;
+ XAresult xa_result = (*m_AudioEncCapsItf)->GetAudioEncoders(
+ m_AudioEncCapsItf,
+ &numEncoders,
+ encoderIds);
+ TInt32 returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ for (TInt index = 0; index < numEncoders; index++) {
+ m_EncoderIds.Append(encoderIds[index]);
+ switch (encoderIds[index]) {
+ case XA_AUDIOCODEC_PCM:
+ m_EncoderNames.Append(KAUDIOCODECPCM());
+ break;
+ case XA_AUDIOCODEC_AMR:
+ m_EncoderNames.Append(KAUDIOCODECAMR());
+ break;
+ case XA_AUDIOCODEC_AAC:
+ m_EncoderNames.Append(KAUDIOCODECAAC());
+ break;
+ default:
+ break;
+ };
+ }
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+TInt32 XARecordSessionImpl::initAudioInputDevicesList()
+{
+ TRACE_FUNCTION_ENTRY;
+
+ m_InputDeviceIDs.Reset();
+
+ XAuint32 deviceIds[MAX_NUMBER_INPUT_DEVICES];
+ for (TInt index = 0; index < MAX_NUMBER_INPUT_DEVICES; index++)
+ deviceIds[index] = 0;
+
+ XAint32 numInputs = MAX_NUMBER_INPUT_DEVICES;
+ XAresult xa_result = (*m_AudioIODevCapsItf)->GetAvailableAudioInputs(
+ m_AudioIODevCapsItf,
+ &numInputs,
+ deviceIds);
+ TInt32 returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ XAAudioInputDescriptor audioInputDescriptor;
+ for (TInt index = 0; index < numInputs; index++) {
+ xa_result = (*m_AudioIODevCapsItf)->QueryAudioInputCapabilities(
+ m_AudioIODevCapsItf,
+ deviceIds[index],
+ &audioInputDescriptor);
+ returnValue = mapError(xa_result, ETrue);
+ if (returnValue != KErrNone)
+ continue;
+
+ TUint8 * inDevNamePtr = audioInputDescriptor.deviceName;
+ TUint8 * tempPtr = audioInputDescriptor.deviceName;
+ TInt32 inDevNameLength = 0;
+ while (*tempPtr++)
+ inDevNameLength++;
+ TPtrC8 ptr(inDevNamePtr, inDevNameLength);
+ /* Convert 8 bit to 16 bit */
+ TBuf16<KMaxNameLength> name;
+ name.Copy(ptr);
+ /* Using TRAP with returnValue results in compiler error */
+ TRAPD(err2, m_AudioInputDeviceNames->AppendL(name));
+ returnValue = err2;
+ if (returnValue != KErrNone)
+ continue;
+ m_InputDeviceIDs.Append(deviceIds[index]);
+ }
+
+ numInputs = MAX_NUMBER_INPUT_DEVICES;
+ for (TInt index = 0; index < MAX_NUMBER_INPUT_DEVICES; index++)
+ deviceIds[index] = 0;
+ xa_result = (*m_AudioIODevCapsItf)->GetDefaultAudioDevices(
+ m_AudioIODevCapsItf,
+ XA_DEFAULTDEVICEID_AUDIOINPUT,
+ &numInputs,
+ deviceIds);
+ returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ for (TInt index = 0; index < numInputs; index++) {
+ xa_result = (*m_AudioIODevCapsItf)->QueryAudioInputCapabilities(
+ m_AudioIODevCapsItf,
+ deviceIds[index],
+ &audioInputDescriptor);
+ returnValue = mapError(xa_result, ETrue);
+ if (returnValue != KErrNone)
+ continue;
+ TUint8* inDevNamePtr = audioInputDescriptor.deviceName;
+ TUint8* tempPtr = audioInputDescriptor.deviceName;
+ TInt32 inDevNameLength = 0;
+ while (*tempPtr++)
+ inDevNameLength++;
+ TPtrC8 ptr(inDevNamePtr, inDevNameLength);
+ /* Convert 8 bit to 16 bit */
+ TBuf16<KMaxNameLength> name;
+ name.Copy(ptr);
+ /* Using TRAP with returnValue results in compiler error */
+ TRAPD(err2, m_DefaultAudioInputDeviceNames->AppendL(name));
+ returnValue = err2;
+ if (returnValue != KErrNone)
+ continue;
+ m_DefaultInputDeviceIDs.Append(deviceIds[index]);
+ m_InputDeviceId = deviceIds[index];
+ }
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+TInt32 XARecordSessionImpl::setEncoderSettingsToMediaRecorder()
+{
+ TRACE_FUNCTION_EXIT;
+
+ /* Get current settings */
+ XAAudioEncoderSettings settings;
+ XAresult xa_result = (*m_AudioEncItf)->GetEncoderSettings(
+ m_AudioEncItf,
+ &settings);
+ TInt32 returnValue = mapError(xa_result, ETrue);
+
+ settings.encoderId = m_AudioEncoderId;
+ settings.channelsOut = m_ChannelsOut;
+ if ((m_SampleRate != 0) && (m_SampleRate != 0xffffffff))
+ settings.sampleRate = m_SampleRate;
+ if ((m_BitRate != 0) && (m_BitRate != 0xffffffff))
+ settings.bitRate = m_BitRate;
+ if (m_RateControl != 0)
+ settings.rateControl = m_RateControl;
+ settings.profileSetting = m_ProfileSetting;
+ xa_result = (*m_AudioEncItf)->SetEncoderSettings(
+ m_AudioEncItf,
+ &settings);
+ returnValue = mapError(xa_result, ETrue);
+
+ TRACE_FUNCTION_EXIT;
+ return returnValue;
+}
+
+TInt32 XARecordSessionImpl::getBitratesByAudioCodecID(
+ XAuint32 encoderId,
+ RArray<TUint32> &aBitrates,
+ XAboolean& aContinuous)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ if (!m_AudioEncCapsItf)
+ return KErrGeneral;
+
+ XAuint32 numCaps = 0;
+ XAAudioCodecDescriptor codecDesc;
+ XAresult xa_result = (*m_AudioEncCapsItf)->GetAudioEncoderCapabilities(
+ m_AudioEncCapsItf,
+ encoderId,
+ &numCaps,
+ &codecDesc);
+ TInt32 returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+ aContinuous = codecDesc.isBitrateRangeContinuous;
+ /* TODO What do we do if we have more than one caps?? */
+ if (codecDesc.isBitrateRangeContinuous == XA_BOOLEAN_TRUE) {
+ aBitrates.Append(codecDesc.minBitRate);
+ aBitrates.Append(codecDesc.maxBitRate);
+ }
+ else {
+ XAuint32 numBrSupported = codecDesc.numBitratesSupported;
+ XAuint32 * pBitratesSupported(NULL);
+ pBitratesSupported = codecDesc.pBitratesSupported;
+ TInt32 index = 0;
+ for (index = 0; index < numBrSupported; index++)
+ aBitrates.Append(*(pBitratesSupported + index));
+ }
+
+ TRACE_FUNCTION_ENTRY;
+ return returnValue;
+}
+
+TInt32 XARecordSessionImpl::getSampleRatesByAudioCodecID(XAuint32 encoderId,
+ RArray<TInt32> &aSampleRates)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ if (!m_AudioEncCapsItf)
+ return KErrGeneral;
+
+ XAuint32 numCaps = 0;
+ XAAudioCodecDescriptor codecDesc;
+ XAresult xa_result = (*m_AudioEncCapsItf)->GetAudioEncoderCapabilities(
+ m_AudioEncCapsItf,
+ encoderId,
+ &numCaps,
+ &codecDesc);
+ TInt returnValue = mapError(xa_result, ETrue);
+ RET_ERR_IF_ERR(returnValue);
+
+ /* TODO What do we do if we have more than one caps?? */
+ if (codecDesc.isFreqRangeContinuous == XA_BOOLEAN_TRUE) {
+ aSampleRates.Append(codecDesc.minSampleRate / KMilliToHz);
+ aSampleRates.Append(codecDesc.maxSampleRate / KMilliToHz);
+ }
+ else {
+ XAuint32 numSRSupported = codecDesc.numSampleRatesSupported;
+ XAmilliHertz *pSampleRatesSupported(NULL);
+ pSampleRatesSupported = codecDesc.pSampleRatesSupported;
+ for (TInt index = 0; index < numSRSupported; index++)
+ aSampleRates.Append((*(pSampleRatesSupported + index)) / KMilliToHz);
+ }
+
+ TRACE_FUNCTION_ENTRY;
+ return returnValue;
+}
+
+/* Local function implementation */
+void cbXAObjectItf(
+ XAObjectItf caller,
+ const void *pContext,
+ XAuint32 event,
+ XAresult result,
+ XAuint32 param,
+ void *pInterface)
+{
+ if (pContext) {
+ ((XARecordSessionImpl*)pContext)->cbMediaRecorder(
+ caller,
+ pContext,
+ event,
+ result,
+ param,
+ pInterface);
+ }
+}
+
+void cbXARecordItf(
+ XARecordItf caller,
+ void *pContext,
+ XAuint32 event)
+{
+ if (pContext) {
+ ((XARecordSessionImpl*)pContext)->cbRecordItf(
+ caller,
+ pContext,
+ event);
+ }
+}
+
+void cbXAAvailableAudioInputsChanged(
+ XAAudioIODeviceCapabilitiesItf caller,
+ void * pContext,
+ XAuint32 deviceID,
+ XAint32 numInputs,
+ XAboolean isNew)
+{
+ if (pContext) {
+ ((XARecordSessionImpl*)pContext)->cbAvailableAudioInputsChanged(
+ caller,
+ pContext,
+ deviceID,
+ numInputs,
+ isNew);
+ }
+}
diff --git a/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.h b/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.h
new file mode 100644
index 000000000..81e4ac763
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/mediarecorder/xarecordsessionimpl.h
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 XARECORDSESSIONIMPL_H
+#define XARECORDSESSIONIMPL_H
+
+#include <OpenMAXAL.h>
+#include <badesca.h>
+
+
+class XARecordObserver;
+class XARecordSessionImpl
+{
+public:
+ XARecordSessionImpl(XARecordObserver &parent);
+ ~XARecordSessionImpl();
+ TInt32 postConstruct();
+
+ /* For QMediaRecorderControl begin */
+ TInt32 setURI(const TDesC &aURI);
+ TInt32 record();
+ TInt32 pause();
+ TInt32 stop();
+ TInt32 duration(TInt64 &aDur);
+ /* For QMediaRecorderControl end */
+
+ void cbMediaRecorder(XAObjectItf caller,
+ const void *pContext,
+ XAuint32 event,
+ XAresult result,
+ XAuint32 param,
+ void *pInterface);
+ void cbRecordItf(XARecordItf caller,
+ void *pContext,
+ XAuint32 event);
+
+ /* For QAudioEndpointSelector begin */
+ void getAudioInputDeviceNames(RArray<TPtrC> &aArray);
+ TInt32 defaultAudioInputDevice(TPtrC &endPoint);
+ TInt32 activeAudioInputDevice(TPtrC &endPoint);
+ TBool setAudioInputDevice(const TDesC &aDevice);
+ void cbAvailableAudioInputsChanged(XAAudioIODeviceCapabilitiesItf caller,
+ void *pContext,
+ XAuint32 deviceID,
+ XAint32 numInputs,
+ XAboolean isNew);
+ /* For QAudioEndpointSelector end */
+
+ /* For QAudioEncoderControl begin */
+ const RArray<TPtrC>& getAudioEncoderNames();
+ TInt32 getSampleRates(const TDesC &aEncoder,
+ RArray<TInt32> &aSampleRates,
+ TBool &aIsContinuous);
+ TInt32 getBitrates(const TDesC &aEncoder,
+ RArray<TUint32> &aBitrates,
+ TBool& aContinuous);
+ /* For QAudioEncoderControl end */
+
+ /* For QMediaContainerControl begin */
+ const RArray<TPtrC>& getContainerNames();
+ const RArray<TPtrC>& getContainerDescs();
+ /* For QMediaContainerControl end */
+
+ void resetEncoderAttributes();
+ void setContainerType(const TDesC &aURI);
+ TBool setCodec(const TDesC &aURI);
+ TUint32 getBitRate();
+ void setBitRate(TUint32 aBitRate);
+ TUint32 getChannels();
+ void setChannels(TUint32 aChannels);
+ void setOptimalChannelCount();
+ TUint32 getSampleRate();
+ void setSampleRate(TUint32 aSampleRate);
+ void setOptimalSampleRate();
+ TInt32 setCBRMode();
+ TInt32 setVBRMode();
+ void setVeryLowQuality();
+ void setLowQuality();
+ void setNormalQuality();
+ void setHighQuality();
+ void setVeryHighQuality();
+
+private:
+ TInt32 createMediaRecorderObject();
+ TInt32 mapError(XAresult xa_err,
+ TBool debPrn);
+ TInt32 initContainersList();
+ TInt32 initAudioEncodersList();
+ TInt32 initAudioInputDevicesList();
+ TInt32 setEncoderSettingsToMediaRecorder();
+ TInt32 getBitratesByAudioCodecID(XAuint32 encoderId,
+ RArray<TUint32> &aBitrates,
+ XAboolean& aContinuous);
+ TInt32 getSampleRatesByAudioCodecID(XAuint32 encoderId,
+ RArray<TInt32> &aSampleRates);
+
+
+private:
+ XARecordObserver &m_Parent;
+ XAObjectItf m_EOEngine;
+ XAObjectItf m_MORecorder;
+ XARecordItf m_RecordItf;
+ XAAudioEncoderItf m_AudioEncItf;
+ /* Audio Source */
+ XADataSource m_DataSource;
+ XADataLocator_IODevice m_LocatorMic;
+ XADataFormat_MIME m_Mime;
+ XADataLocator_URI m_Uri;
+ /*Audio Sink*/
+ XADataSink m_DataSink;
+ HBufC8 *m_WAVMime;
+
+ /* Set by client*/
+ HBufC8 *m_URIName;
+ XAuint32 m_AudioEncoderId;
+ XAuint32 m_InputDeviceId;
+ XAuint32 m_ContainerType;
+ XAuint32 m_BitRate;
+ XAuint32 m_RateControl;
+ XAuint32 m_ProfileSetting;
+ XAuint32 m_ChannelsOut;
+ XAuint32 m_SampleRate;
+
+ /* For QAudioEndpointSelector begin */
+ XAAudioIODeviceCapabilitiesItf m_AudioIODevCapsItf;
+ RArray<TUint32> m_InputDeviceIDs;
+ CDesC16ArrayFlat *m_AudioInputDeviceNames;
+ RArray<TUint32> m_DefaultInputDeviceIDs;
+ CDesC16ArrayFlat *m_DefaultAudioInputDeviceNames;
+ /* For QAudioEndpointSelector end */
+
+ /* For QAudioEncoderControl begin */
+ XAAudioEncoderCapabilitiesItf m_AudioEncCapsItf;
+ RArray<XAuint32> m_EncoderIds;
+ RArray<TPtrC> m_EncoderNames;
+ RArray<TPtrC> m_ContainerNames;
+ RArray<TPtrC> m_ContainerDescs;
+ /* For QAudioEncoderControl begin */
+};
+
+#endif /* XARECORDSESSIONIMPL_H */
diff --git a/src/plugins/symbian/openmaxal/openmaxal.pro b/src/plugins/symbian/openmaxal/openmaxal.pro
new file mode 100644
index 000000000..0565536a4
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/openmaxal.pro
@@ -0,0 +1,58 @@
+TEMPLATE = lib
+
+CONFIG += plugin
+TARGET = $$qtLibraryTarget(qtmultimediakit_openmaxalengine)
+PLUGIN_TYPE = mediaservice
+include (../../../../common.pri)
+qtAddLibrary(QtMultimediaKit)
+
+#includes here so that all defines are added here also
+include(mediaplayer/mediaplayer.pri)
+include(mediarecorder/mediarecorder.pri)
+include(radiotuner/radiotuner.pri)
+
+DEPENDPATH += .
+
+HEADERS += qxamediaserviceproviderplugin.h \
+ qxacommon.h \
+ xacommon.h
+
+SOURCES += qxamediaserviceproviderplugin.cpp
+
+# Input parameters for the generated bld.inf file
+# -----------------------------------------------
+SYMBIAN_PLATFORMS = DEFAULT
+
+# Input parameters for the generated mmp file
+# -------------------------------------------
+load(data_caging_paths)
+TARGET.UID3 = 0x10207CA1
+TARGET.CAPABILITY = ALL -TCB
+TARGET.EPOCALLOWDLLDATA = 1
+MMP_RULES += EXPORTUNFROZEN
+
+# Macros controlling debug traces
+#DEFINES += PROFILE_TIME
+#DEFINES += PROFILE_RAM_USAGE
+#DEFINES += PROFILE_HEAP_USAGE
+#DEFINES += PLUGIN_QT_TRACE_ENABLED
+#DEFINES += PLUGIN_QT_SIGNAL_EMIT_TRACE_ENABLED
+#DEFINES += PLUGIN_SYMBIAN_TRACE_ENABLED
+
+INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE
+INCLUDEPATH += /epoc32/include/platform/mw/khronos
+
+
+# Input parameters for qmake to make the dll a qt plugin
+pluginDep.sources = $${TARGET}.dll
+pluginDep.path = $${QT_PLUGINS_BASE_DIR}/$${PLUGIN_TYPE}
+DEPLOYMENT += pluginDep
+
+LIBS += \
+ -lQtMultimediaKit \
+ -lopenmaxal
+
+# check for PROFILE_RAM_USAGE
+contains(DEFINES, PROFILE_RAM_USAGE) {
+ LIBS += -lhal
+}
diff --git a/src/plugins/symbian/openmaxal/qxacommon.h b/src/plugins/symbian/openmaxal/qxacommon.h
new file mode 100644
index 000000000..f19a75d1c
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/qxacommon.h
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** 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$
+** 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 QXACOMMON_H
+#define QXACOMMON_H
+
+#if defined(PLUGIN_QT_TRACE_ENABLED) \
+ || defined(PLUGIN_QT_SIGNAL_EMIT_TRACE_ENABLED) \
+ || defined(PROFILE_TIME) \
+ || defined(PROFILE_RAM_USAGE) \
+ || defined(PROFILE_HEAP_USAGE)
+# include <QDebug>
+#endif /* PLUGIN_QT_TRACE_ENABLED */
+
+#ifdef PROFILE_RAM_USAGE
+# include <hal.h>
+#endif
+
+
+#ifdef PLUGIN_QT_TRACE_ENABLED
+# define QT_TRACE_FUNCTION_ENTRY qDebug() << __PRETTY_FUNCTION__ << ">"
+# define QT_TRACE_FUNCTION_EXIT qDebug() << __PRETTY_FUNCTION__ << "<"
+# define QT_TRACE_FUNCTION_ENTRY_EXIT qDebug() << __PRETTY_FUNCTION__ << "><"
+# define QT_TRACE1(v1) qDebug() << v1
+# define QT_TRACE2(v1, v2) qDebug() << v1 << v2
+#else
+# define QT_TRACE_FUNCTION_ENTRY
+# define QT_TRACE_FUNCTION_EXIT
+# define QT_TRACE_FUNCTION_ENTRY_EXIT
+# define QT_TRACE1(v1)
+# define QT_TRACE2(v1, v2)
+#endif /*PLUGIN_QT_TRACE_ENABLED*/
+
+#ifdef PLUGIN_QT_SIGNAL_EMIT_TRACE_ENABLED
+# define SIGNAL_EMIT_TRACE1(v1) qDebug() << __PRETTY_FUNCTION__ << v1
+#else
+# define SIGNAL_EMIT_TRACE1(v1)
+#endif /*PLUGIN_QT_SIGNAL_EMIT_TRACE_ENABLED*/
+
+#ifdef PROFILE_TIME_ELAPSED
+# define TAG_TIME_PROFILING_BEGIN \
+ TTime beginProfilingTime; \
+ beginProfilingTime.HomeTime()
+
+# define TAG_TIME_PROFILING_END \
+ TTime endProfilingTime; \
+ endProfilingTime.HomeTime(); \
+ TTimeIntervalMicroSeconds diffInMicroSecs = endProfilingTime.MicroSecondsFrom(beginProfilingTime)
+
+# define QT_PRINT_TO_CONSOLE_TIME_DIFF \
+ qDebug() << "VPROFILEDAT: " << __PRETTY_FUNCTION__ << ": Time taken " << diffInMicroSecs.Int64() << " microseconds"
+#else /* Empty macros */
+# define TAG_TIME_PROFILING_BEGIN
+# define TAG_TIME_PROFILING_END
+# define QT_PRINT_TO_CONSOLE_TIME_DIFF
+#endif /*PROFILE_TIME_ELAPSED*/
+
+#ifdef PROFILE_RAM_USAGE
+# define TAG_RAM_PROFILING_BEGIN \
+ TInt beginProfilingRAM; \
+ TInt err1 = HAL::Get(HALData::EMemoryRAMFree, beginProfilingRAM)
+
+# define TAG_RAM_PROFILING_END \
+ TInt endProfilingRAM; \
+ TInt err2 = HAL::Get(HALData::EMemoryRAMFree, endProfilingRAM)
+
+# define QT_PRINT_TO_CONSOLE_RAM_DIFF \
+ if ((err1 == KErrNone) && (err2 == KErrNone)) \
+ { \
+ TInt diffRAM = (beginProfilingRAM - endProfilingRAM); \
+ if ( diffRAM > 0 ) \
+ { \
+ qDebug() << "VPROFILEDAT: " << __PRETTY_FUNCTION__ << ": " << diffRAM << " bytes of RAM used"; \
+ } \
+ else \
+ { \
+ qDebug() << "VPROFILEDAT: " << __PRETTY_FUNCTION__ << ": " << -(diffRAM) << " bytes of RAM freed"; \
+ } \
+ } \
+ else \
+ { \
+ qDebug() << "VPROFILEDAT: " << __PRETTY_FUNCTION__ << "Error1[" << err1 << "] Error2[" << err2; \
+ }
+
+#else /* Empty macros */
+# define TAG_RAM_PROFILING_BEGIN
+# define TAG_RAM_PROFILING_END
+# define QT_PRINT_TO_CONSOLE_RAM_DIFF
+#endif /*PROFILE_RAM_USAGE*/
+
+#ifdef PROFILE_HEAP_USAGE
+# define TAG_DEFAULT_HEAP_PROFILING_BEGIN \
+ TInt beginProfilingHEAPBiggestBlock; \
+ TInt beginProfilingHEAP = User::Available(beginProfilingHEAPBiggestBlock) \
+
+# define TAG_DEFAULT_HEAP_PROFILING_END \
+ TInt endProfilingHEAPBiggestBlock; \
+ TInt endProfilingHEAP = User::Available(endProfilingHEAPBiggestBlock) \
+
+# define QT_PRINT_TO_CONSOLE_HEAP_DIFF \
+ TInt diffHEAP = beginProfilingHEAP - endProfilingHEAP; \
+ if ( diffHEAP > 0 ) \
+ { \
+ qDebug() << "VPROFILEDAT: " << __PRETTY_FUNCTION__ << ": " << diffHEAP << " bytes in default HEAP used"; \
+ } \
+ else \
+ { \
+ qDebug() << "VPROFILEDAT: " << __PRETTY_FUNCTION__ << ": " << -(diffHEAP) << " bytes in default HEAP freed"; \
+ }
+#else /* Empty macros */
+# define TAG_DEFAULT_HEAP_PROFILING_BEGIN
+# define TAG_DEFAULT_HEAP_PROFILING_END
+# define QT_PRINT_TO_CONSOLE_HEAP_DIFF
+#endif /*PROFILE_HEAP_USAGE*/
+
+/* This macro checks p pointer for null. If it is, returns value 's' from
+ * function immediately.
+ */
+#define RET_s_IF_p_IS_NULL(p, s) \
+ if (p == NULL) { \
+ return s; \
+ }
+
+/* This macro checks p pointer for null. If it is, returns from function
+ * immediately.
+ */
+#define RET_IF_p_IS_NULL(p) \
+ if (p == NULL) { \
+ return; \
+ }
+
+/* This macro checks p pointer for null. If it is, emits an error signal
+ * error(QMediaPlayer::ResourceError, tr("Resource Error"));
+ * and returns value 's' from function immediately.
+ */
+#define RET_s_IF_p_IS_NULL_EMIT_PLAYER_RESOURCE_ERROR(p, s) \
+ if (p == NULL) { \
+ emit error(QMediaPlayer::ResourceError, tr("Resource Error")); \
+ SIGNAL_EMIT_TRACE1("emit error(QMediaPlayer::ResourceError, tr(\"Resource Error\"))"); \
+ return s; \
+ }
+
+/* This macro checks p pointer for null. If it is, emits an error signal
+ * error(QMediaPlayer::ResourceError, tr("Resource Error"));
+ * and returns from function immediately.
+ */
+#define RET_IF_p_IS_NULL_EMIT_PLAYER_RESOURCE_ERROR(p) \
+ if (p == NULL) { \
+ emit error(QMediaPlayer::ResourceError, tr("Resource Error")); \
+ SIGNAL_EMIT_TRACE1("emit error(QMediaPlayer::ResourceError, tr(\"Resource Error\"))"); \
+ return; \
+ }
+
+/* This macro checks p pointer for null. If it is, emits an error signal
+ * error(QMediaPlayer::ResourceError, tr("Resource Error"));
+ * and returns from function immediately.
+ */
+#define RET_IF_ERROR(p) \
+ if (p != KErrNone) { \
+ emit error(QMediaPlayer::ResourceError, tr("Resource Error")); \
+ SIGNAL_EMIT_TRACE1("emit error(QMediaPlayer::ResourceError, tr(\"Resource Error\"))"); \
+ return; \
+ }
+
+#endif /* QXACOMMON_H */
diff --git a/src/plugins/symbian/openmaxal/qxamediaserviceproviderplugin.cpp b/src/plugins/symbian/openmaxal/qxamediaserviceproviderplugin.cpp
new file mode 100644
index 000000000..bfbb4333a
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/qxamediaserviceproviderplugin.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <QString>
+#include "qxamediaserviceproviderplugin.h"
+#include "qxaplaymediaservice.h"
+#include "qxarecordmediaservice.h"
+#include "qxaradiomediaservice.h"
+#include "qxacommon.h"
+
+QStringList QXAMediaServiceProviderPlugin::keys() const
+{
+ return QStringList()
+ << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)
+ << QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE)
+ << QLatin1String(Q_MEDIASERVICE_RADIO);
+}
+
+QMediaService* QXAMediaServiceProviderPlugin::create(QString const& key)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ QMediaService* service = NULL;
+ if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER) ) {
+ service = new QXAPlayMediaService;
+ QT_TRACE1("Created QXAPlayMediaService");
+ }
+ else if (key == QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE)) {
+ service = new QXARecodMediaService;
+ QT_TRACE1("Created QXARecodMediaService");
+ }
+ else if (key == QLatin1String(Q_MEDIASERVICE_RADIO) ) {
+ service = new QXARadioMediaService;
+ QT_TRACE1("Created QXARadioMediaService");
+ }
+ else {
+ QT_TRACE2("unsupported key:", key);
+ }
+ QT_TRACE_FUNCTION_EXIT;
+ return service;
+}
+
+void QXAMediaServiceProviderPlugin::release(QMediaService *service)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ delete service;
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+Q_EXPORT_PLUGIN2(qtmultimediakit_openmaxalengine, QXAMediaServiceProviderPlugin);
diff --git a/src/plugins/symbian/openmaxal/qxamediaserviceproviderplugin.h b/src/plugins/symbian/openmaxal/qxamediaserviceproviderplugin.h
new file mode 100644
index 000000000..6d3530349
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/qxamediaserviceproviderplugin.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** 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 QXAMEDIASERVICEPROVIDERPLUGIN_H
+#define QXAMEDIASERVICEPROVIDERPLUGIN_H
+
+#include <QtCore/qobject.h>
+#include <qmediaserviceprovider.h>
+#include <qmediaserviceproviderplugin.h>
+
+QT_USE_NAMESPACE
+
+class QXAMediaServiceProviderPlugin : public QMediaServiceProviderPlugin
+{
+ Q_OBJECT
+public:
+ QStringList keys() const;
+ QMediaService* create(QString const& key);
+ void release(QMediaService *service);
+};
+
+#endif /* QXAMEDIASERVICEPROVIDERPLUGIN_H */
diff --git a/src/plugins/symbian/openmaxal/radiotuner/qxaradiocontrol.cpp b/src/plugins/symbian/openmaxal/radiotuner/qxaradiocontrol.cpp
new file mode 100644
index 000000000..9666b0410
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/radiotuner/qxaradiocontrol.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qxaradiocontrol.h"
+#include "qxaradiosession.h"
+#include "xaradiosessionimpl.h"
+
+QXARadioControl::QXARadioControl(QXARadioSession *session, QObject *parent)
+:QRadioTunerControl(parent), m_session(session)
+{
+
+ connect(m_session, SIGNAL(stateChanged(QRadioTuner::State)), this, SIGNAL(stateChanged(QRadioTuner::State)));
+
+ connect(m_session, SIGNAL(bandChanged(QRadioTuner::Band)), this, SIGNAL(bandChanged(QRadioTuner::Band)));
+
+ connect(m_session, SIGNAL(frequencyChanged(int)), this, SIGNAL(frequencyChanged(int)));
+
+ connect(m_session, SIGNAL(stereoStatusChanged(bool)), this, SIGNAL(stereoStatusChanged(bool)));
+
+ connect(m_session, SIGNAL(searchingChanged(bool)), this, SIGNAL(searchingChanged(bool)));
+
+ connect(m_session, SIGNAL(signalStrengthChanged(int)), this, SIGNAL(signalStrengthChanged(int)));
+
+ connect(m_session, SIGNAL(volumeChanged(int)), this, SIGNAL(volumeChanged(int)));
+
+ connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool)));
+
+// connect(m_session, SIGNAL(error(int,QString)), this,SIGNAL(error(int,QString)));
+}
+
+QXARadioControl::~QXARadioControl()
+{
+
+}
+
+QtMultimediaKit::AvailabilityError QXARadioControl::availabilityError() const
+{
+ return m_session->availabilityError();
+}
+
+bool QXARadioControl::isAvailable() const
+{
+ return m_session->isAvailable();
+}
+
+QRadioTuner::State QXARadioControl::state() const
+{
+ return m_session->state();
+}
+
+QRadioTuner::Band QXARadioControl::band() const
+{
+ return m_session->band();
+}
+
+void QXARadioControl::setBand(QRadioTuner::Band band)
+{
+ m_session->setBand(band);
+}
+
+bool QXARadioControl::isBandSupported(QRadioTuner::Band band) const
+{
+ return m_session->isBandSupported(band);
+}
+
+int QXARadioControl::frequency() const
+{
+ return m_session->frequency();
+}
+
+int QXARadioControl::frequencyStep(QRadioTuner::Band band) const
+{
+ return m_session->frequencyStep(band);
+}
+
+QPair<int,int> QXARadioControl::frequencyRange(QRadioTuner::Band band) const
+{
+ return m_session->frequencyRange(band);
+}
+
+void QXARadioControl::setFrequency(int freq)
+{
+ m_session->setFrequency(freq);
+}
+
+bool QXARadioControl::isStereo() const
+{
+ return m_session->isStereo();
+}
+
+QRadioTuner::StereoMode QXARadioControl::stereoMode() const
+{
+ return m_session->stereoMode();
+}
+
+void QXARadioControl::setStereoMode(QRadioTuner::StereoMode stereoMode)
+{
+ m_session->setStereoMode(stereoMode);
+}
+
+int QXARadioControl::signalStrength() const
+{
+ return m_session->signalStrength();
+}
+
+int QXARadioControl::volume() const
+{
+ return m_session->volume();
+}
+
+void QXARadioControl::setVolume(int volume)
+{
+ m_session->setVolume(volume);
+}
+
+bool QXARadioControl::isMuted() const
+{
+ return m_session->isMuted();
+}
+
+void QXARadioControl::setMuted(bool muted)
+{
+ m_session->setMuted(muted);
+}
+
+bool QXARadioControl::isSearching() const
+{
+ return m_session->isSearching();
+}
+
+void QXARadioControl::searchForward()
+{
+ m_session->searchForward();
+}
+
+void QXARadioControl::searchBackward()
+{
+ m_session->searchBackward();
+}
+
+void QXARadioControl::cancelSearch()
+{
+ m_session->cancelSearch();
+}
+
+void QXARadioControl::start()
+{
+ m_session->start();
+}
+
+void QXARadioControl::stop()
+{
+ m_session->stop();
+}
+
+QRadioTuner::Error QXARadioControl::error() const
+{
+ return m_session->error();
+}
+
+QString QXARadioControl::errorString() const
+{
+ return m_session->errorString();
+}
diff --git a/src/plugins/symbian/openmaxal/radiotuner/qxaradiocontrol.h b/src/plugins/symbian/openmaxal/radiotuner/qxaradiocontrol.h
new file mode 100644
index 000000000..47d4f827d
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/radiotuner/qxaradiocontrol.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QXARADIOCONTROL_H
+#define QXARADIOCONTROL_H
+
+#include <QObject>
+#include <QRadioTunerControl>
+
+QT_USE_NAMESPACE
+
+class QXARadioSession;
+
+class QXARadioControl : public QRadioTunerControl
+{
+ Q_OBJECT
+
+public:
+ QXARadioControl(QXARadioSession *session, QObject *parent = 0);
+ virtual ~QXARadioControl();
+ QRadioTuner::State state() const;
+
+ QRadioTuner::Band band() const;
+ void setBand(QRadioTuner::Band band);
+ bool isBandSupported(QRadioTuner::Band band) const;
+ int frequency() const;
+ int frequencyStep(QRadioTuner::Band band) const;
+ QPair<int,int> frequencyRange(QRadioTuner::Band band) const;
+ void setFrequency(int freq);
+ bool isStereo() const;
+ QRadioTuner::StereoMode stereoMode() const;
+ void setStereoMode(QRadioTuner::StereoMode stereoMode);
+ int signalStrength() const;
+ int volume() const;
+ void setVolume(int volume);
+ bool isMuted() const;
+ void setMuted(bool muted);
+ bool isSearching() const;
+ void searchForward();
+ void searchBackward();
+ void cancelSearch();
+ bool isValid() const;
+ bool isAvailable() const;
+ QtMultimediaKit::AvailabilityError availabilityError() const;
+ void start();
+ void stop();
+ QRadioTuner::Error error() const;
+ QString errorString() const;
+
+private:
+ QXARadioSession *m_session;
+
+protected:
+ QXARadioControl(QObject* parent = 0);
+};
+
+#endif /* QXARADIOCONTROL_H */
diff --git a/src/plugins/symbian/openmaxal/radiotuner/qxaradiomediaservice.cpp b/src/plugins/symbian/openmaxal/radiotuner/qxaradiomediaservice.cpp
new file mode 100644
index 000000000..f399ef8c5
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/radiotuner/qxaradiomediaservice.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QString>
+
+#include "qxaradiomediaservice.h"
+#include "qxaradiosession.h"
+#include "qxaradiocontrol.h"
+#include <qradiotunercontrol.h>
+
+QXARadioMediaService::QXARadioMediaService(QObject *parent)
+ : QMediaService(parent)
+{
+ m_session = new QXARadioSession(this);
+ m_control = new QXARadioControl(m_session, this);
+}
+
+QXARadioMediaService::~QXARadioMediaService()
+{
+}
+
+QMediaControl* QXARadioMediaService::requestControl(const char *name)
+{
+
+ if (qstrcmp(name, QRadioTunerControl_iid) == 0) {
+ return m_control;
+ }
+ return 0;
+}
+
+void QXARadioMediaService::releaseControl(QMediaControl *control)
+{
+ Q_UNUSED(control)
+}
diff --git a/src/plugins/symbian/openmaxal/radiotuner/qxaradiomediaservice.h b/src/plugins/symbian/openmaxal/radiotuner/qxaradiomediaservice.h
new file mode 100644
index 000000000..7ac014f8f
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/radiotuner/qxaradiomediaservice.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** 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$
+** 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 QXARADIOMEDIASERVICE_H
+#define QXARADIOMEDIASERVICE_H
+
+#include <QtCore/qobject.h>
+#include <qmediaservice.h>
+
+QT_USE_NAMESPACE
+
+class QXARadioSession;
+class QXARadioControl;
+
+class QXARadioMediaService : public QMediaService
+{
+ Q_OBJECT
+public:
+ QXARadioMediaService(QObject *parent = 0);
+ ~QXARadioMediaService();
+ QMediaControl *requestControl(const char *name);
+ void releaseControl( QMediaControl *control);
+private:
+ QXARadioSession *m_session;
+ QXARadioControl *m_control;
+};
+
+#endif /*QXARADIOMEDIASERVICE_H*/
diff --git a/src/plugins/symbian/openmaxal/radiotuner/qxaradiosession.cpp b/src/plugins/symbian/openmaxal/radiotuner/qxaradiosession.cpp
new file mode 100644
index 000000000..6822813c4
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/radiotuner/qxaradiosession.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** 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$
+** 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 <qradiotuner.h>
+#include "qxaradiosession.h"
+#include "xaradiosessionimpl.h"
+#include "qxacommon.h"
+
+QXARadioSession::QXARadioSession(QObject *parent)
+:QObject(parent)
+{
+ QT_TRACE_FUNCTION_ENTRY;
+ m_impl = new XARadioSessionImpl(*this);
+ if (!m_impl) {
+ QT_TRACE1("RadioSession::RadioSession(): ERROR creating RadioSessionImpl...");
+ return;
+ }
+ if (m_impl->PostConstruct() != QRadioTuner::NoError) {
+ QT_TRACE1("RadioSession::RadioSession(): ERROR from RadioSessionImpl::PostContstruct...");
+ delete m_impl;
+ m_impl = NULL;
+ }
+ QT_TRACE_FUNCTION_EXIT;
+}
+
+QXARadioSession::~QXARadioSession()
+{
+ delete m_impl;
+}
+
+QRadioTuner::State QXARadioSession::state() const
+{
+ QRadioTuner::State state = QRadioTuner::StoppedState;
+ if (m_impl)
+ state = m_impl->State();
+ return state;
+ }
+QtMultimediaKit::AvailabilityError QXARadioSession::availabilityError() const
+{
+ QtMultimediaKit::AvailabilityError error = QtMultimediaKit::NoError;
+ if (m_impl)
+ error = m_impl->AvailabilityError();
+ return error;
+}
+
+QRadioTuner::Band QXARadioSession::band() const
+{
+ QRadioTuner::Band band = QRadioTuner::FM;
+ if (m_impl)
+ band = m_impl->Band();
+ return band;
+}
+
+void QXARadioSession::setBand(QRadioTuner::Band band)
+{
+ if (m_impl)
+ m_impl->SetBand(band);
+}
+
+bool QXARadioSession::isBandSupported(QRadioTuner::Band band) const
+{
+ if (m_impl)
+ return m_impl->IsBandSupported(band);
+ return false;
+}
+
+bool QXARadioSession::isAvailable() const
+{
+ if (m_impl)
+ return m_impl->IsAvailable();
+ return false;
+}
+
+int QXARadioSession::frequency() const
+{
+ TInt frequency = 0;
+ if (m_impl)
+ frequency = m_impl->GetFrequency();
+ return (int)frequency;
+}
+
+int QXARadioSession::frequencyStep(QRadioTuner::Band band) const
+{
+ TInt freqStep = 0;
+ if (m_impl)
+ freqStep = m_impl->FrequencyStep(band);
+ return (int)freqStep;
+}
+
+QPair<int, int> QXARadioSession::frequencyRange(QRadioTuner::Band /*band*/) const
+{
+ QPair<int, int> freqRange;
+ freqRange.first = 0;
+ freqRange.second =0;
+
+ if (m_impl) {
+ TInt freqRangeType = m_impl->GetFrequencyRange();
+ m_impl->GetFrequencyRangeProperties(freqRangeType, freqRange.first, freqRange.second);
+ }
+
+ return freqRange;
+}
+
+void QXARadioSession::setFrequency(int frequency)
+{
+ if (m_impl)
+ m_impl->SetFrequency(frequency);
+}
+
+bool QXARadioSession::isStereo() const
+{
+ bool isStereo = false;
+ if (m_impl)
+ isStereo = m_impl->IsStereo();
+ return isStereo;
+}
+
+QRadioTuner::StereoMode QXARadioSession::stereoMode() const
+{
+ QRadioTuner::StereoMode mode(QRadioTuner::Auto);
+ if (m_impl)
+ mode = m_impl->StereoMode();
+ return mode;
+}
+
+void QXARadioSession::setStereoMode(QRadioTuner::StereoMode mode)
+{
+ if (m_impl)
+ m_impl->SetStereoMode(mode);
+}
+
+int QXARadioSession::signalStrength() const
+{
+ TInt signalStrength = 0;
+ if (m_impl)
+ signalStrength = m_impl->GetSignalStrength();
+ return (int)signalStrength;
+}
+
+int QXARadioSession::volume() const
+{
+ TInt volume = 0;
+ if (m_impl)
+ volume = m_impl->GetVolume();
+ return volume;
+}
+
+int QXARadioSession::setVolume(int volume)
+{
+ TInt newVolume = 0;
+ if (m_impl) {
+ m_impl->SetVolume(volume);
+ newVolume = m_impl->GetVolume();
+ }
+ return newVolume;
+}
+
+bool QXARadioSession::isMuted() const
+{
+ bool isMuted = false;
+ if (m_impl)
+ isMuted = m_impl->IsMuted();
+ return isMuted;
+}
+
+void QXARadioSession::setMuted(bool muted)
+{
+ if (m_impl)
+ m_impl->SetMuted(muted);
+}
+
+bool QXARadioSession::isSearching() const
+{
+ bool isSearching = false;
+ if (m_impl)
+ isSearching = m_impl->IsSearching();
+ return isSearching;
+}
+
+void QXARadioSession::searchForward()
+{
+ if (m_impl)
+ m_impl->Seek(true);
+}
+
+void QXARadioSession::searchBackward()
+{
+ if (m_impl)
+ m_impl->Seek(false);
+}
+
+void QXARadioSession::cancelSearch()
+{
+ if (m_impl)
+ m_impl->StopSeeking();
+}
+
+void QXARadioSession::start()
+{
+ if (m_impl)
+ m_impl->Start();
+}
+
+void QXARadioSession::stop()
+{
+ if (m_impl)
+ m_impl->Stop();
+}
+
+QRadioTuner::Error QXARadioSession::error() const
+{
+ QRadioTuner::Error err(QRadioTuner::NoError);
+ if (m_impl)
+ err = m_impl->Error();
+ return err;
+}
+
+QString QXARadioSession::errorString() const
+{
+ QString str = NULL;
+ switch (iError) {
+ case QRadioTuner::ResourceError:
+ str = "Resource Error";
+ break;
+ case QRadioTuner::OpenError:
+ str = "Open Error";
+ break;
+ case QRadioTuner::OutOfRangeError:
+ str = "Out of Range Error";
+ break;
+ default:
+ break;
+ }
+
+ return str;
+}
+
+// Callbacks, which will emit signals to client:
+void QXARadioSession::CBStateChanged(QRadioTuner::State state)
+{
+ emit stateChanged(state);
+}
+
+void QXARadioSession::CBBandChanged(QRadioTuner::Band band)
+{
+ emit bandChanged(band);
+}
+
+void QXARadioSession::CBFrequencyChanged(TInt newFrequency)
+{
+ emit frequencyChanged(newFrequency);
+}
+
+void QXARadioSession::CBStereoStatusChanged(bool isStereo)
+{
+ emit stereoStatusChanged(isStereo);
+}
+
+void QXARadioSession::CBSignalStrengthChanged(int signalStrength)
+{
+ emit signalStrengthChanged(signalStrength);
+}
+
+void QXARadioSession::CBVolumeChanged(int volume)
+{
+ emit volumeChanged(volume);
+}
+
+void QXARadioSession::CBMutedChanged(bool isMuted)
+{
+ emit mutedChanged(isMuted);
+}
+
+void QXARadioSession::CBSearchingChanged(bool isSearching)
+{
+ emit searchingChanged(isSearching);
+}
+
+void QXARadioSession::CBError(QRadioTuner::Error err)
+{
+ iError = err;
+ emit error((int)err, errorString());
+}
+
+
diff --git a/src/plugins/symbian/openmaxal/radiotuner/qxaradiosession.h b/src/plugins/symbian/openmaxal/radiotuner/qxaradiosession.h
new file mode 100644
index 000000000..72f6a7a01
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/radiotuner/qxaradiosession.h
@@ -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$
+** 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 QXARADIOSESSION_H
+#define QXARADIOSESSION_H
+
+#include <QObject>
+#include <QUrl>
+#include <qradiotuner.h>
+#include "xaradiosessionimplobserver.h"
+
+QT_USE_NAMESPACE
+
+class XARadioSessionImpl;
+
+class QXARadioSession : public QObject, public XARadioSessionImplObserver
+{
+Q_OBJECT
+
+public:
+ QXARadioSession(QObject *parent);
+ virtual ~QXARadioSession();
+
+ QRadioTuner::State state() const;
+ QRadioTuner::Band band() const;
+ void setBand(QRadioTuner::Band band);
+ bool isBandSupported(QRadioTuner::Band band) const;
+ int frequency() const;
+ int frequencyStep(QRadioTuner::Band b) const;
+ QPair<int,int> frequencyRange(QRadioTuner::Band b) const;
+ void setFrequency(int frequency);
+ bool isStereo() const;
+ QRadioTuner::StereoMode stereoMode() const;
+ void setStereoMode(QRadioTuner::StereoMode mode);
+ int signalStrength() const;
+ int volume() const;
+ int setVolume(int volume);
+ bool isMuted() const;
+ void setMuted(bool muted);
+ bool isSearching() const;
+ void searchForward();
+ void searchBackward();
+ void cancelSearch();
+ void start();
+ void stop();
+ bool isAvailable() const;
+ QtMultimediaKit::AvailabilityError availabilityError() const;
+ QRadioTuner::Error error() const;
+ QString errorString() const;
+
+ /* Callbacks from XARadioSessionImplObserver begin */
+ void CBBandChanged(QRadioTuner::Band band);
+ void CBStateChanged(QRadioTuner::State state);
+ void CBFrequencyChanged(TInt newFrequency);
+ void CBStereoStatusChanged(bool isStereo);
+ void CBSignalStrengthChanged(int signalStrength);
+ void CBVolumeChanged(int volume);
+ void CBMutedChanged(bool isMuted);
+ void CBSearchingChanged(bool isSearching);
+ void CBError(QRadioTuner::Error err);
+ /* Callbacks from XARadioSessionImplObserver end */
+
+signals:
+ void stateChanged(QRadioTuner::State state);
+ void bandChanged(QRadioTuner::Band band);
+ void frequencyChanged(int frequency);
+ void stereoStatusChanged(bool stereo);
+ void searchingChanged(bool stereo);
+ void signalStrengthChanged(int signalStrength);
+ void volumeChanged(int volume);
+ void mutedChanged(bool muted);
+ void error(int err, QString str);
+
+private:
+ /* Own */
+ QRadioTuner::Error iError;
+ XARadioSessionImpl* m_impl;
+};
+
+#endif /*QXARADIOSESSION_H*/
diff --git a/src/plugins/symbian/openmaxal/radiotuner/radiotuner.pri b/src/plugins/symbian/openmaxal/radiotuner/radiotuner.pri
new file mode 100644
index 000000000..bf83d05fc
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/radiotuner/radiotuner.pri
@@ -0,0 +1,18 @@
+INCLUDEPATH += $$PWD
+
+# Input
+HEADERS += \
+ $$PWD/qxaradiomediaservice.h \
+ $$PWD/qxaradiosession.h \
+ $$PWD/qxaradiocontrol.h \
+ $$PWD/xaradiosessionimpl.h \
+ $$PWD/xaradiosessionimplobserver.h
+
+SOURCES += \
+ $$PWD/qxaradiomediaservice.cpp \
+ $$PWD/qxaradiosession.cpp \
+ $$PWD/qxaradiocontrol.cpp \
+ $$PWD/xaradiosessionimpl.cpp
+
+LIBS += \
+ -lbafl
diff --git a/src/plugins/symbian/openmaxal/radiotuner/xaradiosessionimpl.cpp b/src/plugins/symbian/openmaxal/radiotuner/xaradiosessionimpl.cpp
new file mode 100644
index 000000000..94bebc373
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/radiotuner/xaradiosessionimpl.cpp
@@ -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$
+** 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 "xaradiosessionimpl.h"
+#include "xaradiosessionimplobserver.h"
+#include <xaradioitfext.h>
+#include "xacommon.h"
+
+#define MAX_NUMBER_INTERFACES 20
+#define FM_STEP 100000; // Hz (.1 MHz)
+
+/*
+ * function declarations.
+ * */
+void EngineObjectCallback(XAObjectItf caller, const void */*pContext*/,
+ XAuint32 event, XAresult result, XAuint32 /*param*/,
+ void */*pInterface*/);
+
+void RadioCallback(XARadioItf caller, void* pContext, XAuint32 event, XAuint32 eventIntData, XAboolean eventBooleanData);
+void NokiaVolumeExtItfCallback(XANokiaVolumeExtItf caller, void* pContext, XAuint32 event, XAboolean eventBooleanData);
+void NokiaLinearVolumeItfCallback(XANokiaLinearVolumeItf caller, void* pContext, XAuint32 event, XAboolean eventBooleanData);
+void PlayItfCallbackForRadio(XAPlayItf caller, void* pContext, XAuint32 event);
+
+XARadioSessionImpl::XARadioSessionImpl(XARadioSessionImplObserver& parent)
+:iParent(parent),
+iRadio(NULL),
+iEngine(NULL),
+iPlayer(NULL),
+iSearching(EFalse),
+iRadioAvailable(EFalse),
+iState(QRadioTuner::StoppedState)
+{
+ iAvailabilityError = QtMultimediaKit::NoError;
+}
+
+XARadioSessionImpl::~XARadioSessionImpl()
+{
+ if (iRadio) {
+ TRACE_LOG((_L("XARadioSessionImpl::~XARadioSessionImpl(): Deleting Radio Device...")));
+ (*iRadio)->Destroy(iRadio);
+ iRadio = NULL;
+ TRACE_LOG((_L("XARadioSessionImpl::~XARadioSessionImpl(): Deleted Radio Device")));
+ }
+ if (iPlayer) {
+ TRACE_LOG((_L("XARadioSessionImpl::~XARadioSessionImpl(): Deleting player...")));
+ (*iPlayer)->Destroy(iPlayer);
+ iPlayer = NULL;
+ TRACE_LOG((_L("XARadioSessionImpl::~XARadioSessionImpl(): Deleted iPlayer")));
+ }
+ if ( iEngine ) {
+ TRACE_LOG((_L("XARadioSessionImpl::~XARadioSessionImpl(): Deleting engine...")));
+ (*iEngine)->Destroy(iEngine);
+ iEngine = NULL;
+ TRACE_LOG((_L("XARadioSessionImpl::~XARadioSessionImpl(): Deleted engine")));
+ }
+}
+
+QRadioTuner::Error XARadioSessionImpl::PostConstruct()
+{
+ XAresult res = CreateEngine();
+ if (res != KErrNone)
+ return QRadioTuner::ResourceError;
+ else
+ return QRadioTuner::NoError;
+}
+
+TInt XARadioSessionImpl::CreateEngine()
+{
+ TRACE_FUNCTION_ENTRY;
+ XAboolean required[MAX_NUMBER_INTERFACES];
+ XAInterfaceID iidArray[MAX_NUMBER_INTERFACES];
+ XAuint32 noOfInterfaces = 0;
+ int i;
+ XAresult res;
+
+ XAEngineOption EngineOption[] =
+ {
+ {
+ (XAuint32) XA_ENGINEOPTION_THREADSAFE,
+ (XAuint32) XA_BOOLEAN_TRUE
+ }
+ };
+
+ /* Create XA engine */
+ if (!iEngine) {
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Creating Engine...")));
+ res = xaCreateEngine(&iEngine, 1, EngineOption, 0, NULL, NULL);
+ RET_ERR_IF_ERR(CheckErr(res));
+ res = (*iEngine)->RegisterCallback(iEngine, EngineObjectCallback, NULL);
+ RET_ERR_IF_ERR(CheckErr(res));
+
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Realizing...")));
+ res = (*iEngine)->Realize(iEngine, XA_BOOLEAN_FALSE);
+ RET_ERR_IF_ERR(CheckErr(res));
+
+ // Create Engine Interface:
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Creating Engine Interface")));
+ RET_ERR_IF_ERR(CheckErr((*iEngine)->GetInterface(iEngine, XA_IID_ENGINE, (void*)&iEngineItf)));
+
+ // Create Radio Device and interface(s):
+ if (!iRadio) {
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Creating Radio Device")));
+ res = (*iEngineItf)->CreateRadioDevice(iEngineItf,&iRadio, 0, NULL, NULL);
+ RET_ERR_IF_ERR(CheckErr(res));
+
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Realize Radio Device")));
+ res = (*iRadio)->Realize(iRadio, XA_BOOLEAN_FALSE);
+ RET_ERR_IF_ERR(CheckErr(res));
+
+ // Get Radio interface:
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Get Radio Interface")));
+ res = (*iRadio)->GetInterface(iRadio, XA_IID_RADIO, (void*)&iRadioItf);
+ RET_ERR_IF_ERR(CheckErr(res));
+ iRadioAvailable = ETrue;
+ // Register Radio Callback:
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Create Radio Callback:")));
+ res = (*iRadioItf)->RegisterRadioCallback(iRadioItf, RadioCallback, (void*)this);
+ RET_ERR_IF_ERR(CheckErr(res));
+ }
+ XADataSource audioSource;
+ XADataLocator_IODevice locatorIODevice;
+ XADataSink audioSink;
+ XADataLocator_OutputMix locator_outputmix;
+
+ /* Init arrays required[] and iidArray[] */
+ for (i = 0; i < MAX_NUMBER_INTERFACES; i++) {
+ required[i] = XA_BOOLEAN_FALSE;
+ iidArray[i] = XA_IID_NULL;
+ }
+
+ iidArray[0] = XA_IID_NOKIAVOLUMEEXT;
+ iidArray[1] = XA_IID_NOKIALINEARVOLUME;
+ noOfInterfaces = 2;
+
+ locatorIODevice.locatorType = XA_DATALOCATOR_IODEVICE;
+ locatorIODevice.deviceType = XA_IODEVICE_RADIO;
+ locatorIODevice.deviceID = 0; /* ignored */
+ locatorIODevice.device = iRadio;
+ audioSource.pLocator = (void*) &locatorIODevice;
+ audioSource.pFormat = NULL;
+
+ /* Setup the data sink structure */
+ locator_outputmix.locatorType = XA_DEFAULTDEVICEID_AUDIOOUTPUT;
+ locator_outputmix.outputMix = NULL;
+ audioSink.pLocator = (void*) &locator_outputmix;
+ audioSink.pFormat = NULL;
+
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Create Media Player:")));
+ res = (*iEngineItf)->CreateMediaPlayer(iEngineItf, &iPlayer, &audioSource, NULL, &audioSink, NULL, NULL, NULL, noOfInterfaces, iidArray, required);
+ RET_ERR_IF_ERR(CheckErr(res));
+
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Realize Media Player:")));
+ res = (*iPlayer)->Realize(iPlayer, XA_BOOLEAN_FALSE);
+ RET_ERR_IF_ERR(CheckErr(res));
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Get Play Interface from player:")));
+ res = (*iPlayer)->GetInterface(iPlayer, XA_IID_PLAY, (void*) &iPlayItf);
+ RET_ERR_IF_ERR(CheckErr(res));
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Create PlayItf Callback:")));
+ res = (*iPlayItf)->RegisterCallback(iPlayItf, PlayItfCallbackForRadio, (void*)this);
+ RET_ERR_IF_ERR(CheckErr(res));
+
+ // Get Volume Interfaces specific for Nokia impl:
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Get NokiaVolumeExt Interface")));
+ res = (*iPlayer)->GetInterface(iPlayer, XA_IID_NOKIAVOLUMEEXT, (void*)&iNokiaVolumeExtItf);
+ RET_ERR_IF_ERR(CheckErr(res));
+
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Get NokiaLinearVolume Interface")));
+ res = (*iPlayer)->GetInterface(iPlayer, XA_IID_NOKIALINEARVOLUME, (void*)&iNokiaLinearVolumeItf);
+ RET_ERR_IF_ERR(CheckErr(res));
+
+ // Register Volume Callbacks:
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Create NokiaVolumeExtItf Callback:")));
+ res = (*iNokiaVolumeExtItf)->RegisterVolumeCallback(iNokiaVolumeExtItf, NokiaVolumeExtItfCallback, (void*)this);
+ RET_ERR_IF_ERR(CheckErr(res));
+ res = (*iNokiaVolumeExtItf)->SetCallbackEventsMask(iNokiaVolumeExtItf,(XA_NOKIAVOLUMEEXT_EVENT_MUTE_CHANGED));
+ RET_ERR_IF_ERR(CheckErr(res));
+ TRACE_LOG((_L("XARadioSessionImpl::CreateEngine: Create NokiaLinearVolumeItf Callback:")));
+ res = (*iNokiaLinearVolumeItf)->RegisterVolumeCallback(iNokiaLinearVolumeItf, NokiaLinearVolumeItfCallback, (void*)this);
+ RET_ERR_IF_ERR(CheckErr(res));
+ res = (*iNokiaLinearVolumeItf)->SetCallbackEventsMask(iNokiaLinearVolumeItf,(XA_NOKIALINEARVOLUME_EVENT_VOLUME_CHANGED));
+ RET_ERR_IF_ERR(CheckErr(res));
+ }
+
+ TRACE_FUNCTION_EXIT;
+ return EFalse;
+}
+
+QRadioTuner::State XARadioSessionImpl::State() const
+{
+ TRACE_FUNCTION_ENTRY_EXIT;
+ return iState;
+}
+
+QtMultimediaKit::AvailabilityError XARadioSessionImpl::AvailabilityError() const
+{
+ TRACE_FUNCTION_ENTRY_EXIT;
+ return iAvailabilityError;
+}
+
+ bool XARadioSessionImpl::IsAvailable() const
+{
+ TRACE_FUNCTION_ENTRY_EXIT;
+ return iRadioAvailable;
+}
+
+QRadioTuner::Band XARadioSessionImpl::Band() const
+{
+ TRACE_FUNCTION_ENTRY_EXIT;
+ return iBand;
+}
+
+void XARadioSessionImpl::SetBand(QRadioTuner::Band band)
+{
+ if (band != QRadioTuner::FM)
+ iParent.CBError(QRadioTuner::OpenError);
+ else
+ iBand = band;
+}
+
+bool XARadioSessionImpl::IsBandSupported(QRadioTuner::Band band) const
+{
+ if (band == QRadioTuner::FM)
+ return ETrue;
+ else
+ return EFalse;
+}
+
+// Returns the number of Hertz to increment the frequency by when stepping through frequencies within a given band.
+TInt XARadioSessionImpl::FrequencyStep(QRadioTuner::Band /*band*/) const
+{
+ TInt freqStep = FM_STEP;
+ return (int)freqStep;
+}
+
+bool XARadioSessionImpl::IsStereo() //const
+{
+ bool isStereo = EFalse;
+ QRadioTuner::StereoMode mode = StereoMode();
+ if (mode == QRadioTuner::ForceStereo || mode == QRadioTuner::Auto)
+ isStereo = ETrue;
+ return isStereo;
+}
+
+bool XARadioSessionImpl::IsMuted() const
+{
+ TRACE_FUNCTION_ENTRY;
+ XAboolean isMuted = EFalse;
+ (*iNokiaVolumeExtItf)->GetMute(iNokiaVolumeExtItf, &isMuted );
+ TRACE_LOG((_L("XARadioSessionImpl::IsMuted: isMuted = %d"), isMuted));
+
+ TRACE_FUNCTION_EXIT;
+ return isMuted;
+}
+
+bool XARadioSessionImpl::IsSearching() const
+{
+ //iSearching is set when seek (QT:searchForward-backward)
+ // iSearching is cleared when SearchingStatusChanged is called or StopSeeking is called
+ return iSearching;
+}
+
+TInt XARadioSessionImpl::GetFrequency()
+{
+ TRACE_FUNCTION_ENTRY;
+
+ XAuint32 freq = 0;
+ XAresult res = (*iRadioItf)->GetFrequency(iRadioItf, &freq );
+ RET_ERR_IF_ERR(CheckErr(res));
+ TRACE_LOG((_L("XARadioSessionImpl::GetFrequency: Frequency = %d"), freq));
+
+ TRACE_FUNCTION_EXIT;
+ return (int)freq;
+}
+
+TInt XARadioSessionImpl::GetFrequencyRange()
+{
+ TRACE_FUNCTION_ENTRY;
+ XAuint8 range = 0;
+
+ XAresult res = (*iRadioItf)->GetFreqRange(iRadioItf, &range);
+ RET_ERR_IF_ERR(CheckErr(res));
+ TRACE_LOG((_L("XARadioSessionImpl::GetFrequencyRange: Frequency Range = %d"), range));
+
+ TRACE_FUNCTION_EXIT;
+ return (int)range;
+}
+
+TInt XARadioSessionImpl::GetFrequencyRangeProperties(TInt range, TInt &minFreq, TInt &maxFreq)
+{
+ TRACE_FUNCTION_ENTRY;
+ XAuint32 freqInterval = 0;
+ XAresult res = (*iRadioItf)->GetFreqRangeProperties(iRadioItf, (XAuint8)range, (XAuint32*)&minFreq,(XAuint32*)&maxFreq, (XAuint32*)&freqInterval);
+ RET_ERR_IF_ERR(CheckErr(res));
+ TRACE_LOG((_L("XARadioSessionImpl::GetFrequencyRangeProperties: minFreq = %d, maxFreq = %d"), minFreq, maxFreq));
+
+ TRACE_FUNCTION_EXIT;
+ return res;
+}
+
+TInt XARadioSessionImpl::SetFrequency(TInt aFreq)
+{
+ TRACE_FUNCTION_ENTRY;
+
+ TRACE_LOG((_L("XARadioSessionImpl::SetFrequency: Setting Frequency to: %d"), aFreq));
+ XAresult res = (*iRadioItf)->SetFrequency(iRadioItf, aFreq );
+ RET_ERR_IF_ERR(CheckErr(res));
+
+ TRACE_FUNCTION_EXIT;
+ return res;
+}
+
+QRadioTuner::StereoMode XARadioSessionImpl::StereoMode()
+{
+ TRACE_FUNCTION_ENTRY;
+ QRadioTuner::StereoMode qtStereoMode;
+ XAuint32 symStereoMode;
+ (*iRadioItf)->GetStereoMode(iRadioItf, &symStereoMode);
+
+ if (symStereoMode == XA_STEREOMODE_MONO)
+ qtStereoMode = QRadioTuner::ForceMono;
+ else if (symStereoMode == XA_STEREOMODE_STEREO)
+ qtStereoMode = QRadioTuner::ForceStereo;
+ else
+ qtStereoMode = QRadioTuner::Auto;
+
+ TRACE_FUNCTION_EXIT;
+ return qtStereoMode;
+}
+
+TInt XARadioSessionImpl::SetStereoMode(QRadioTuner::StereoMode qtStereoMode)
+{
+ TRACE_FUNCTION_ENTRY;
+ XAuint32 symStereoMode;
+
+ if (qtStereoMode == QRadioTuner::ForceMono)
+ symStereoMode = XA_STEREOMODE_MONO;
+ else if (qtStereoMode == QRadioTuner::ForceStereo)
+ symStereoMode = XA_STEREOMODE_STEREO;
+ else
+ symStereoMode = XA_STEREOMODE_AUTO;
+
+ XAresult res = (*iRadioItf)->SetStereoMode(iRadioItf, (symStereoMode));
+ TRACE_FUNCTION_EXIT;
+ return res;
+}
+
+TInt XARadioSessionImpl::GetSignalStrength()
+{
+ TRACE_FUNCTION_ENTRY;
+ XAuint32 signalStrength = 0;
+
+ (*iRadioItf)->GetSignalStrength(iRadioItf, &signalStrength );
+ TRACE_LOG((_L("XARadioSessionImpl::GetSignalStrength: Signal Strength = %d"), signalStrength));
+ TRACE_FUNCTION_EXIT;
+ return (int)signalStrength;
+}
+
+TInt XARadioSessionImpl::GetVolume()
+{
+ TRACE_FUNCTION_ENTRY;
+ XAuint32 vol;
+ if (iPlayer && iNokiaLinearVolumeItf) {
+ (*iNokiaLinearVolumeItf)->GetVolumeLevel(iNokiaLinearVolumeItf, &vol );
+ TRACE_LOG((_L("XARadioSessionImpl::GetVolume: Volume = %d"), vol));
+ }
+ TRACE_FUNCTION_EXIT;
+ return (TInt)vol;
+}
+
+TInt XARadioSessionImpl::SetVolume(TInt aVolume)
+{
+ TRACE_FUNCTION_ENTRY;
+ XAuint32 newVolume = 0;
+ TRACE_LOG((_L("XARadioSessionImpl::SetVolume: Setting volume to: %d"), aVolume));
+ if (iPlayer && iNokiaLinearVolumeItf) {
+ newVolume = aVolume;
+ XAresult res = (*iNokiaLinearVolumeItf)->SetVolumeLevel(iNokiaLinearVolumeItf, &newVolume);
+ }
+ TRACE_FUNCTION_EXIT;
+ return (TInt)newVolume;
+}
+
+TInt XARadioSessionImpl::SetMuted(TBool aMuted)
+{
+ TRACE_FUNCTION_ENTRY;
+ XAresult res = (*iNokiaVolumeExtItf)->SetMute(iNokiaVolumeExtItf, aMuted);
+ TRACE_FUNCTION_EXIT;
+ return res;
+}
+
+TInt XARadioSessionImpl::Seek(TBool aDirection)
+{
+ TRACE_FUNCTION_ENTRY;
+ iSearching = true;
+ XAresult res = (*iRadioItf)->Seek(iRadioItf, aDirection );
+ TRACE_FUNCTION_EXIT;
+ return res;
+}
+
+TInt XARadioSessionImpl::StopSeeking()
+{
+ TRACE_FUNCTION_ENTRY;
+ XAresult res = (*iRadioItf)->StopSeeking(iRadioItf);
+ iSearching = EFalse;
+ TRACE_FUNCTION_EXIT;
+ return res;
+}
+
+void XARadioSessionImpl::Start()
+{
+ TRACE_FUNCTION_ENTRY;
+ if (iPlayItf) {
+ XAresult res = (*iPlayItf)->SetPlayState(iPlayItf, XA_PLAYSTATE_PLAYING);
+ // add error handling if res != 0 (call errorCB)
+ }
+ TRACE_FUNCTION_EXIT;
+}
+
+void XARadioSessionImpl::Stop()
+{
+ TRACE_FUNCTION_ENTRY;
+ if (iPlayItf) {
+ XAresult res = (*iPlayItf)->SetPlayState(iPlayItf, XA_PLAYSTATE_STOPPED);
+ // add error handling if res != 0 (call errorCB)
+ }
+ TRACE_FUNCTION_EXIT;
+}
+
+QRadioTuner::Error XARadioSessionImpl::Error()
+{
+ TRACE_FUNCTION_ENTRY_EXIT;
+ return QRadioTuner::NoError;
+}
+
+//TInt XARadioSessionImpl::ErrorString();
+// {
+// TRACE_FUNCTION_ENTRY;
+
+// TRACE_FUNCTION_EXIT;
+// }
+
+void XARadioSessionImpl::StateChanged(QRadioTuner::State state)
+{
+ TRACE_FUNCTION_ENTRY;
+ iState = state;
+ iParent.CBStateChanged(state);
+ TRACE_FUNCTION_EXIT;
+}
+
+void XARadioSessionImpl::FrequencyChanged(XAuint32 freq)
+{
+ TRACE_FUNCTION_ENTRY;
+ iParent.CBFrequencyChanged(freq);
+ TRACE_FUNCTION_EXIT;
+}
+
+void XARadioSessionImpl::SearchingChanged(TBool isSearching)
+{
+ TRACE_FUNCTION_ENTRY;
+ iSearching = EFalse;
+ iParent.CBSearchingChanged(isSearching);
+ TRACE_FUNCTION_EXIT;
+}
+
+void XARadioSessionImpl::StereoStatusChanged(TBool stereoStatus)
+{
+ TRACE_FUNCTION_ENTRY;
+ iParent.CBStereoStatusChanged(stereoStatus);
+ TRACE_FUNCTION_EXIT;
+}
+
+void XARadioSessionImpl::SignalStrengthChanged(TBool stereoStatus)
+{
+ TRACE_FUNCTION_ENTRY;
+ iParent.CBSignalStrengthChanged(stereoStatus);
+ TRACE_FUNCTION_EXIT;
+}
+
+void XARadioSessionImpl::VolumeChanged()
+{
+ TRACE_FUNCTION_ENTRY;
+ int vol = 0;
+ iParent.CBVolumeChanged(vol);
+ TRACE_FUNCTION_EXIT;
+}
+
+void XARadioSessionImpl::MutedChanged(TBool mute)
+{
+ TRACE_FUNCTION_ENTRY;
+ iParent.CBMutedChanged(mute);
+ TRACE_FUNCTION_EXIT;
+}
+
+void EngineObjectCallback(XAObjectItf /*caller*/,
+ const void */*pContext*/,
+#ifdef PLUGIN_SYMBIAN_TRACE_ENABLED
+ XAuint32 event,
+#else
+ XAuint32 /*event*/,
+#endif /*PLUGIN_SYMBIAN_TRACE_ENABLED*/
+ XAresult /*result*/,
+ XAuint32 /*param*/,
+ void */*pInterface*/)
+{
+#ifdef PLUGIN_SYMBIAN_TRACE_ENABLED
+ TRACE_LOG((_L("Engine object event: 0x%x\n"), (int)event));
+#endif /*PLUGIN_SYMBIAN_TRACE_ENABLED*/
+}
+
+void RadioCallback(XARadioItf /*caller*/,
+ void* pContext,
+ XAuint32 event,
+ XAuint32 eventIntData,
+ XAboolean eventBooleanData)
+{
+ XAuint32 freq;
+ XAboolean stereoStatus(XA_BOOLEAN_FALSE);
+
+ switch (event) {
+ case XA_RADIO_EVENT_ANTENNA_STATUS_CHANGED:
+ TRACE_LOG((_L("RadioCallback: XA_RADIO_EVENT_ANTENNA_STATUS_CHANGED")));
+ // Qt API has no callback defined for this event.
+ break;
+ case XA_RADIO_EVENT_FREQUENCY_CHANGED:
+ freq = eventIntData;
+ TRACE_LOG((_L("RadioCallback: XA_RADIO_EVENT_FREQUENCY_CHANGED to: %d"), freq));
+ if (pContext)
+ ((XARadioSessionImpl*)pContext)->FrequencyChanged(freq);
+ break;
+ case XA_RADIO_EVENT_FREQUENCY_RANGE_CHANGED:
+ TRACE_LOG((_L("RadioCallback: XA_RADIO_EVENT_FREQUENCY_RANGE_CHANGED")));
+ // Qt API has no callback defined for this event.
+ break;
+ case XA_RADIO_EVENT_PRESET_CHANGED:
+ TRACE_LOG((_L("RadioCallback: XA_RADIO_EVENT_PRESET_CHANGED")));
+ // Qt API has no callback defined for this event.
+ break;
+ case XA_RADIO_EVENT_SEEK_COMPLETED:
+ TRACE_LOG((_L("RadioCallback: XA_RADIO_EVENT_SEEK_COMPLETED")));
+ if (pContext)
+ ((XARadioSessionImpl*)pContext)->SearchingChanged(false);
+ break;
+ case XA_RADIO_EVENT_STEREO_STATUS_CHANGED:
+ stereoStatus = eventBooleanData;
+ TRACE_LOG((_L("RadioCallback: XA_RADIO_EVENT_STEREO_STATUS_CHANGED: %d"), stereoStatus));
+ if (pContext)
+ ((XARadioSessionImpl*)pContext)->StereoStatusChanged(stereoStatus);
+ break;
+ case XA_RADIO_EVENT_SIGNAL_STRENGTH_CHANGED:
+ TRACE_LOG((_L("RadioCallback: XA_RADIO_EVENT_SIGNAL_STRENGTH_CHANGED")));
+ if (pContext)
+ ((XARadioSessionImpl*)pContext)->SignalStrengthChanged(stereoStatus);
+ break;
+ default:
+ TRACE_LOG((_L("RadioCallback: default")));
+ break;
+ }
+}
+
+void NokiaVolumeExtItfCallback(XANokiaVolumeExtItf /*caller*/,
+ void* pContext,
+ XAuint32 event,
+ XAboolean eventBooleanData)
+{
+ XAboolean mute;
+ switch (event) {
+ case XA_NOKIAVOLUMEEXT_EVENT_MUTE_CHANGED:
+ mute = eventBooleanData;
+ TRACE_LOG((_L("NokiaVolumeExtItfCallback: XA_NOKIAVOLUMEEXT_EVENT_MUTE_CHANGED to: %d"), mute));
+ if (pContext)
+ ((XARadioSessionImpl*)pContext)->MutedChanged(mute);
+ break;
+ default:
+ TRACE_LOG((_L("NokiaVolumeExtItfCallback: default")));
+ break;
+ }
+}
+
+void NokiaLinearVolumeItfCallback(XANokiaLinearVolumeItf /*caller*/,
+ void* pContext,
+ XAuint32 event,
+ XAboolean /*eventBooleanData*/)
+{
+ switch (event) {
+ case XA_NOKIALINEARVOLUME_EVENT_VOLUME_CHANGED:
+ if (pContext)
+ ((XARadioSessionImpl*)pContext)->VolumeChanged();
+ break;
+ default:
+ TRACE_LOG((_L("NokiaLinearVolumeItfCallback: default")));
+ break;
+ }
+}
+
+void PlayItfCallbackForRadio(XAPlayItf /*caller*/,
+ void* pContext,
+ XAuint32 event)
+{
+ switch (event) {
+ case XA_PLAYEVENT_HEADMOVING:
+ if (pContext)
+ ((XARadioSessionImpl*)pContext)->StateChanged(QRadioTuner::ActiveState);
+ break;
+ case XA_PLAYEVENT_HEADSTALLED:
+ if (pContext)
+ ((XARadioSessionImpl*)pContext)->StateChanged(QRadioTuner::StoppedState);
+ break;
+ default:
+ TRACE_LOG((_L("NokiaLinearVolumeItfCallback: default")));
+ break;
+ }
+}
+
+TInt XARadioSessionImpl::CheckErr(XAresult res)
+{
+ TInt status(KErrGeneral);
+ switch(res) {
+ case XA_RESULT_SUCCESS:
+ //TRACE_LOG((_L("XA_RESULT_SUCCESS")));
+ status = KErrNone;
+ break;
+ case XA_RESULT_PRECONDITIONS_VIOLATED:
+ TRACE_LOG((_L("XA_RESULT_PRECONDITIONS_VIOLATED")));
+ break;
+ case XA_RESULT_PARAMETER_INVALID:
+ TRACE_LOG((_L("XA_RESULT_PARAMETER_INVALID")));
+ break;
+ case XA_RESULT_MEMORY_FAILURE:
+ TRACE_LOG((_L("XA_RESULT_MEMORY_FAILURE")));
+ iAvailabilityError = QtMultimediaKit::ResourceError;
+ break;
+ case XA_RESULT_RESOURCE_ERROR:
+ TRACE_LOG((_L("XA_RESULT_RESOURCE_ERROR")));
+ iAvailabilityError = QtMultimediaKit::ResourceError;
+ break;
+ case XA_RESULT_RESOURCE_LOST:
+ TRACE_LOG((_L("XA_RESULT_RESOURCE_LOST")));
+ iAvailabilityError = QtMultimediaKit::ResourceError;
+ break;
+ case XA_RESULT_IO_ERROR:
+ TRACE_LOG((_L("XA_RESULT_IO_ERROR")));
+ break;
+ case XA_RESULT_BUFFER_INSUFFICIENT:
+ TRACE_LOG((_L("XA_RESULT_BUFFER_INSUFFICIENT")));
+ break;
+ case XA_RESULT_CONTENT_CORRUPTED:
+ TRACE_LOG((_L("XA_RESULT_CONTENT_CORRUPTED")));
+ break;
+ case XA_RESULT_CONTENT_UNSUPPORTED:
+ TRACE_LOG((_L("XA_RESULT_CONTENT_UNSUPPORTED")));
+ break;
+ case XA_RESULT_CONTENT_NOT_FOUND:
+ TRACE_LOG((_L("XA_RESULT_CONTENT_NOT_FOUND")));
+ break;
+ case XA_RESULT_PERMISSION_DENIED:
+ TRACE_LOG((_L("XA_RESULT_PERMISSION_DENIED")));
+ break;
+ case XA_RESULT_FEATURE_UNSUPPORTED:
+ TRACE_LOG((_L("XA_RESULT_FEATURE_UNSUPPORTED")));
+ break;
+ case XA_RESULT_INTERNAL_ERROR:
+ TRACE_LOG((_L("XA_RESULT_INTERNAL_ERROR")));
+ break;
+ case XA_RESULT_UNKNOWN_ERROR:
+ TRACE_LOG((_L("XA_RESULT_UNKNOWN_ERROR")));
+ break;
+ case XA_RESULT_OPERATION_ABORTED:
+ TRACE_LOG((_L("XA_RESULT_OPERATION_ABORTED")));
+ break;
+ case XA_RESULT_CONTROL_LOST:
+ TRACE_LOG((_L("XA_RESULT_CONTROL_LOST")));
+ break;
+ default:
+ TRACE_LOG((_L("Unknown Error!!!")));
+ }
+ return status;
+}
diff --git a/src/plugins/symbian/openmaxal/radiotuner/xaradiosessionimpl.h b/src/plugins/symbian/openmaxal/radiotuner/xaradiosessionimpl.h
new file mode 100644
index 000000000..ee5f53a2f
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/radiotuner/xaradiosessionimpl.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** 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$
+** 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 XARADIOSESSIONIMPL_H
+#define XARADIOSESSIONIMPL_H
+
+#include <OpenMAXAL.h>
+#include <xanokialinearvolumeitf.h>
+#include <xanokiavolumeextitf.h>
+#include <qradiotuner.h>
+#include <qtmedianamespace.h>
+
+QT_USE_NAMESPACE
+
+class XARadioSessionImplObserver;
+
+class XARadioSessionImpl
+{
+public:
+ XARadioSessionImpl(XARadioSessionImplObserver& parent);
+ ~XARadioSessionImpl();
+ QRadioTuner::Error PostConstruct();
+ QRadioTuner::Band Band() const;
+ QRadioTuner::State State() const;
+ QtMultimediaKit::AvailabilityError AvailabilityError() const;
+ bool IsAvailable() const;
+ void SetBand(QRadioTuner::Band band);
+ bool IsBandSupported(QRadioTuner::Band band) const;
+ TInt FrequencyStep(QRadioTuner::Band band) const;
+ bool IsStereo(); //const;
+ bool IsMuted() const;
+ bool IsSearching() const;
+ TInt GetFrequency();
+ TInt GetFrequencyRange();
+ TInt GetFrequencyRangeProperties(TInt range, TInt &minFreq, TInt &maxFreq);
+ TInt SetFrequency(TInt aFreq);
+ QRadioTuner::StereoMode StereoMode();
+ TInt SetStereoMode(QRadioTuner::StereoMode stereoMode);
+ TInt GetSignalStrength();
+ TInt GetVolume();
+ TInt SetVolume(TInt aVolume);
+ TInt SetMuted(TBool aMuted);
+ TInt Seek(TBool aDirection);
+ TInt StopSeeking();
+ void Start();
+ void Stop();
+ QRadioTuner::Error Error();
+//TInt ErrorString();
+ void StateChanged(QRadioTuner::State state);
+ void FrequencyChanged(XAuint32 freq);
+ void SearchingChanged(TBool isSearching);
+ void StereoStatusChanged(TBool stereoStatus);
+ void SignalStrengthChanged(TBool stereoStatus);
+ void VolumeChanged();
+ void MutedChanged(TBool mute);
+
+private:
+ TInt CreateEngine();
+ TInt CheckErr(XAresult res);
+
+
+private:
+ XARadioSessionImplObserver& iParent;
+ XAObjectItf iRadio;
+ XAObjectItf iEngine;
+ XAObjectItf iPlayer;
+ XAEngineItf iEngineItf;
+ XARecordItf iRecordItf;
+ XAPlayItf iPlayItf;
+ XARadioItf iRadioItf;
+ XARDSItf iRdsItf;
+ XANokiaVolumeExtItf iNokiaVolumeExtItf; // used for mute functionality
+ XANokiaLinearVolumeItf iNokiaLinearVolumeItf; // used for volume functionality
+
+ /* Audio Source */
+ XADataSource iDataSource;
+
+ /*Audio Sink*/
+ XADataSink iAudioSink;
+ XADataLocator_OutputMix iLocator_outputmix;
+
+ TBool iAutoFlag;
+ TBool iSearching;
+ TBool iRadioAvailable;
+ QtMultimediaKit::AvailabilityError iAvailabilityError;
+ QRadioTuner::Band iBand;
+ QRadioTuner::State iState;
+};
+
+#endif /* XARADIOSESSIONIMPL_H */
diff --git a/src/plugins/symbian/openmaxal/radiotuner/xaradiosessionimplobserver.h b/src/plugins/symbian/openmaxal/radiotuner/xaradiosessionimplobserver.h
new file mode 100644
index 000000000..73c734fd3
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/radiotuner/xaradiosessionimplobserver.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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$
+** 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 XARADIOSESSIONIMPLOBSERVER_H
+#define XARADIOSESSIONIMPLOBSERVER_H
+
+#include <e32base.h>
+#include <qradiotuner.h>
+
+QT_USE_NAMESPACE
+
+class XARadioSessionImplObserver
+{
+public:
+ virtual void CBStateChanged(QRadioTuner::State state) = 0;
+ virtual void CBBandChanged(QRadioTuner::Band band) = 0;
+ virtual void CBFrequencyChanged(TInt newFrequency) = 0;
+ virtual void CBStereoStatusChanged(bool isStereo) = 0;
+ virtual void CBSignalStrengthChanged(int signalStrength) = 0;
+ virtual void CBVolumeChanged(int volume) = 0;
+ virtual void CBMutedChanged(bool isMuted) = 0;
+ virtual void CBSearchingChanged(bool isSearching) = 0;
+ virtual void CBError(QRadioTuner::Error err) = 0;
+};
+
+#endif /*XARADIOSESSIONIMPLOBSERVER_H*/
diff --git a/src/plugins/symbian/openmaxal/xacommon.h b/src/plugins/symbian/openmaxal/xacommon.h
new file mode 100644
index 000000000..9aecbc8f5
--- /dev/null
+++ b/src/plugins/symbian/openmaxal/xacommon.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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$
+** 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 XACOMMON_H
+#define XACOMMON_H
+
+#ifdef PLUGIN_SYMBIAN_TRACE_ENABLED
+# include <e32debug.h>
+#endif /* PLUGIN_SYMBIAN_TRACE_ENABLED */
+
+#ifdef PLUGIN_SYMBIAN_TRACE_ENABLED
+# define TRACE_FUNCTION_ENTRY RDebug::Printf( "%s >", __PRETTY_FUNCTION__)
+# define TRACE_FUNCTION_EXIT RDebug::Printf( "%s <", __PRETTY_FUNCTION__)
+# define TRACE_FUNCTION_ENTRY_EXIT RDebug::Printf( "%s ><", __PRETTY_FUNCTION__)
+# define TRACE_LOG(s) RDebug::Print s
+#else
+# define TRACE_FUNCTION_ENTRY
+# define TRACE_FUNCTION_EXIT
+# define TRACE_FUNCTION_ENTRY_EXIT
+# define TRACE_LOG
+#endif /* PLUGIN_SYMBIAN_TRACE_ENABLED */
+
+#define RET_IF_FALSE(e) \
+ if (e == false) \
+ { \
+ return; \
+ }
+
+#define RET_BOOL_IF_FALSE(e) \
+ if (e == false) \
+ { \
+ return e; \
+ }
+
+#define RET_ERR_IF_ERR(e) \
+ if (e != 0) \
+ { \
+ return e; \
+ }
+
+#endif /* XACOMMON_H */
diff --git a/src/plugins/symbian/symbian.pro b/src/plugins/symbian/symbian.pro
new file mode 100644
index 000000000..7fc2c8690
--- /dev/null
+++ b/src/plugins/symbian/symbian.pro
@@ -0,0 +1,23 @@
+######################################################################
+#
+# Mobility API project - Symbian backends
+#
+######################################################################
+
+TEMPLATE = subdirs
+
+include (../../../config.pri)
+
+# The openmax-al backend is currently not supported
+# we include mmf only if we are not building openmaxal based backend
+#contains(openmaxal_symbian_enabled, no) {
+# message("Enabling mmf mediarecording, playback and radio backend")
+# symbian:SUBDIRS += mmf
+#
+#else {
+# message("Enabling OpenMAX AL audio record, playback and radio backend")
+# symbian:SUBDIRS += openmaxal
+#
+
+symbian:SUBDIRS += ecam mmf
+
diff --git a/src/plugins/symbian/videooutput/s60videodisplay.cpp b/src/plugins/symbian/videooutput/s60videodisplay.cpp
new file mode 100644
index 000000000..35e234e98
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videodisplay.cpp
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** 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$
+** 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 "s60videodisplay.h"
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include <coecntrl.h>
+#include <w32std.h>
+
+S60VideoDisplay::S60VideoDisplay(QObject *parent)
+: QObject(parent)
+, m_fullScreen(false)
+, m_visible(true)
+, m_aspectRatioMode(Qt::KeepAspectRatio)
+, m_paintingEnabled(false)
+, m_rotation(0.0f)
+{
+ connect(this, SIGNAL(displayRectChanged(QRect, QRect)),
+ this, SLOT(updateContentRect()));
+ connect(this, SIGNAL(nativeSizeChanged(QSize)),
+ this, SLOT(updateContentRect()));
+}
+
+S60VideoDisplay::~S60VideoDisplay()
+{
+
+}
+
+RWindow *S60VideoDisplay::windowHandle() const
+{
+ return winId() ? static_cast<RWindow *>(winId()->DrawableWindow()) : 0;
+}
+
+QRect S60VideoDisplay::clipRect() const
+{
+ QRect displayableRect;
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ if (RWindow *window = windowHandle())
+ displayableRect = QRect(0, 0, window->Size().iWidth, window->Size().iHeight);
+#else
+ displayableRect = QApplication::desktop()->screenGeometry();
+#endif
+ return extentRect().intersected(displayableRect);
+}
+
+QRect S60VideoDisplay::contentRect() const
+{
+ return m_contentRect;
+}
+
+void S60VideoDisplay::setFullScreen(bool enabled)
+{
+ if (m_fullScreen != enabled) {
+ m_fullScreen = enabled;
+ emit fullScreenChanged(m_fullScreen);
+ }
+}
+
+bool S60VideoDisplay::isFullScreen() const
+{
+ return m_fullScreen;
+}
+
+void S60VideoDisplay::setVisible(bool enabled)
+{
+ if (m_visible != enabled) {
+ m_visible = enabled;
+ emit visibilityChanged(m_visible);
+ }
+}
+
+bool S60VideoDisplay::isVisible() const
+{
+ return m_visible;
+}
+
+void S60VideoDisplay::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ if (m_aspectRatioMode != mode) {
+ m_aspectRatioMode = mode;
+ emit aspectRatioModeChanged(m_aspectRatioMode);
+ }
+}
+
+Qt::AspectRatioMode S60VideoDisplay::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void S60VideoDisplay::setNativeSize(const QSize &size)
+{
+ if (m_nativeSize != size) {
+ m_nativeSize = size;
+ emit nativeSizeChanged(m_nativeSize);
+ }
+}
+
+const QSize& S60VideoDisplay::nativeSize() const
+{
+ return m_nativeSize;
+}
+
+void S60VideoDisplay::setPaintingEnabled(bool enabled)
+{
+ if (m_paintingEnabled != enabled) {
+ m_paintingEnabled = enabled;
+ emit paintingEnabledChanged(m_paintingEnabled);
+ }
+}
+
+bool S60VideoDisplay::isPaintingEnabled() const
+{
+ return m_paintingEnabled;
+}
+
+void S60VideoDisplay::setRotation(qreal value)
+{
+ if (value != m_rotation) {
+ m_rotation = value;
+ emit rotationChanged(m_rotation);
+ }
+}
+
+qreal S60VideoDisplay::rotation() const
+{
+ return m_rotation;
+}
+
+void S60VideoDisplay::updateContentRect()
+{
+ if (isPaintingEnabled()) {
+ const int dx = qMax(0, extentRect().width() - nativeSize().width());
+ const int dy = qMax(0, extentRect().height() - nativeSize().height());
+ QRect contentRect(QPoint(dx/2, dy/2), nativeSize());
+ if (m_contentRect != contentRect) {
+ m_contentRect = contentRect;
+ emit contentRectChanged(m_contentRect);
+ }
+ }
+}
+
diff --git a/src/plugins/symbian/videooutput/s60videodisplay.h b/src/plugins/symbian/videooutput/s60videodisplay.h
new file mode 100644
index 000000000..e16e7bb71
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videodisplay.h
@@ -0,0 +1,188 @@
+/**
+** 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$
+** 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 S60VIDEODISPLAY_H
+#define S60VIDEODISPLAY_H
+
+#include <QtCore/QMetaType>
+#include <QtCore/QObject>
+#include <QtCore/QRect>
+#include <QtCore/QSize>
+#include <QtGui/qwindowdefs.h>
+
+class CFbsBitmap;
+class RWindow;
+
+QT_USE_NAMESPACE
+
+/*
+ * This class defines a common API used by Symbian camera and mediaplayer
+ * backends to render to on-screen video outputs, i.e. implementations of
+ * QVideoWidgetControl and QVideoWindowControl.
+ */
+class S60VideoDisplay : public QObject
+{
+ Q_OBJECT
+public:
+ S60VideoDisplay(QObject *parent);
+ virtual ~S60VideoDisplay();
+
+ /*
+ * Returns native Symbian handle of the window to be used for rendering
+ */
+ RWindow *windowHandle() const;
+
+ /*
+ * Returns Qt WId (CCoeControl* on Symbian)
+ */
+ virtual WId winId() const = 0;
+
+ /*
+ * Returns video display rectangle
+ *
+ * This is the rectangle which includes both the video content itself, plus
+ * any border bars which added around the video. The aspect ratio of this
+ * rectangle therefore may differ from that of the nativeSize().
+ *
+ * If running on a platform supporting video rendering to graphics
+ * surfaces (i.e. if VIDEOOUTPUT_GRAPHICS_SURFACES is defined), the return
+ * value is the relative to the origin of the video window. Otherwise, the
+ * return value is an absolute screen rectangle.
+ *
+ * Note that this rectangle can extend beyond the bounds of the screen or of
+ * the video window.
+ *
+ * When using QVideoWindowControl, the size of the extentRect matches the
+ * displayRect; if running on a platform which supports only DSA rendering,
+ * the origin differs as described above.
+ *
+ * See also clipRect, contentRect
+ */
+ virtual QRect extentRect() const = 0;
+
+ /*
+ * Returns video clipping rectangle
+ *
+ * This rectangle is the intersection of displayRect() with either the window
+ * rectangle (on platforms supporting video rendering to graphics surfaces),
+ * or the screen rectangle (on platforms supporting only DSA video rendering).
+ *
+ * If running on a platform supporting video rendering to graphics
+ * surfaces (i.e. if VIDEOOUTPUT_GRAPHICS_SURFACES is defined), the return
+ * value is the relative to the origin of the video window. Otherwise, the
+ * return value is an absolute screen rectangle.
+ *
+ * See also extentRect, contentRect
+ */
+ QRect clipRect() const;
+
+ /*
+ * Returns video content rectangle
+ *
+ * This is the rectangle in which the video content is rendered, i.e. its
+ * size is that of extentRect() minus border bars. The aspect ratio of this
+ * rectangle is therefore equal to that of the nativeSize().
+ *
+ * This rectangle is always relative to the window in which video is rendered.
+ *
+ * See also extentRect, clipRect
+ */
+ QRect contentRect() const;
+
+ void setFullScreen(bool enabled);
+ bool isFullScreen() const;
+
+ void setVisible(bool visible);
+ bool isVisible() const;
+
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+ Qt::AspectRatioMode aspectRatioMode() const;
+
+ const QSize& nativeSize() const;
+
+ void setPaintingEnabled(bool enabled);
+ bool isPaintingEnabled() const;
+
+ void setRotation(qreal value);
+ qreal rotation() const;
+
+public slots:
+ void setNativeSize(const QSize &size);
+
+ /*
+ * Provide new video frame
+ *
+ * If setPaintingEnabled(true) has been called, the frame is rendered to
+ * the display.
+ *
+ * If a QWidget is available to the control (i.e. the control is a
+ * QVideoWidgetControl), the frame is rendered via QPainter. Otherwise, the
+ * frame is blitted to the window using native Symbian drawing APIs.
+ */
+ virtual void setFrame(const CFbsBitmap &bitmap) = 0;
+
+signals:
+ void windowHandleChanged(RWindow *);
+ void displayRectChanged(QRect extentRect, QRect clipRect);
+ void fullScreenChanged(bool);
+ void visibilityChanged(bool);
+ void aspectRatioModeChanged(Qt::AspectRatioMode);
+ void nativeSizeChanged(QSize);
+ void contentRectChanged(QRect);
+ void paintingEnabledChanged(bool);
+ void rotationChanged(qreal);
+ void beginVideoWindowNativePaint();
+ void endVideoWindowNativePaint();
+
+private slots:
+ void updateContentRect();
+
+private:
+ QRect m_contentRect;
+ bool m_fullScreen;
+ bool m_visible;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QSize m_nativeSize;
+ bool m_paintingEnabled;
+ qreal m_rotation;
+};
+
+#endif // S60VIDEODISPLAY_H
+
diff --git a/src/plugins/symbian/videooutput/s60videooutpututils.cpp b/src/plugins/symbian/videooutput/s60videooutpututils.cpp
new file mode 100644
index 000000000..feac346d1
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videooutpututils.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** 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$
+** 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 "s60videooutpututils.h"
+
+#ifdef PRIVATE_QTGUI_HEADERS_AVAILABLE
+#if QT_VERSION >= 0x040601 && !defined(__WINSCW__)
+#include <QtGui/private/qt_s60_p.h>
+#include <QtGui/private/qwidget_p.h>
+#define USE_PRIVATE_QTGUI_APIS
+#endif // QT_VERSION >= 0x040601 && !defined(__WINSCW__)
+#endif // PRIVATE_QTGUI_HEADERS_AVAILABLE
+
+namespace S60VideoOutputUtils
+{
+
+void setIgnoreFocusChanged(QWidget *widget)
+{
+#ifdef USE_PRIVATE_QTGUI_APIS
+ // Warning: if this flag is not set, the application may crash due to
+ // CGraphicsContext being called from within the context of
+ // QGraphicsVideoItem::paint(), when the video widget is shown.
+ static_cast<QSymbianControl *>(widget->winId())->setIgnoreFocusChanged(true);
+#else
+ Q_UNUSED(widget)
+#endif
+}
+
+void setNativePaintMode(QWidget *widget, NativePaintMode mode)
+{
+#ifdef USE_PRIVATE_QTGUI_APIS
+ QWidgetPrivate *widgetPrivate = qt_widget_private(widget->window());
+ widgetPrivate->createExtra();
+ QWExtra::NativePaintMode widgetMode = QWExtra::Default;
+ switch (mode) {
+ case Default:
+ break;
+ case ZeroFill:
+ widgetMode = QWExtra::ZeroFill;
+ break;
+ case BlitWriteAlpha:
+#if QT_VERSION >= 0x040704
+ widgetMode = QWExtra::BlitWriteAlpha;
+#endif
+ break;
+ case Disable:
+ widgetMode = QWExtra::Disable;
+ break;
+ }
+ widgetPrivate->extraData()->nativePaintMode = widgetMode;
+#else
+ Q_UNUSED(widget)
+ Q_UNUSED(mode)
+#endif
+}
+
+void setNativePaintMode(WId wid, NativePaintMode mode)
+{
+#ifdef USE_PRIVATE_QTGUI_APIS
+ QWidget *window = static_cast<QSymbianControl *>(wid)->widget()->window();
+ setNativePaintMode(window, mode);
+#else
+ Q_UNUSED(wid)
+ Q_UNUSED(mode)
+#endif
+}
+
+void setReceiveNativePaintEvents(QWidget *widget, bool enabled)
+{
+#ifdef USE_PRIVATE_QTGUI_APIS
+ QWidgetPrivate *widgetPrivate = qt_widget_private(widget);
+ widgetPrivate->createExtra();
+ widgetPrivate->extraData()->receiveNativePaintEvents = enabled;
+#else
+ Q_UNUSED(widget)
+ Q_UNUSED(enabled)
+#endif
+}
+
+} // namespace S60VideoOutputUtils
+
diff --git a/src/plugins/symbian/videooutput/s60videooutpututils.h b/src/plugins/symbian/videooutput/s60videooutpututils.h
new file mode 100644
index 000000000..6d83062c3
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videooutpututils.h
@@ -0,0 +1,71 @@
+/**
+** 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$
+** 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 S60VIDEOOUTPUTUTILS_H
+#define S60VIDEOOUTPUTUTILS_H
+
+#include <QtCore/qglobal.h>
+#include <QtGui/qwindowdefs.h>
+
+QT_FORWARD_DECLARE_CLASS(QWidget)
+
+/*
+ * Helper functions used by video output.
+ */
+namespace S60VideoOutputUtils
+{
+
+enum NativePaintMode
+{
+ Default,
+ ZeroFill,
+ BlitWriteAlpha,
+ Disable
+};
+
+void setIgnoreFocusChanged(QWidget *widget);
+void setNativePaintMode(QWidget *widget, NativePaintMode mode);
+void setNativePaintMode(WId wid, NativePaintMode mode);
+void setReceiveNativePaintEvents(QWidget *widget, bool enabled);
+
+} // namespace S60VideoOutputUtils
+
+#endif // S60VIDEOOUTPUTUTILS_H
+
diff --git a/src/plugins/symbian/videooutput/s60videowidget.cpp b/src/plugins/symbian/videooutput/s60videowidget.cpp
new file mode 100644
index 000000000..44c0919ba
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videowidget.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** 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$
+** 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 "s60videowidget.h"
+#include "s60videooutpututils.h"
+
+#include <QtCore/QVariant>
+#include <QtCore/QEvent>
+#include <QtGui/QApplication>
+#include <QtGui/QPainter>
+
+#include <coemain.h> // CCoeEnv
+#include <coecntrl.h> // CCoeControl
+#include <w32std.h>
+
+using namespace S60VideoOutputUtils;
+
+const int NullOrdinalPosition = -1;
+
+S60VideoWidget::S60VideoWidget(QWidget *parent)
+: QWidget(parent)
+, m_pixmap(NULL)
+, m_paintingEnabled(false)
+, m_topWinId(0)
+, m_ordinalPosition(NullOrdinalPosition)
+{
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ setPalette(QPalette(Qt::black));
+ setAutoFillBackground(false);
+ if (!parent)
+ setProperty("_q_DummyWindowSurface", true);
+ S60VideoOutputUtils::setIgnoreFocusChanged(this);
+}
+
+S60VideoWidget::~S60VideoWidget()
+{
+
+}
+
+bool S60VideoWidget::event(QEvent *event)
+{
+ if (event->type() == QEvent::WinIdChange)
+ updateOrdinalPosition();
+ return QWidget::event(event);
+}
+
+void S60VideoWidget::paintEvent(QPaintEvent *event)
+{
+ if (m_paintingEnabled && m_pixmap) {
+ QPainter painter(this);
+ if (m_pixmap->size() != m_contentRect.size())
+ qWarning("pixmap size does not match expected value");
+ painter.drawPixmap(m_contentRect.topLeft(), *m_pixmap);
+ }
+}
+
+void S60VideoWidget::setVisible(bool visible)
+{
+ queueReactivateWindow();
+ QWidget::setVisible(visible);
+}
+
+
+WId S60VideoWidget::videoWinId() const
+{
+ WId wid = 0;
+ if (internalWinId())
+ wid = internalWinId();
+ else if (parentWidget() && effectiveWinId())
+ wid = effectiveWinId();
+ return wid;
+}
+
+void S60VideoWidget::setPixmap(const QPixmap *pixmap)
+{
+ m_pixmap = pixmap;
+ update();
+}
+
+void S60VideoWidget::setContentRect(const QRect &rect)
+{
+ if (m_contentRect != rect) {
+ m_contentRect = rect;
+ update();
+ }
+}
+
+void S60VideoWidget::setWindowBackgroundColor()
+{
+ if (WId wid = internalWinId())
+ static_cast<RWindow *>(wid->DrawableWindow())->SetBackgroundColor(TRgb(0, 0, 0, 255));
+}
+
+WId S60VideoWidget::topWinId() const
+{
+ return m_topWinId;
+}
+
+void S60VideoWidget::setTopWinId(WId id)
+{
+ m_topWinId = id;
+ updateOrdinalPosition();
+#ifdef VIDEOOUTPUT_GRAPHICS_SURFACES
+ // This function may be called from a paint event, so defer any window
+ // manipulation until painting is complete.
+ QMetaObject::invokeMethod(this, "setWindowsNonFading", Qt::QueuedConnection);
+#endif
+}
+
+void S60VideoWidget::setOrdinalPosition(int ordinalPosition)
+{
+ m_ordinalPosition = ordinalPosition;
+ updateOrdinalPosition();
+}
+
+int S60VideoWidget::ordinalPosition() const
+{
+ return m_ordinalPosition;
+}
+
+void S60VideoWidget::updateOrdinalPosition()
+{
+ if ((m_ordinalPosition != NullOrdinalPosition) && m_topWinId) {
+ if (WId wid = videoWinId()) {
+ int topOrdinalPosition = m_topWinId->DrawableWindow()->OrdinalPosition();
+ queueReactivateWindow();
+ wid->DrawableWindow()->SetOrdinalPosition(m_ordinalPosition + topOrdinalPosition);
+ }
+ }
+}
+
+void S60VideoWidget::queueReactivateWindow()
+{
+ if (!parent()) {
+ if (QWidget *activeWindow = QApplication::activeWindow())
+ QMetaObject::invokeMethod(this, "reactivateWindow", Qt::QueuedConnection,
+ Q_ARG(QWidget *, activeWindow));
+ }
+}
+
+void S60VideoWidget::reactivateWindow(QWidget *widget)
+{
+ widget->activateWindow();
+}
+
+void S60VideoWidget::setWindowsNonFading()
+{
+ winId()->DrawableWindow()->SetNonFading(ETrue);
+ if (m_topWinId)
+ m_topWinId->DrawableWindow()->SetNonFading(ETrue);
+}
+
+void S60VideoWidget::beginNativePaintEvent(const QRect &rect)
+{
+ Q_UNUSED(rect)
+ emit beginVideoWidgetNativePaint();
+}
+
+void S60VideoWidget::endNativePaintEvent(const QRect &rect)
+{
+ Q_UNUSED(rect)
+ CCoeEnv::Static()->WsSession().Flush();
+ emit endVideoWidgetNativePaint();
+}
+
+void S60VideoWidget::setPaintingEnabled(bool enabled)
+{
+ if (enabled) {
+#ifndef VIDEOOUTPUT_GRAPHICS_SURFACES
+ setAttribute(Qt::WA_OpaquePaintEvent, false);
+ setAttribute(Qt::WA_NoSystemBackground, false);
+ S60VideoOutputUtils::setReceiveNativePaintEvents(this, false);
+ S60VideoOutputUtils::setNativePaintMode(this, Default);
+#else
+ S60VideoOutputUtils::setNativePaintMode(this, Default);
+#endif // !VIDEOOUTPUT_GRAPHICS_SURFACES
+ } else {
+#ifndef VIDEOOUTPUT_GRAPHICS_SURFACES
+ setAttribute(Qt::WA_OpaquePaintEvent, true);
+ setAttribute(Qt::WA_NoSystemBackground, true);
+ S60VideoOutputUtils::setReceiveNativePaintEvents(this, true);
+ S60VideoOutputUtils::setNativePaintMode(this, ZeroFill);
+#else
+ S60VideoOutputUtils::setNativePaintMode(this, Disable);
+#endif // !VIDEOOUTPUT_GRAPHICS_SURFACES
+ winId(); // Create native window handle
+ }
+ m_paintingEnabled = enabled;
+ setWindowBackgroundColor();
+}
+
+void S60VideoWidget::setFullScreen(bool enabled)
+{
+ if (enabled)
+ showFullScreen();
+ else
+ showMaximized();
+}
+
diff --git a/src/plugins/symbian/videooutput/s60videowidget.h b/src/plugins/symbian/videooutput/s60videowidget.h
new file mode 100644
index 000000000..30e7a3bd0
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videowidget.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60VIDEOWIDGET_H
+#define S60VIDEOWIDGET_H
+
+#include <QtGui/QWidget>
+
+QT_USE_NAMESPACE
+
+class S60VideoWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ S60VideoWidget(QWidget *parent = 0);
+ ~S60VideoWidget();
+
+ // QWidget
+ bool event(QEvent *event);
+ void paintEvent(QPaintEvent *event);
+ void setVisible(bool visible);
+
+ WId videoWinId() const;
+ void setPixmap(const QPixmap *pixmap);
+ void setWindowBackgroundColor();
+ void setTopWinId(WId id);
+ WId topWinId() const;
+ void setOrdinalPosition(int ordinalPosition);
+ int ordinalPosition() const;
+
+public slots:
+ void beginNativePaintEvent(const QRect &rect);
+ void endNativePaintEvent(const QRect &rect);
+ void setPaintingEnabled(bool enabled);
+ void setFullScreen(bool enabled);
+ void setContentRect(const QRect &rect);
+
+signals:
+ void beginVideoWidgetNativePaint();
+ void endVideoWidgetNativePaint();
+
+private:
+ void updateOrdinalPosition();
+ void queueReactivateWindow();
+
+private slots:
+ void reactivateWindow(QWidget *window);
+ void setWindowsNonFading();
+
+private:
+ const QPixmap *m_pixmap;
+ QRect m_contentRect;
+ bool m_paintingEnabled;
+ WId m_topWinId;
+ int m_ordinalPosition;
+};
+
+#endif // S60VIDEOWIDGET_H
+
diff --git a/src/plugins/symbian/videooutput/s60videowidgetcontrol.cpp b/src/plugins/symbian/videooutput/s60videowidgetcontrol.cpp
new file mode 100644
index 000000000..46cb2963e
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videowidgetcontrol.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** 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$
+** 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 "s60videowidgetcontrol.h"
+#include "s60videowidgetdisplay.h"
+
+S60VideoWidgetControl::S60VideoWidgetControl(QObject *parent)
+: QVideoWidgetControl(parent)
+, m_display(new S60VideoWidgetDisplay(this))
+{
+ connect(m_display, SIGNAL(nativeSizeChanged(QSize)),
+ this, SIGNAL(nativeSizeChanged()));
+}
+
+S60VideoWidgetControl::~S60VideoWidgetControl()
+{
+
+}
+
+QWidget *S60VideoWidgetControl::videoWidget()
+{
+ return m_display->widget();
+}
+
+Qt::AspectRatioMode S60VideoWidgetControl::aspectRatioMode() const
+{
+ return m_display->aspectRatioMode();
+}
+
+void S60VideoWidgetControl::setAspectRatioMode(Qt::AspectRatioMode ratio)
+{
+ m_display->setAspectRatioMode(ratio);
+}
+
+bool S60VideoWidgetControl::isFullScreen() const
+{
+ return m_display->isFullScreen();
+}
+
+void S60VideoWidgetControl::setFullScreen(bool fullScreen)
+{
+ m_display->setFullScreen(fullScreen);
+}
+
+int S60VideoWidgetControl::brightness() const
+{
+ return 0;
+}
+
+void S60VideoWidgetControl::setBrightness(int brightness)
+{
+ Q_UNUSED(brightness);
+}
+
+int S60VideoWidgetControl::contrast() const
+{
+ return 0;
+}
+
+void S60VideoWidgetControl::setContrast(int contrast)
+{
+ Q_UNUSED(contrast);
+}
+
+int S60VideoWidgetControl::hue() const
+{
+ return 0;
+}
+
+void S60VideoWidgetControl::setHue(int hue)
+{
+ Q_UNUSED(hue);
+}
+
+int S60VideoWidgetControl::saturation() const
+{
+ return 0;
+}
+
+void S60VideoWidgetControl::setSaturation(int saturation)
+{
+ Q_UNUSED(saturation);
+}
+
+S60VideoWidgetDisplay *S60VideoWidgetControl::display() const
+{
+ return m_display;
+}
+
+void S60VideoWidgetControl::setTopWinId(WId id)
+{
+ m_display->setTopWinId(id);
+}
+
+WId S60VideoWidgetControl::topWinId() const
+{
+ return m_display->topWinId();
+}
+
+int S60VideoWidgetControl::ordinalPosition() const
+{
+ return m_display->ordinalPosition();
+}
+
+void S60VideoWidgetControl::setOrdinalPosition(int ordinalPosition)
+{
+ m_display->setOrdinalPosition(ordinalPosition);
+}
+
+const QRect &S60VideoWidgetControl::extentRect() const
+{
+ return m_display->explicitExtentRect();
+}
+
+void S60VideoWidgetControl::setExtentRect(const QRect &rect)
+{
+ m_display->setExplicitExtentRect(rect);
+}
+
+QSize S60VideoWidgetControl::nativeSize() const
+{
+ return m_display->nativeSize();
+}
+
+qreal S60VideoWidgetControl::rotation() const
+{
+ return m_display->rotation();
+}
+
+void S60VideoWidgetControl::setRotation(qreal value)
+{
+ m_display->setRotation(value);
+}
diff --git a/src/plugins/symbian/videooutput/s60videowidgetcontrol.h b/src/plugins/symbian/videooutput/s60videowidgetcontrol.h
new file mode 100644
index 000000000..eb103b6b8
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videowidgetcontrol.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60VIDEOWIDGETCONTROL_H
+#define S60VIDEOWIDGETCONTROL_H
+
+#include <qvideowidgetcontrol.h>
+
+QT_USE_NAMESPACE
+
+class S60VideoWidgetDisplay;
+
+class S60VideoWidgetControl : public QVideoWidgetControl
+{
+ Q_OBJECT
+
+ /**
+ * WId of the topmost window in the application, used to calculate the
+ * absolute ordinal position of the video widget.
+ * This is used by the "window" implementation of QGraphicsVideoItem.
+ */
+ Q_PROPERTY(WId topWinId READ topWinId WRITE setTopWinId)
+
+ /**
+ * Ordinal position of the video widget, relative to the topmost window
+ * in the application. If both the topWinId property and the ordinalPosition
+ * property are set, the absolute ordinal position of the video widget is
+ * the sum of the topWinId ordinal position and the value of the
+ * ordinalPosition property.
+ * This is used by the "window" implementation of QGraphicsVideoItem.
+ */
+ Q_PROPERTY(int ordinalPosition READ ordinalPosition WRITE setOrdinalPosition)
+
+ /**
+ * Extent of the video, relative to this video widget.
+ * This is used by the "window" implementation of QGraphicsVideoItem.
+ */
+ Q_PROPERTY(QRect extentRect READ extentRect WRITE setExtentRect)
+
+ /**
+ * Native size of video.
+ * This is used by the "window" implementation of QGraphicsVideoItem.
+ */
+ Q_PROPERTY(QSize nativeSize READ nativeSize)
+
+ /**
+ * Rotation to be applied to video.
+ * Angle is measured in degrees, with positive values counter-clockwise.
+ * Zero is at 12 o'clock.
+ */
+ Q_PROPERTY(qreal rotation READ rotation WRITE setRotation)
+
+public:
+ S60VideoWidgetControl(QObject *parent);
+ ~S60VideoWidgetControl();
+
+public:
+ // QVideoWidgetControl
+ QWidget *videoWidget();
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode ratio);
+ bool isFullScreen() const;
+ void setFullScreen(bool fullScreen);
+ int brightness() const;
+ void setBrightness(int brightness);
+ int contrast() const;
+ void setContrast(int contrast);
+ int hue() const;
+ void setHue(int hue);
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ S60VideoWidgetDisplay *display() const;
+
+ WId topWinId() const;
+ void setTopWinId(WId id);
+ int ordinalPosition() const;
+ void setOrdinalPosition(int ordinalPosition);
+ const QRect &extentRect() const;
+ void setExtentRect(const QRect &rect);
+ QSize nativeSize() const;
+ qreal rotation() const;
+ void setRotation(qreal value);
+
+signals:
+ void nativeSizeChanged();
+
+private:
+ S60VideoWidgetDisplay *m_display;
+};
+
+#endif // S60VIDEOWIDGETCONTROL_H
+
diff --git a/src/plugins/symbian/videooutput/s60videowidgetdisplay.cpp b/src/plugins/symbian/videooutput/s60videowidgetdisplay.cpp
new file mode 100644
index 000000000..de7440dbf
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videowidgetdisplay.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** 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$
+** 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 "s60videowidget.h"
+#include "s60videowidgetdisplay.h"
+#include <QtCore/QEvent>
+#include <QtCore/QVariant>
+#include <fbs.h>
+#include <w32std.h>
+
+S60VideoWidgetDisplay::S60VideoWidgetDisplay(QObject *parent)
+: S60VideoDisplay(parent)
+, m_widget(new S60VideoWidget)
+{
+ connect(this, SIGNAL(paintingEnabledChanged(bool)), m_widget, SLOT(setPaintingEnabled(bool)));
+ connect(this, SIGNAL(fullScreenChanged(bool)), m_widget, SLOT(setFullScreen(bool)));
+ connect(this, SIGNAL(contentRectChanged(const QRect&)), m_widget, SLOT(setContentRect(const QRect &)));
+#ifndef VIDEOOUTPUT_GRAPHICS_SURFACES
+ connect(m_widget, SIGNAL(beginVideoWidgetNativePaint()), this, SIGNAL(beginVideoWindowNativePaint()));
+ connect(m_widget, SIGNAL(endVideoWidgetNativePaint()), this, SIGNAL(endVideoWindowNativePaint()));
+#endif
+ m_widget->installEventFilter(this);
+ m_widget->setPaintingEnabled(false);
+}
+
+S60VideoWidgetDisplay::~S60VideoWidgetDisplay()
+{
+ // Notify observers that window is about to be destroyed
+ QScopedPointer<QWidget> widget(m_widget);
+ m_widget = 0;
+ emit windowHandleChanged(windowHandle());
+ // Widget will be deleted by QScopedPointer
+}
+
+bool S60VideoWidgetDisplay::eventFilter(QObject *object, QEvent *e)
+{
+ if (object == m_widget) {
+ switch (e->type()) {
+ case QEvent::ParentChange:
+ if (QWidget *parent = m_widget->parentWidget())
+ parent->setProperty("_q_DummyWindowSurface", true);
+ break;
+ case QEvent::WinIdChange:
+ m_widget->setWindowBackgroundColor();
+ emit windowHandleChanged(windowHandle());
+ break;
+ case QEvent::Resize:
+ emit displayRectChanged(extentRect(), clipRect());
+ break;
+#ifndef VIDEOOUTPUT_GRAPHICS_SURFACES
+ case QEvent::Move:
+ // TODO: this is insufficient - we also need to respond to changes in
+ // the position of ancestor widgets
+ emit displayRectChanged(extentRect(), clipRect());
+ break;
+#endif
+ case QEvent::Show:
+ emit windowHandleChanged(windowHandle());
+ emit visibilityChanged(true);
+ break;
+ case QEvent::Hide:
+ emit visibilityChanged(false);
+ break;
+ default:
+ // Do nothing
+ break;
+ }
+ }
+ return false;
+}
+
+WId S60VideoWidgetDisplay::winId() const
+{
+ return m_widget ? m_widget->videoWinId() : 0;
+}
+
+QRect S60VideoWidgetDisplay::extentRect() const
+{
+ QRect rect;
+ if (const RWindow *window = windowHandle()) {
+ const TSize size = window ? window->Size() : TSize();
+ if (m_explicitExtentRect.isValid())
+ rect = m_explicitExtentRect;
+ else
+ rect = QRect(0, 0, size.iWidth, size.iHeight);
+#ifndef VIDEOOUTPUT_GRAPHICS_SURFACES
+ const TPoint pos = window ? window->AbsPosition() : TPoint();
+ rect.moveTopLeft(QPoint(pos.iX, pos.iY));
+#endif
+ }
+ return rect;
+}
+
+void S60VideoWidgetDisplay::setFrame(const CFbsBitmap &bitmap)
+{
+ m_pixmap = QPixmap::fromSymbianCFbsBitmap(const_cast<CFbsBitmap*>(&bitmap));
+ m_widget->setPixmap(&m_pixmap);
+}
+
+QWidget *S60VideoWidgetDisplay::widget() const
+{
+ return m_widget;
+}
+
+void S60VideoWidgetDisplay::setTopWinId(WId id)
+{
+ m_widget->setTopWinId(id);
+}
+
+WId S60VideoWidgetDisplay::topWinId() const
+{
+ return m_widget->topWinId();
+}
+
+void S60VideoWidgetDisplay::setOrdinalPosition(int ordinalPosition)
+{
+ m_widget->setOrdinalPosition(ordinalPosition);
+}
+
+int S60VideoWidgetDisplay::ordinalPosition() const
+{
+ return m_widget->ordinalPosition();
+}
+
+const QRect &S60VideoWidgetDisplay::explicitExtentRect() const
+{
+ return m_explicitExtentRect;
+}
+
+void S60VideoWidgetDisplay::setExplicitExtentRect(const QRect &rect)
+{
+ if (rect != m_explicitExtentRect) {
+ m_explicitExtentRect = rect;
+ emit displayRectChanged(extentRect(), clipRect());
+ }
+}
diff --git a/src/plugins/symbian/videooutput/s60videowidgetdisplay.h b/src/plugins/symbian/videooutput/s60videowidgetdisplay.h
new file mode 100644
index 000000000..d3d92d953
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videowidgetdisplay.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60VIDEOWIDGETDISPLAY_H
+#define S60VIDEOWIDGETDISPLAY_H
+
+#include "s60videodisplay.h"
+#include <QtGui/qwindowdefs.h>
+#include <QtGui/QPixmap>
+
+class CFbsBitmap;
+class S60VideoWidget;
+class QWidget;
+
+QT_USE_NAMESPACE
+
+class S60VideoWidgetDisplay : public S60VideoDisplay
+{
+ Q_OBJECT
+public:
+ S60VideoWidgetDisplay(QObject *parent);
+ ~S60VideoWidgetDisplay();
+
+ // QObject
+ bool eventFilter(QObject *object, QEvent *e);
+
+ // S60VideoDisplay
+ WId winId() const;
+ QRect extentRect() const;
+ void setFrame(const CFbsBitmap &bitmap);
+
+ QWidget *widget() const;
+ WId topWinId() const;
+ void setTopWinId(WId id);
+ void setOrdinalPosition(int ordinalPosition);
+ int ordinalPosition() const;
+ const QRect &explicitExtentRect() const;
+ void setExplicitExtentRect(const QRect &rect);
+
+private:
+ S60VideoWidget *m_widget;
+ QPixmap m_pixmap;
+ QRect m_explicitExtentRect;
+};
+
+#endif // S60VIDEOWIDGETDISPLAY_H
+
diff --git a/src/plugins/symbian/videooutput/s60videowindowcontrol.cpp b/src/plugins/symbian/videooutput/s60videowindowcontrol.cpp
new file mode 100644
index 000000000..db33a5f32
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videowindowcontrol.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** 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$
+** 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 "s60videowindowcontrol.h"
+#include "s60videowindowdisplay.h"
+
+S60VideoWindowControl::S60VideoWindowControl(QObject *parent)
+: QVideoWindowControl(parent)
+, m_display(new S60VideoWindowDisplay(this))
+{
+ connect(m_display, SIGNAL(nativeSizeChanged(QSize)),
+ this, SIGNAL(nativeSizeChanged()));
+ connect(m_display, SIGNAL(fullScreenChanged(bool)),
+ this, SIGNAL(fullScreenChanged(bool)));
+}
+
+S60VideoWindowControl::~S60VideoWindowControl()
+{
+
+}
+
+WId S60VideoWindowControl::winId() const
+{
+ return m_display->winId();
+}
+
+void S60VideoWindowControl::setWinId(WId id)
+{
+ m_display->setWinId(id);
+}
+
+QRect S60VideoWindowControl::displayRect() const
+{
+ return m_display->displayRect();
+}
+
+void S60VideoWindowControl::setDisplayRect(const QRect &rect)
+{
+ m_display->setDisplayRect(rect);
+}
+
+Qt::AspectRatioMode S60VideoWindowControl::aspectRatioMode() const
+{
+ return m_display->aspectRatioMode();
+}
+
+void S60VideoWindowControl::setAspectRatioMode(Qt::AspectRatioMode ratio)
+{
+ m_display->setAspectRatioMode(ratio);
+}
+
+QSize S60VideoWindowControl::customAspectRatio() const
+{
+ return QSize();
+}
+
+void S60VideoWindowControl::setCustomAspectRatio(const QSize &customRatio)
+{
+ Q_UNUSED(customRatio);
+}
+
+void S60VideoWindowControl::repaint()
+{
+ m_display->repaint();
+}
+
+int S60VideoWindowControl::brightness() const
+{
+ return 0;
+}
+
+void S60VideoWindowControl::setBrightness(int brightness)
+{
+ Q_UNUSED(brightness)
+}
+
+int S60VideoWindowControl::contrast() const
+{
+ return 0;
+}
+
+void S60VideoWindowControl::setContrast(int contrast)
+{
+ Q_UNUSED(contrast)
+}
+
+int S60VideoWindowControl::hue() const
+{
+ return 0;
+}
+
+void S60VideoWindowControl::setHue(int hue)
+{
+ Q_UNUSED(hue)
+}
+
+int S60VideoWindowControl::saturation() const
+{
+ return 0;
+}
+
+void S60VideoWindowControl::setSaturation(int saturation)
+{
+ Q_UNUSED(saturation)
+}
+
+bool S60VideoWindowControl::isFullScreen() const
+{
+ return m_display->isFullScreen();
+}
+
+void S60VideoWindowControl::setFullScreen(bool fullScreen)
+{
+ m_display->setFullScreen(fullScreen);
+}
+
+QSize S60VideoWindowControl::nativeSize() const
+{
+ return m_display->nativeSize();
+}
+
+void S60VideoWindowControl::refreshDisplay()
+{
+ m_display->refreshDisplay();
+}
+
+S60VideoWindowDisplay *S60VideoWindowControl::display() const
+{
+ return m_display;
+}
+
+qreal S60VideoWindowControl::rotation() const
+{
+ return m_display->rotation();
+}
+
+void S60VideoWindowControl::setRotation(qreal value)
+{
+ m_display->setRotation(value);
+}
diff --git a/src/plugins/symbian/videooutput/s60videowindowcontrol.h b/src/plugins/symbian/videooutput/s60videowindowcontrol.h
new file mode 100644
index 000000000..a62d29a13
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videowindowcontrol.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60VIDEOWINDOWCONTROL_H
+#define S60VIDEOWINDOWCONTROL_H
+
+#include <qvideowindowcontrol.h>
+
+class S60VideoWindowDisplay;
+
+QT_USE_NAMESPACE
+
+class S60VideoWindowControl : public QVideoWindowControl
+{
+ Q_OBJECT
+
+ /**
+ * Rotation to be applied to video.
+ * Angle is measured in degrees, with positive values counter-clockwise.
+ * Zero is at 12 o'clock.
+ */
+ Q_PROPERTY(qreal rotation READ rotation WRITE setRotation)
+
+public:
+ S60VideoWindowControl(QObject *parent);
+ ~S60VideoWindowControl();
+
+public:
+ // QVideoWindowControl
+ WId winId() const;
+ void setWinId(WId id);
+ QRect displayRect() const;
+ void setDisplayRect(const QRect &rect);
+ bool isFullScreen() const;
+ void setFullScreen(bool fullScreen);
+ void repaint();
+ QSize nativeSize() const;
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+ QSize customAspectRatio() const;
+ void setCustomAspectRatio(const QSize &customRatio);
+ int brightness() const;
+ void setBrightness(int brightness);
+ int contrast() const;
+ void setContrast(int contrast);
+ int hue() const;
+ void setHue(int hue);
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ S60VideoWindowDisplay *display() const;
+
+ qreal rotation() const;
+ void setRotation(qreal value);
+
+public slots:
+ void refreshDisplay();
+
+private:
+ S60VideoWindowDisplay *m_display;
+};
+
+#endif // S60VIDEOWINDOWCONTROL_H
+
diff --git a/src/plugins/symbian/videooutput/s60videowindowdisplay.cpp b/src/plugins/symbian/videooutput/s60videowindowdisplay.cpp
new file mode 100644
index 000000000..a8bdb8b4a
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videowindowdisplay.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** 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$
+** 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 "s60videowindowdisplay.h"
+#include "s60videooutpututils.h"
+#include <QtCore/QVariant>
+#include <coecntrl.h>
+#include <w32std.h>
+
+using namespace S60VideoOutputUtils;
+
+S60VideoWindowDisplay::S60VideoWindowDisplay(QObject *parent)
+: S60VideoDisplay(parent)
+, m_winId(0)
+, m_bitmap(0)
+{
+ parent->setProperty("colorKey", Qt::transparent);
+}
+
+S60VideoWindowDisplay::~S60VideoWindowDisplay()
+{
+
+}
+
+WId S60VideoWindowDisplay::winId() const
+{
+ return m_winId;
+}
+
+QRect S60VideoWindowDisplay::extentRect() const
+{
+ QRect rect = displayRect();
+#ifndef VIDEOOUTPUT_GRAPHICS_SURFACES
+ if (RWindow *window = windowHandle()) {
+ const TPoint windowPos = window->AbsPosition();
+ rect.translate(windowPos.iX, windowPos.iY);
+ }
+#endif // VIDEOOUTPUT_GRAPHICS_SURFACES
+ return rect;
+}
+
+void S60VideoWindowDisplay::setFrame(const CFbsBitmap &bitmap)
+{
+ m_bitmap = const_cast<CFbsBitmap*>(&bitmap);
+ if (m_winId) {
+ // Blit the bitmap into the native window owned by m_winId
+ CWindowGc &gc = m_winId->SystemGc();
+ RWindow *window = windowHandle();
+ gc.Activate(*window);
+ const QPoint offsetQ = displayRect().topLeft() + contentRect().topLeft();
+ const TPoint offsetT(offsetQ.x(), offsetQ.y());
+ const TRect winRect(offsetT, m_bitmap->SizeInPixels());
+ window->BeginRedraw(winRect);
+ gc.BitBlt(offsetT, m_bitmap);
+ window->EndRedraw();
+ gc.Deactivate();
+ }
+}
+
+void S60VideoWindowDisplay::setWinId(WId id)
+{
+ if (m_winId != id) {
+ m_winId = id;
+ if (m_winId) {
+ static_cast<RWindow *>(m_winId->DrawableWindow())->SetBackgroundColor(TRgb(0, 0, 0, 0));
+#ifndef VIDEOOUTPUT_GRAPHICS_SURFACES
+ if (QSysInfo::s60Version() >= QSysInfo::SV_S60_5_0)
+ S60VideoOutputUtils::setNativePaintMode(m_winId, BlitWriteAlpha);
+#endif // !VIDEOOUTPUT_GRAPHICS_SURFACES
+ }
+ emit windowHandleChanged(windowHandle());
+ }
+}
+
+void S60VideoWindowDisplay::setDisplayRect(const QRect &rect)
+{
+ if (m_displayRect != rect) {
+ // If QGraphicsVideoItem moves out of screen, display rect is invalidated
+ if (rect == QRect(QPoint(-1,-1), QSize(1,1)))
+ emit visibilityChanged(false);
+ else
+ emit visibilityChanged(true);
+ m_displayRect = rect;
+ emit displayRectChanged(extentRect(), clipRect());
+ }
+}
+
+QRect S60VideoWindowDisplay::displayRect() const
+{
+ return m_displayRect;
+}
+
+void S60VideoWindowDisplay::repaint()
+{
+ // TODO
+}
+
+void S60VideoWindowDisplay::refreshDisplay()
+{
+ emit displayRectChanged(extentRect(), clipRect());
+}
+
diff --git a/src/plugins/symbian/videooutput/s60videowindowdisplay.h b/src/plugins/symbian/videooutput/s60videowindowdisplay.h
new file mode 100644
index 000000000..8e749dcf3
--- /dev/null
+++ b/src/plugins/symbian/videooutput/s60videowindowdisplay.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** 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$
+** 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 S60VIDEOWINDOWDISPLAY_H
+#define S60VIDEOWINDOWDISPLAY_H
+
+#include "s60videodisplay.h"
+
+QT_USE_NAMESPACE
+
+class S60VideoWindowDisplay : public S60VideoDisplay
+{
+public:
+ S60VideoWindowDisplay(QObject *parent);
+ ~S60VideoWindowDisplay();
+
+ // S60VideoDisplay
+ WId winId() const;
+ QRect extentRect() const;
+ void setFrame(const CFbsBitmap &bitmap);
+
+ void setWinId(WId id);
+ void setDisplayRect(const QRect &rect);
+ QRect displayRect() const;
+ void repaint();
+ void refreshDisplay();
+
+private:
+ WId m_winId;
+ QRect m_displayRect;
+ CFbsBitmap *m_bitmap;
+};
+
+#endif // S60VIDEOWINDOWDISPLAY_H
+
diff --git a/src/plugins/symbian/videooutput/videooutput.pri b/src/plugins/symbian/videooutput/videooutput.pri
new file mode 100644
index 000000000..13aa7a0fc
--- /dev/null
+++ b/src/plugins/symbian/videooutput/videooutput.pri
@@ -0,0 +1,37 @@
+INCLUDEPATH += $$PWD
+
+message("VideoOutput: using common implementation")
+
+contains(surfaces_s60_enabled, yes) {
+ message("VideoOutput: graphics surface rendering supported")
+ DEFINES += VIDEOOUTPUT_GRAPHICS_SURFACES
+} else {
+ message("VideoOutput: no graphics surface rendering support - DSA only")
+}
+
+exists($$[QT_INSTALL_HEADERS]/QtGui/private/qwidget_p.h) {
+ DEFINES += PRIVATE_QTGUI_HEADERS_AVAILABLE
+ message("VideoOutput: private QtGui headers are available")
+} else {
+ message("VideoOutput: private QtGui headers not available - video and viewfinder may not be rendered correctly")
+}
+
+HEADERS += $$PWD/s60videodisplay.h \
+ $$PWD/s60videooutpututils.h \
+ $$PWD/s60videowidget.h \
+ $$PWD/s60videowidgetcontrol.h \
+ $$PWD/s60videowidgetdisplay.h \
+ $$PWD/s60videowindowcontrol.h \
+ $$PWD/s60videowindowdisplay.h
+
+SOURCES += $$PWD/s60videodisplay.cpp \
+ $$PWD/s60videooutpututils.cpp \
+ $$PWD/s60videowidget.cpp \
+ $$PWD/s60videowidgetcontrol.cpp \
+ $$PWD/s60videowidgetdisplay.cpp \
+ $$PWD/s60videowindowcontrol.cpp \
+ $$PWD/s60videowindowdisplay.cpp
+
+LIBS *= -lcone
+LIBS *= -lws32
+
diff --git a/src/plugins/v4l/radio/radio.pri b/src/plugins/v4l/radio/radio.pri
new file mode 100644
index 000000000..04c6720c5
--- /dev/null
+++ b/src/plugins/v4l/radio/radio.pri
@@ -0,0 +1,29 @@
+INCLUDEPATH += $$PWD
+
+maemo5 {
+ QT += dbus
+
+ CONFIG += link_pkgconfig
+
+ PKGCONFIG += gstreamer-0.10
+
+ LIBS += -lasound
+
+ HEADERS += \
+ $$PWD/v4lradiocontrol_maemo5.h \
+ $$PWD/v4lradioservice.h
+
+ SOURCES += \
+ $$PWD/v4lradiocontrol_maemo5.cpp \
+ $$PWD/v4lradioservice.cpp
+
+} else {
+
+HEADERS += \
+ $$PWD/v4lradiocontrol.h \
+ $$PWD/v4lradioservice.h
+
+SOURCES += \
+ $$PWD/v4lradiocontrol.cpp \
+ $$PWD/v4lradioservice.cpp
+}
diff --git a/src/plugins/v4l/radio/v4lradiocontrol.cpp b/src/plugins/v4l/radio/v4lradiocontrol.cpp
new file mode 100644
index 000000000..1b698279a
--- /dev/null
+++ b/src/plugins/v4l/radio/v4lradiocontrol.cpp
@@ -0,0 +1,538 @@
+/****************************************************************************
+**
+** 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$
+** 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 "v4lradiocontrol.h"
+#include "v4lradioservice.h"
+
+#include <QtCore/qdebug.h>
+
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include "linux/videodev2.h"
+
+#include <sys/soundcard.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+V4LRadioControl::V4LRadioControl(QObject *parent)
+ :QRadioTunerControl(parent)
+{
+ fd = -1;
+ initRadio();
+ muted = false;
+ stereo = false;
+ m_error = false;
+ sig = 0;
+ currentBand = QRadioTuner::FM;
+ step = 100000;
+ scanning = false;
+ playTime.restart();
+ timer = new QTimer(this);
+ timer->setInterval(200);
+ connect(timer,SIGNAL(timeout()),this,SLOT(search()));
+ timer->start();
+}
+
+V4LRadioControl::~V4LRadioControl()
+{
+ timer->stop();
+
+ if(fd > 0)
+ ::close(fd);
+}
+
+bool V4LRadioControl::isAvailable() const
+{
+ return available;
+}
+
+QtMultimediaKit::AvailabilityError V4LRadioControl::availabilityError() const
+{
+ if (fd > 0)
+ return QtMultimediaKit::NoError;
+ else
+ return QtMultimediaKit::ResourceError;
+}
+
+QRadioTuner::State V4LRadioControl::state() const
+{
+ return fd > 0 ? QRadioTuner::ActiveState : QRadioTuner::StoppedState;
+}
+
+QRadioTuner::Band V4LRadioControl::band() const
+{
+ return currentBand;
+}
+
+bool V4LRadioControl::isBandSupported(QRadioTuner::Band b) const
+{
+ QRadioTuner::Band bnd = (QRadioTuner::Band)b;
+ switch(bnd) {
+ case QRadioTuner::FM:
+ if(freqMin <= 87500000 && freqMax >= 108000000)
+ return true;
+ break;
+ case QRadioTuner::LW:
+ if(freqMin <= 148500 && freqMax >= 283500)
+ return true;
+ case QRadioTuner::AM:
+ if(freqMin <= 520000 && freqMax >= 1610000)
+ return true;
+ default:
+ if(freqMin <= 1711000 && freqMax >= 30000000)
+ return true;
+ }
+
+ return false;
+}
+
+void V4LRadioControl::setBand(QRadioTuner::Band b)
+{
+ if(freqMin <= 87500000 && freqMax >= 108000000 && b == QRadioTuner::FM) {
+ // FM 87.5 to 108.0 MHz, except Japan 76-90 MHz
+ currentBand = (QRadioTuner::Band)b;
+ step = 100000; // 100kHz steps
+ emit bandChanged(currentBand);
+
+ } else if(freqMin <= 148500 && freqMax >= 283500 && b == QRadioTuner::LW) {
+ // LW 148.5 to 283.5 kHz, 9kHz channel spacing (Europe, Africa, Asia)
+ currentBand = (QRadioTuner::Band)b;
+ step = 1000; // 1kHz steps
+ emit bandChanged(currentBand);
+
+ } else if(freqMin <= 520000 && freqMax >= 1610000 && b == QRadioTuner::AM) {
+ // AM 520 to 1610 kHz, 9 or 10kHz channel spacing, extended 1610 to 1710 kHz
+ currentBand = (QRadioTuner::Band)b;
+ step = 1000; // 1kHz steps
+ emit bandChanged(currentBand);
+
+ } else if(freqMin <= 1711000 && freqMax >= 30000000 && b == QRadioTuner::SW) {
+ // SW 1.711 to 30.0 MHz, divided into 15 bands. 5kHz channel spacing
+ currentBand = (QRadioTuner::Band)b;
+ step = 500; // 500Hz steps
+ emit bandChanged(currentBand);
+ }
+ playTime.restart();
+}
+
+int V4LRadioControl::frequency() const
+{
+ return currentFreq;
+}
+
+int V4LRadioControl::frequencyStep(QRadioTuner::Band b) const
+{
+ int step = 0;
+
+ if(b == QRadioTuner::FM)
+ step = 100000; // 100kHz steps
+ else if(b == QRadioTuner::LW)
+ step = 1000; // 1kHz steps
+ else if(b == QRadioTuner::AM)
+ step = 1000; // 1kHz steps
+ else if(b == QRadioTuner::SW)
+ step = 500; // 500Hz steps
+
+ return step;
+}
+
+QPair<int,int> V4LRadioControl::frequencyRange(QRadioTuner::Band b) const
+{
+ if(b == QRadioTuner::AM)
+ return qMakePair<int,int>(520000,1710000);
+ else if(b == QRadioTuner::FM)
+ return qMakePair<int,int>(87500000,108000000);
+ else if(b == QRadioTuner::SW)
+ return qMakePair<int,int>(1711111,30000000);
+ else if(b == QRadioTuner::LW)
+ return qMakePair<int,int>(148500,283500);
+
+ return qMakePair<int,int>(0,0);
+}
+
+void V4LRadioControl::setFrequency(int frequency)
+{
+ qint64 f = frequency;
+
+ v4l2_frequency freq;
+
+ if(frequency < freqMin)
+ f = freqMax;
+ if(frequency > freqMax)
+ f = freqMin;
+
+ if(fd > 0) {
+ memset( &freq, 0, sizeof( freq ) );
+ // Use the first tuner
+ freq.tuner = 0;
+ if ( ioctl( fd, VIDIOC_G_FREQUENCY, &freq ) >= 0 ) {
+ if(low) {
+ // For low, freq in units of 62.5Hz, so convert from Hz to units.
+ freq.frequency = (int)(f/62.5);
+ } else {
+ // For high, freq in units of 62.5kHz, so convert from Hz to units.
+ freq.frequency = (int)(f/62500);
+ }
+ ioctl( fd, VIDIOC_S_FREQUENCY, &freq );
+ currentFreq = f;
+ playTime.restart();
+ emit frequencyChanged(currentFreq);
+ }
+ }
+ playTime.restart();
+}
+
+bool V4LRadioControl::isStereo() const
+{
+ return stereo;
+}
+
+QRadioTuner::StereoMode V4LRadioControl::stereoMode() const
+{
+ return QRadioTuner::Auto;
+}
+
+void V4LRadioControl::setStereoMode(QRadioTuner::StereoMode mode)
+{
+ bool stereo = true;
+
+ if(mode == QRadioTuner::ForceMono)
+ stereo = false;
+
+ v4l2_tuner tuner;
+
+ memset( &tuner, 0, sizeof( tuner ) );
+
+ if ( ioctl( fd, VIDIOC_G_TUNER, &tuner ) >= 0 ) {
+ if(stereo)
+ tuner.audmode = V4L2_TUNER_MODE_STEREO;
+ else
+ tuner.audmode = V4L2_TUNER_MODE_MONO;
+
+ if ( ioctl( fd, VIDIOC_S_TUNER, &tuner ) >= 0 ) {
+ emit stereoStatusChanged(stereo);
+ }
+ }
+}
+
+int V4LRadioControl::signalStrength() const
+{
+ v4l2_tuner tuner;
+
+ // Return the first tuner founds signal strength.
+ for ( int index = 0; index < tuners; ++index ) {
+ memset( &tuner, 0, sizeof( tuner ) );
+ tuner.index = index;
+ if ( ioctl( fd, VIDIOC_G_TUNER, &tuner ) < 0 )
+ continue;
+ if ( tuner.type != V4L2_TUNER_RADIO )
+ continue;
+ // percentage signal strength
+ return tuner.signal*100/65535;
+ }
+
+ return 0;
+}
+
+int V4LRadioControl::volume() const
+{
+ v4l2_queryctrl queryctrl;
+
+ if(fd > 0) {
+ memset( &queryctrl, 0, sizeof( queryctrl ) );
+ queryctrl.id = V4L2_CID_AUDIO_VOLUME;
+ if ( ioctl( fd, VIDIOC_QUERYCTRL, &queryctrl ) >= 0 ) {
+ if(queryctrl.maximum == 0) {
+ return vol;
+ } else {
+ // percentage volume returned
+ return queryctrl.default_value*100/queryctrl.maximum;
+ }
+ }
+ }
+ return 0;
+}
+
+void V4LRadioControl::setVolume(int volume)
+{
+ v4l2_queryctrl queryctrl;
+
+ if(fd > 0) {
+ memset( &queryctrl, 0, sizeof( queryctrl ) );
+ queryctrl.id = V4L2_CID_AUDIO_VOLUME;
+ if ( ioctl( fd, VIDIOC_QUERYCTRL, &queryctrl ) >= 0 ) {
+ v4l2_control control;
+
+ if(queryctrl.maximum > 0) {
+ memset( &control, 0, sizeof( control ) );
+ control.id = V4L2_CID_AUDIO_VOLUME;
+ control.value = volume*queryctrl.maximum/100;
+ ioctl( fd, VIDIOC_S_CTRL, &control );
+ } else {
+ setVol(volume);
+ }
+ emit volumeChanged(volume);
+ }
+ }
+}
+
+bool V4LRadioControl::isMuted() const
+{
+ return muted;
+}
+
+void V4LRadioControl::setMuted(bool muted)
+{
+ v4l2_queryctrl queryctrl;
+
+ if(fd > 0) {
+ memset( &queryctrl, 0, sizeof( queryctrl ) );
+ queryctrl.id = V4L2_CID_AUDIO_MUTE;
+ if ( ioctl( fd, VIDIOC_QUERYCTRL, &queryctrl ) >= 0 ) {
+ v4l2_control control;
+ memset( &control, 0, sizeof( control ) );
+ control.id = V4L2_CID_AUDIO_MUTE;
+ control.value = (muted ? queryctrl.maximum : queryctrl.minimum );
+ ioctl( fd, VIDIOC_S_CTRL, &control );
+ this->muted = muted;
+ emit mutedChanged(muted);
+ }
+ }
+}
+
+bool V4LRadioControl::isSearching() const
+{
+ return scanning;
+}
+
+void V4LRadioControl::cancelSearch()
+{
+ scanning = false;
+ timer->stop();
+}
+
+void V4LRadioControl::searchForward()
+{
+ // Scan up
+ if(scanning) {
+ cancelSearch();
+ return;
+ }
+ scanning = true;
+ forward = true;
+ timer->start();
+}
+
+void V4LRadioControl::searchBackward()
+{
+ // Scan down
+ if(scanning) {
+ cancelSearch();
+ return;
+ }
+ scanning = true;
+ forward = false;
+ timer->start();
+}
+
+void V4LRadioControl::start()
+{
+}
+
+void V4LRadioControl::stop()
+{
+}
+
+QRadioTuner::Error V4LRadioControl::error() const
+{
+ if(m_error)
+ return QRadioTuner::OpenError;
+
+ return QRadioTuner::NoError;
+}
+
+QString V4LRadioControl::errorString() const
+{
+ return QString();
+}
+
+void V4LRadioControl::search()
+{
+ int signal = signalStrength();
+ if(sig != signal) {
+ sig = signal;
+ emit signalStrengthChanged(sig);
+ }
+
+ if(!scanning) return;
+
+ if (signal > 25) {
+ cancelSearch();
+ return;
+ }
+
+ if(forward) {
+ setFrequency(currentFreq+step);
+ } else {
+ setFrequency(currentFreq-step);
+ }
+}
+
+bool V4LRadioControl::initRadio()
+{
+ v4l2_tuner tuner;
+ v4l2_input input;
+ v4l2_frequency freq;
+ v4l2_capability cap;
+
+ low = false;
+ available = false;
+ freqMin = freqMax = currentFreq = 0;
+
+ fd = ::open("/dev/radio0", O_RDWR);
+
+ if(fd != -1) {
+ // Capabilities
+ memset( &cap, 0, sizeof( cap ) );
+ if(::ioctl(fd, VIDIOC_QUERYCAP, &cap ) >= 0) {
+ if(((cap.capabilities & V4L2_CAP_RADIO) == 0) && ((cap.capabilities & V4L2_CAP_AUDIO) == 0))
+ available = true;
+ }
+
+ // Tuners
+ memset( &input, 0, sizeof( input ) );
+ tuners = 0;
+ for ( ;; ) {
+ memset( &input, 0, sizeof( input ) );
+ input.index = tuners;
+ if ( ioctl( fd, VIDIOC_ENUMINPUT, &input ) < 0 )
+ break;
+ ++tuners;
+ }
+
+ // Freq bands
+ for ( int index = 0; index < tuners; ++index ) {
+ memset( &tuner, 0, sizeof( tuner ) );
+ tuner.index = index;
+ if ( ioctl( fd, VIDIOC_G_TUNER, &tuner ) < 0 )
+ continue;
+ if ( tuner.type != V4L2_TUNER_RADIO )
+ continue;
+ if ( ( tuner.capability & V4L2_TUNER_CAP_LOW ) != 0 ) {
+ // Units are 1/16th of a kHz.
+ low = true;
+ }
+ if(low) {
+ freqMin = tuner.rangelow * 62.5;
+ freqMax = tuner.rangehigh * 62.5;
+ } else {
+ freqMin = tuner.rangelow * 62500;
+ freqMax = tuner.rangehigh * 62500;
+ }
+ }
+
+ // frequency
+ memset( &freq, 0, sizeof( freq ) );
+ if(::ioctl(fd, VIDIOC_G_FREQUENCY, &freq ) >= 0) {
+ if ( ((int)freq.frequency) != -1 ) { // -1 means not set.
+ if(low)
+ currentFreq = freq.frequency * 62.5;
+ else
+ currentFreq = freq.frequency * 62500;
+ }
+ }
+
+ // stereo
+ bool stereo = false;
+ memset( &tuner, 0, sizeof( tuner ) );
+ if ( ioctl( fd, VIDIOC_G_TUNER, &tuner ) >= 0 ) {
+ if((tuner.rxsubchans & V4L2_TUNER_SUB_STEREO) != 0)
+ stereo = true;
+ }
+
+ vol = getVol();
+
+ return true;
+ }
+ m_error = true;
+ emit error();
+
+ return false;
+}
+
+void V4LRadioControl::setVol(int v)
+{
+ int fd = ::open( "/dev/mixer", O_RDWR, 0 );
+ if ( fd < 0 )
+ return;
+ int volume = v;
+ if ( volume < 0 )
+ volume = 0;
+ else if ( volume > 100 )
+ volume = 100;
+ vol = volume;
+ volume += volume << 8;
+ ::ioctl( fd, MIXER_WRITE(SOUND_MIXER_VOLUME), &volume );
+ ::close( fd );
+}
+
+int V4LRadioControl::getVol()
+{
+ int fd = ::open( "/dev/mixer", O_RDWR, 0 );
+ if ( fd >= 0 ) {
+ int volume = 0;
+ ::ioctl( fd, MIXER_READ(SOUND_MIXER_VOLUME), &volume );
+ int left = ( volume & 0xFF );
+ int right = ( ( volume >> 8 ) & 0xFF );
+ if ( left > right )
+ vol = left;
+ else
+ vol = right;
+ ::close( fd );
+ return vol;
+ }
+ return 0;
+}
+
diff --git a/src/plugins/v4l/radio/v4lradiocontrol.h b/src/plugins/v4l/radio/v4lradiocontrol.h
new file mode 100644
index 000000000..3349be236
--- /dev/null
+++ b/src/plugins/v4l/radio/v4lradiocontrol.h
@@ -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$
+** 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 V4LRADIOCONTROL_H
+#define V4LRADIOCONTROL_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qdatetime.h>
+
+#include <qradiotunercontrol.h>
+
+#include <linux/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <linux/videodev2.h>
+
+QT_USE_NAMESPACE
+
+class V4LRadioService;
+
+class V4LRadioControl : public QRadioTunerControl
+{
+ Q_OBJECT
+public:
+ V4LRadioControl(QObject *parent = 0);
+ ~V4LRadioControl();
+
+ bool isAvailable() const;
+ QtMultimediaKit::AvailabilityError availabilityError() const;
+
+ QRadioTuner::State state() const;
+
+ QRadioTuner::Band band() const;
+ void setBand(QRadioTuner::Band b);
+ bool isBandSupported(QRadioTuner::Band b) const;
+
+ int frequency() const;
+ int frequencyStep(QRadioTuner::Band b) const;
+ QPair<int,int> frequencyRange(QRadioTuner::Band b) const;
+ void setFrequency(int frequency);
+
+ bool isStereo() const;
+ QRadioTuner::StereoMode stereoMode() const;
+ void setStereoMode(QRadioTuner::StereoMode mode);
+
+ int signalStrength() const;
+
+ int volume() const;
+ void setVolume(int volume);
+
+ bool isMuted() const;
+ void setMuted(bool muted);
+
+ bool isSearching() const;
+ void cancelSearch();
+
+ void searchForward();
+ void searchBackward();
+
+ void start();
+ void stop();
+
+ QRadioTuner::Error error() const;
+ QString errorString() const;
+
+private slots:
+ void search();
+
+private:
+ bool initRadio();
+ void setVol(int v);
+ int getVol();
+
+ int fd;
+
+ bool m_error;
+ bool muted;
+ bool stereo;
+ bool low;
+ bool available;
+ int tuners;
+ int step;
+ int vol;
+ int sig;
+ bool scanning;
+ bool forward;
+ QTimer* timer;
+ QRadioTuner::Band currentBand;
+ qint64 freqMin;
+ qint64 freqMax;
+ qint64 currentFreq;
+ QTime playTime;
+};
+
+#endif
diff --git a/src/plugins/v4l/radio/v4lradiocontrol_maemo5.cpp b/src/plugins/v4l/radio/v4lradiocontrol_maemo5.cpp
new file mode 100644
index 000000000..f3dea9d63
--- /dev/null
+++ b/src/plugins/v4l/radio/v4lradiocontrol_maemo5.cpp
@@ -0,0 +1,755 @@
+/****************************************************************************
+**
+** 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$
+** 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 "v4lradiocontrol_maemo5.h"
+#include "v4lradioservice.h"
+
+#include "linux/videodev2.h"
+#include <linux/videodev.h>
+#include <sys/soundcard.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define HEADPHONE_STATE_FILE "/sys/devices/platform/gpio-switch/headphone/state"
+#define HEADPHONE_CONNECTED_STATE "connected"
+#define HEADPHONE_DISCONNECTED_STATE "disconnected"
+
+#define FMRXENABLER_DBUS_SERVICE "de.pycage.FMRXEnabler"
+#define FMRXENABLER_DBUS_OBJ_PATH "/de/pycage/FMRXEnabler"
+#define FMRXENABLER_DBUS_IFACE_NAME "de.pycage.FMRXEnabler"
+
+gboolean
+state_file_changed(GIOChannel* source, GIOCondition /*condition*/, gpointer data)
+{
+ V4LRadioControl* radioControl = (V4LRadioControl*)data;
+ gchar* result;
+
+ g_io_channel_seek_position(source, 0, G_SEEK_SET, NULL);
+ g_io_channel_read_line(source, &result, NULL, NULL, NULL);
+ g_strstrip(result);
+
+ if (g_ascii_strcasecmp(result, HEADPHONE_DISCONNECTED_STATE) == 0) {
+ radioControl->enablePipeline(false);
+ } else if (g_ascii_strcasecmp(result, HEADPHONE_CONNECTED_STATE) == 0) {
+ // Wait 400ms until audio is routed again to headphone to prevent sound coming from speakers
+ QTimer::singleShot(400,radioControl,SLOT(enablePipeline()));
+ }
+
+#ifdef MULTIMEDIA_MAEMO_DEBUG
+ qDebug() << "Headphone is now" << result;
+#endif
+
+ g_free(result);
+ return true;
+}
+
+V4LRadioControl::V4LRadioControl(QObject *parent)
+ : QRadioTunerControl(parent)
+ , fd(1)
+ , m_error(false)
+ , muted(false)
+ , stereo(false)
+ , step(100000)
+ , sig(0)
+ , scanning(false)
+ , currentBand(QRadioTuner::FM)
+ , pipeline(0)
+{
+ if (QDBusConnection::systemBus().isConnected()) {
+ FMRXEnablerIFace = new QDBusInterface(FMRXENABLER_DBUS_SERVICE,
+ FMRXENABLER_DBUS_OBJ_PATH,
+ FMRXENABLER_DBUS_IFACE_NAME,
+ QDBusConnection::systemBus());
+ }
+
+ createGstPipeline();
+
+ GIOChannel* headphoneStateFile = NULL;
+ headphoneStateFile = g_io_channel_new_file(HEADPHONE_STATE_FILE, "r", NULL);
+ if (headphoneStateFile != NULL) {
+ g_io_add_watch(headphoneStateFile, G_IO_PRI, state_file_changed, this);
+ } else {
+#ifdef MULTIMEDIA_MAEMO_DEBUG
+ qWarning() << QString("File %1 can't be read!").arg(HEADPHONE_STATE_FILE) ;
+ qWarning() << "Monitoring headphone state isn't possible!";
+#endif
+ }
+
+ enableFMRX();
+ initRadio();
+ setupHeadPhone();
+
+ setMuted(false);
+
+ timer = new QTimer(this);
+ timer->setInterval(200);
+ connect(timer,SIGNAL(timeout()),this,SLOT(search()));
+
+ tickTimer = new QTimer(this);
+ tickTimer->setInterval(10000);
+ connect(tickTimer,SIGNAL(timeout()),this,SLOT(enableFMRX()));
+ tickTimer->start();
+}
+
+V4LRadioControl::~V4LRadioControl()
+{
+ if (pipeline)
+ {
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+ gst_object_unref (GST_OBJECT (pipeline));
+ }
+
+ if(fd > 0)
+ ::close(fd);
+}
+
+void V4LRadioControl::enablePipeline(bool enable)
+{
+ if (enable == true)
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ else
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+}
+
+void V4LRadioControl::enableFMRX()
+{
+ if (FMRXEnablerIFace && FMRXEnablerIFace->isValid()) {
+ FMRXEnablerIFace->call("request"); // Return value ignored
+ }
+}
+
+// Workaround to capture sound from the PGA line and play it back using gstreamer
+// because N900 doesn't output sound directly to speakers
+bool V4LRadioControl::createGstPipeline()
+{
+ GstElement *source, *sink;
+
+ gst_init (NULL, NULL);
+ pipeline = gst_pipeline_new("my-pipeline");
+
+ source = gst_element_factory_make ("pulsesrc", "source");
+ sink = gst_element_factory_make ("pulsesink", "sink");
+
+ gst_bin_add_many (GST_BIN (pipeline), source, sink, (char *)NULL);
+
+ if (!gst_element_link_many (source, sink, (char *)NULL)) {
+ return false;
+ }
+
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+
+ return true;
+}
+
+bool V4LRadioControl::isAvailable() const
+{
+ return available;
+}
+
+QtMultimediaKit::AvailabilityError V4LRadioControl::availabilityError() const
+{
+ if (fd > 0)
+ return QtMultimediaKit::NoError;
+ else
+ return QtMultimediaKit::ResourceError;
+}
+
+QRadioTuner::State V4LRadioControl::state() const
+{
+ return fd > 0 ? QRadioTuner::ActiveState : QRadioTuner::StoppedState;
+}
+
+QRadioTuner::Band V4LRadioControl::band() const
+{
+ return currentBand;
+}
+
+bool V4LRadioControl::isBandSupported(QRadioTuner::Band b) const
+{
+ QRadioTuner::Band bnd = (QRadioTuner::Band)b;
+ switch(bnd) {
+ case QRadioTuner::FM:
+ if(freqMin <= 87500000 && freqMax >= 108000000)
+ return true;
+ break;
+ case QRadioTuner::LW:
+ if(freqMin <= 148500 && freqMax >= 283500)
+ return true;
+ case QRadioTuner::AM:
+ if(freqMin <= 520000 && freqMax >= 1610000)
+ return true;
+ default:
+ if(freqMin <= 1711000 && freqMax >= 30000000)
+ return true;
+ }
+
+ return false;
+}
+
+void V4LRadioControl::setBand(QRadioTuner::Band b)
+{
+ if(freqMin <= 87500000 && freqMax >= 108000000 && b == QRadioTuner::FM) {
+ // FM 87.5 to 108.0 MHz, except Japan 76-90 MHz
+ currentBand = (QRadioTuner::Band)b;
+ step = 100000; // 100kHz steps
+ emit bandChanged(currentBand);
+
+ } else if(freqMin <= 148500 && freqMax >= 283500 && b == QRadioTuner::LW) {
+ // LW 148.5 to 283.5 kHz, 9kHz channel spacing (Europe, Africa, Asia)
+ currentBand = (QRadioTuner::Band)b;
+ step = 1000; // 1kHz steps
+ emit bandChanged(currentBand);
+
+ } else if(freqMin <= 520000 && freqMax >= 1610000 && b == QRadioTuner::AM) {
+ // AM 520 to 1610 kHz, 9 or 10kHz channel spacing, extended 1610 to 1710 kHz
+ currentBand = (QRadioTuner::Band)b;
+ step = 1000; // 1kHz steps
+ emit bandChanged(currentBand);
+
+ } else if(freqMin <= 1711000 && freqMax >= 30000000 && b == QRadioTuner::SW) {
+ // SW 1.711 to 30.0 MHz, divided into 15 bands. 5kHz channel spacing
+ currentBand = (QRadioTuner::Band)b;
+ step = 500; // 500Hz steps
+ emit bandChanged(currentBand);
+ }
+}
+
+int V4LRadioControl::frequency() const
+{
+ return currentFreq;
+}
+
+int V4LRadioControl::frequencyStep(QRadioTuner::Band b) const
+{
+ int step = 0;
+
+ if(b == QRadioTuner::FM)
+ step = 100000; // 100kHz steps
+ else if(b == QRadioTuner::LW)
+ step = 1000; // 1kHz steps
+ else if(b == QRadioTuner::AM)
+ step = 1000; // 1kHz steps
+ else if(b == QRadioTuner::SW)
+ step = 500; // 500Hz steps
+
+ return step;
+}
+
+QPair<int,int> V4LRadioControl::frequencyRange(QRadioTuner::Band b) const
+{
+ if(b == QRadioTuner::AM)
+ return qMakePair<int,int>(520000,1710000);
+ else if(b == QRadioTuner::FM)
+ return qMakePair<int,int>(87500000,108000000);
+ else if(b == QRadioTuner::SW)
+ return qMakePair<int,int>(1711111,30000000);
+ else if(b == QRadioTuner::LW)
+ return qMakePair<int,int>(148500,283500);
+
+ return qMakePair<int,int>(0,0);
+}
+
+void V4LRadioControl::setFrequency(int frequency)
+{
+ qint64 f = frequency;
+
+ v4l2_frequency freq;
+
+ if(frequency < freqMin)
+ f = freqMax;
+ if(frequency > freqMax)
+ f = freqMin;
+
+ if(fd > 0) {
+ memset(&freq, 0, sizeof(freq));
+ // Use the first tuner
+ freq.tuner = 0;
+ if (::ioctl(fd, VIDIOC_G_FREQUENCY, &freq) >= 0) {
+ if(low) {
+ // For low, freq in units of 62.5Hz, so convert from Hz to units.
+ freq.frequency = (int)(f/62.5);
+ } else {
+ // For high, freq in units of 62.5kHz, so convert from Hz to units.
+ freq.frequency = (int)(f/62500);
+ }
+ ::ioctl(fd, VIDIOC_S_FREQUENCY, &freq);
+ currentFreq = f;
+ emit frequencyChanged(currentFreq);
+
+ int signal = signalStrength();
+ if(sig != signal) {
+ sig = signal;
+ emit signalStrengthChanged(sig);
+ }
+ }
+ }
+}
+
+bool V4LRadioControl::isStereo() const
+{
+ return stereo;
+}
+
+QRadioTuner::StereoMode V4LRadioControl::stereoMode() const
+{
+ return QRadioTuner::Auto;
+}
+
+void V4LRadioControl::setStereoMode(QRadioTuner::StereoMode mode)
+{
+ bool stereo = true;
+
+ if(mode == QRadioTuner::ForceMono)
+ stereo = false;
+
+ v4l2_tuner tuner;
+
+ memset(&tuner, 0, sizeof(tuner));
+
+ if (ioctl(fd, VIDIOC_G_TUNER, &tuner) >= 0) {
+ if(stereo)
+ tuner.audmode = V4L2_TUNER_MODE_STEREO;
+ else
+ tuner.audmode = V4L2_TUNER_MODE_MONO;
+
+ if (ioctl(fd, VIDIOC_S_TUNER, &tuner) >= 0) {
+ emit stereoStatusChanged(stereo);
+ }
+ }
+}
+
+int V4LRadioControl::signalStrength() const
+{
+ v4l2_tuner tuner;
+
+ tuner.index = 0;
+ if (ioctl(fd, VIDIOC_G_TUNER, &tuner) < 0 || tuner.type != V4L2_TUNER_RADIO)
+ return 0;
+ return tuner.signal*100/65535;
+}
+
+int V4LRadioControl::vol(snd_hctl_elem_t *elem) const
+{
+ const QString card("hw:0");
+ int err;
+ snd_ctl_elem_id_t *id;
+ snd_ctl_elem_info_t *info;
+ snd_ctl_elem_value_t *control;
+ snd_ctl_elem_id_alloca(&id);
+ snd_ctl_elem_info_alloca(&info);
+ snd_ctl_elem_value_alloca(&control);
+ if ((err = snd_hctl_elem_info(elem, info)) < 0) {
+ return 0;
+ }
+
+ snd_hctl_elem_get_id(elem, id);
+ snd_hctl_elem_read(elem, control);
+
+ return snd_ctl_elem_value_get_integer(control, 0);
+}
+
+int V4LRadioControl::volume() const
+{
+ const QString ctlName("Line DAC Playback Volume");
+ const QString card("hw:0");
+
+ int volume = 0;
+ int err;
+ static snd_ctl_t *handle = NULL;
+ snd_ctl_elem_info_t *info;
+ snd_ctl_elem_id_t *id;
+ snd_ctl_elem_value_t *control;
+
+ snd_ctl_elem_info_alloca(&info);
+ snd_ctl_elem_id_alloca(&id);
+ snd_ctl_elem_value_alloca(&control);
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); /* MIXER */
+
+ snd_ctl_elem_id_set_name(id, ctlName.toAscii());
+
+ if ((err = snd_ctl_open(&handle, card.toAscii(), 0)) < 0) {
+ return 0;
+ }
+
+ snd_ctl_elem_info_set_id(info, id);
+ if ((err = snd_ctl_elem_info(handle, info)) < 0) {
+ snd_ctl_close(handle);
+ handle = NULL;
+ return 0;
+ }
+
+ snd_ctl_elem_info_get_id(info, id); /* FIXME: Remove it when hctl find works ok !!! */
+ snd_ctl_elem_value_set_id(control, id);
+
+ snd_ctl_close(handle);
+ handle = NULL;
+
+ snd_hctl_t *hctl;
+ snd_hctl_elem_t *elem;
+ if ((err = snd_hctl_open(&hctl, card.toAscii(), 0)) < 0) {
+ return 0;
+ }
+ if ((err = snd_hctl_load(hctl)) < 0) {
+ return 0;
+ }
+ elem = snd_hctl_find_elem(hctl, id);
+ if (elem)
+ volume = vol(elem);
+
+ snd_hctl_close(hctl);
+
+ return (volume/118.0) * 100;
+}
+
+void V4LRadioControl::setVolume(int volume)
+{
+ int vol = (volume / 100.0) * 118; // 118 is a headphone max setting
+ callAmixer("Line DAC Playback Volume", QString().setNum(vol)+QString(",")+QString().setNum(vol));
+}
+
+bool V4LRadioControl::isMuted() const
+{
+ return muted;
+}
+
+void V4LRadioControl::setMuted(bool muted)
+{
+ struct v4l2_control vctrl;
+ vctrl.id = V4L2_CID_AUDIO_MUTE;
+ vctrl.value = muted ? 1 : 0;
+ ioctl(fd, VIDIOC_S_CTRL, &vctrl);
+}
+
+void V4LRadioControl::setupHeadPhone()
+{
+ QMap<QString, QString> settings;
+
+ settings["Jack Function"] = "Headset";
+ settings["Left DAC_L1 Mixer HP Switch"] = "off";
+ settings["Right DAC_R1 Mixer HP Switch"] = "off";
+ settings["Line DAC Playback Switch"] = "on";
+ settings["Line DAC Playback Volume"] = "118,118"; // Volume is set to 100%
+ settings["HPCOM DAC Playback Switch"] = "off";
+ settings["Left DAC_L1 Mixer HP Switch"] = "off";
+ settings["Left DAC_L1 Mixer Line Switch"] = "on";
+ settings["Right DAC_R1 Mixer HP Switch"] = "off";
+ settings["Right DAC_R1 Mixer Line Switch"] = "on";
+ settings["Speaker Function"] = "Off";
+
+ settings["Input Select"] = "ADC";
+ settings["Left PGA Mixer Line1L Switch"] = "off";
+ settings["Right PGA Mixer Line1L Switch"] = "off";
+ settings["Right PGA Mixer Line1R Switch"] = "off";
+ settings["PGA Capture Volume"] = "0,0";
+
+ settings["PGA Capture Switch"] = "on";
+
+ settings["Left PGA Mixer Line2L Switch"] = "on";
+ settings["Right PGA Mixer Line2R Switch"] = "on";
+
+ QMapIterator<QString, QString> i(settings);
+ while (i.hasNext()) {
+ i.next();
+ callAmixer(i.key(), i.value());
+ }
+}
+
+void V4LRadioControl::callAmixer(const QString& target, const QString& value)
+{
+ int err;
+ long tmp;
+ unsigned int count;
+ static snd_ctl_t *handle = NULL;
+ QString card("hw:0");
+ snd_ctl_elem_info_t *info;
+ snd_ctl_elem_id_t *id;
+ snd_ctl_elem_value_t *control;
+ snd_ctl_elem_type_t type;
+
+ snd_ctl_elem_info_alloca(&info);
+ snd_ctl_elem_id_alloca(&id);
+ snd_ctl_elem_value_alloca(&control);
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); /* MIXER */
+
+ // in amixer parse func
+ // char target[64];
+ // e.g. PGA CAPTure Switch
+ snd_ctl_elem_id_set_name(id, target.toAscii());
+
+ if (handle == NULL && (err = snd_ctl_open(&handle, card.toAscii(), 0)) < 0)
+ {
+ return;
+ }
+
+ snd_ctl_elem_info_set_id(info, id);
+ if ((err = snd_ctl_elem_info(handle, info)) < 0)
+ {
+ snd_ctl_close(handle);
+ handle = NULL;
+ return;
+ }
+
+ snd_ctl_elem_info_get_id(info, id); /* FIXME: Remove it when hctl find works ok !!! */
+ type = snd_ctl_elem_info_get_type(info);
+ count = snd_ctl_elem_info_get_count(info);
+
+ snd_ctl_elem_value_set_id(control, id);
+
+ tmp = 0;
+ for (uint idx = 0; idx < count && idx < 128; idx++)
+ {
+ switch (type)
+ {
+ case SND_CTL_ELEM_TYPE_BOOLEAN:
+#ifdef MULTIMEDIA_MAEMO_DEBUG
+ qDebug() << "SND_CTL_ELEM_TYPE_BOOLEAN" << SND_CTL_ELEM_TYPE_BOOLEAN;
+#endif
+ if ((value == "on") ||(value == "1"))
+ {
+ tmp = 1;
+ }
+ snd_ctl_elem_value_set_boolean(control, idx, tmp);
+ break;
+ case SND_CTL_ELEM_TYPE_ENUMERATED:
+ tmp = getEnumItemIndex(handle, info, value);
+ snd_ctl_elem_value_set_enumerated(control, idx, tmp);
+ break;
+ case SND_CTL_ELEM_TYPE_INTEGER:
+#ifdef MULTIMEDIA_MAEMO_DEBUG
+ qDebug() << "SND_CTL_ELEM_TYPE_INTEGER" << SND_CTL_ELEM_TYPE_INTEGER;
+#endif
+ tmp = atoi(value.toAscii());
+ if (tmp < snd_ctl_elem_info_get_min(info))
+ tmp = snd_ctl_elem_info_get_min(info);
+ else if (tmp > snd_ctl_elem_info_get_max(info))
+ tmp = snd_ctl_elem_info_get_max(info);
+ snd_ctl_elem_value_set_integer(control, idx, tmp);
+ break;
+ default:
+ break;
+
+ }
+ }
+
+ if ((err = snd_ctl_elem_write(handle, control)) < 0) {
+ snd_ctl_close(handle);
+ handle = NULL;
+ return;
+ }
+
+ snd_ctl_close(handle);
+ handle = NULL;
+}
+
+
+int V4LRadioControl::getEnumItemIndex(snd_ctl_t *handle, snd_ctl_elem_info_t *info,
+ const QString &value)
+{
+ int items, i;
+
+ items = snd_ctl_elem_info_get_items(info);
+ if (items <= 0)
+ return -1;
+
+ for (i = 0; i < items; i++)
+ {
+ snd_ctl_elem_info_set_item(info, i);
+ if (snd_ctl_elem_info(handle, info) < 0)
+ return -1;
+ QString name = snd_ctl_elem_info_get_item_name(info);
+ if(name == value)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+bool V4LRadioControl::isSearching() const
+{
+ return scanning;
+}
+
+void V4LRadioControl::cancelSearch()
+{
+ scanning = false;
+ timer->stop();
+}
+
+void V4LRadioControl::searchForward()
+{
+ // Scan up
+ if(scanning) {
+ cancelSearch();
+ return;
+ }
+ scanning = true;
+ forward = true;
+ timer->start();
+}
+
+void V4LRadioControl::searchBackward()
+{
+ // Scan down
+ if(scanning) {
+ cancelSearch();
+ return;
+ }
+ scanning = true;
+ forward = false;
+ timer->start();
+}
+
+void V4LRadioControl::start()
+{
+}
+
+void V4LRadioControl::stop()
+{
+}
+
+QRadioTuner::Error V4LRadioControl::error() const
+{
+ if(m_error)
+ return QRadioTuner::OpenError;
+
+ return QRadioTuner::NoError;
+}
+
+QString V4LRadioControl::errorString() const
+{
+ return QString();
+}
+
+void V4LRadioControl::search()
+{
+ if(!scanning) return;
+
+ if(forward) {
+ setFrequency(currentFreq+step);
+ } else {
+ setFrequency(currentFreq-step);
+ }
+
+ int signal = signalStrength();
+ if(sig != signal) {
+ sig = signal;
+ emit signalStrengthChanged(sig);
+ }
+
+ if (signal > 25) {
+ cancelSearch();
+ return;
+ }
+}
+
+bool V4LRadioControl::initRadio()
+{
+ v4l2_tuner tuner;
+ v4l2_frequency freq;
+ v4l2_capability cap;
+
+ low = false;
+ available = false;
+ freqMin = freqMax = currentFreq = 0;
+
+ fd = ::open("/dev/radio1", O_RDWR);
+
+ if(fd != -1) {
+ // Capabilities
+ memset(&cap, 0, sizeof(cap));
+ if(::ioctl(fd, VIDIOC_QUERYCAP, &cap ) >= 0) {
+ available = true;
+ }
+
+ tuner.index = 0;
+
+ if (ioctl(fd, VIDIOC_G_TUNER, &tuner) < 0) {
+ return false;
+ }
+
+ if (tuner.type != V4L2_TUNER_RADIO)
+ return false;
+
+ if ((tuner.capability & V4L2_TUNER_CAP_LOW) != 0) {
+ // Units are 1/16th of a kHz.
+ low = true;
+ }
+
+ if(low) {
+ freqMin = tuner.rangelow * 62.5;
+ freqMax = tuner.rangehigh * 62.5;
+ } else {
+ freqMin = tuner.rangelow * 62500;
+ freqMax = tuner.rangehigh * 62500;
+ }
+
+ // frequency
+ memset(&freq, 0, sizeof(freq));
+
+ if(::ioctl(fd, VIDIOC_G_FREQUENCY, &freq) >= 0) {
+ if (((int)freq.frequency) != -1) { // -1 means not set.
+ if(low)
+ currentFreq = freq.frequency * 62.5;
+ else
+ currentFreq = freq.frequency * 62500;
+ }
+ }
+
+ // stereo
+ bool stereo = false;
+ memset(&tuner, 0, sizeof(tuner));
+ if (ioctl(fd, VIDIOC_G_TUNER, &tuner) >= 0) {
+ if((tuner.rxsubchans & V4L2_TUNER_SUB_STEREO) != 0)
+ stereo = true;
+ }
+
+ return true;
+ }
+
+ m_error = true;
+ emit error();
+
+ return false;
+}
diff --git a/src/plugins/v4l/radio/v4lradiocontrol_maemo5.h b/src/plugins/v4l/radio/v4lradiocontrol_maemo5.h
new file mode 100644
index 000000000..bbf64830c
--- /dev/null
+++ b/src/plugins/v4l/radio/v4lradiocontrol_maemo5.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** 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$
+** 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 V4LRADIOCONTROL_H
+#define V4LRADIOCONTROL_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qtimer.h>
+
+#include <qradiotunercontrol.h>
+
+#include <QtDBus/QtDBus>
+#include <gst/gst.h>
+
+#include <alsa/asoundlib.h>
+
+QT_USE_NAMESPACE
+
+class V4LRadioService;
+
+class V4LRadioControl : public QRadioTunerControl
+{
+ Q_OBJECT
+public:
+ V4LRadioControl(QObject *parent = 0);
+ ~V4LRadioControl();
+
+ bool isAvailable() const;
+ QtMultimediaKit::AvailabilityError availabilityError() const;
+
+ QRadioTuner::State state() const;
+
+ QRadioTuner::Band band() const;
+ void setBand(QRadioTuner::Band b);
+ bool isBandSupported(QRadioTuner::Band b) const;
+
+ int frequency() const;
+ int frequencyStep(QRadioTuner::Band b) const;
+ QPair<int,int> frequencyRange(QRadioTuner::Band b) const;
+ void setFrequency(int frequency);
+
+ bool isStereo() const;
+ QRadioTuner::StereoMode stereoMode() const;
+ void setStereoMode(QRadioTuner::StereoMode mode);
+
+ int signalStrength() const;
+
+ int volume() const;
+ void setVolume(int volume);
+
+ bool isMuted() const;
+ void setMuted(bool muted);
+
+ bool isSearching() const;
+ void cancelSearch();
+
+ void searchForward();
+ void searchBackward();
+
+ void start();
+ void stop();
+
+ QRadioTuner::Error error() const;
+ QString errorString() const;
+
+public slots:
+ void enablePipeline(bool enable = true);
+
+private slots:
+ void search();
+ void enableFMRX();
+
+private:
+ bool initRadio();
+ void setupHeadPhone();
+ bool createGstPipeline();
+ void callAmixer(const QString& target, const QString& value);
+ int getEnumItemIndex(snd_ctl_t *handle, snd_ctl_elem_info_t *info, const QString &value);
+ int vol(snd_hctl_elem_t *elem) const;
+
+private:
+ int fd;
+
+ bool m_error;
+ bool muted;
+ bool stereo;
+ bool low;
+ bool available;
+ int tuners;
+ int step;
+ int sig;
+ bool scanning;
+ bool forward;
+ QTimer* timer;
+ QTimer* tickTimer;
+ QRadioTuner::Band currentBand;
+ qint64 freqMin;
+ qint64 freqMax;
+ qint64 currentFreq;
+
+ GstElement *pipeline;
+
+ QDBusInterface* FMRXEnablerIFace;
+};
+
+#endif
diff --git a/src/plugins/v4l/radio/v4lradioservice.cpp b/src/plugins/v4l/radio/v4lradioservice.cpp
new file mode 100644
index 000000000..2a67c90dd
--- /dev/null
+++ b/src/plugins/v4l/radio/v4lradioservice.cpp
@@ -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$
+** 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 <QtCore/qvariant.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtGui/qwidget.h>
+
+#include "v4lradioservice.h"
+#include "v4lradiocontrol.h"
+
+V4LRadioService::V4LRadioService(QObject *parent):
+ QMediaService(parent)
+{
+ m_control = new V4LRadioControl(this);
+}
+
+V4LRadioService::~V4LRadioService()
+{
+}
+
+QMediaControl *V4LRadioService::requestControl(const char* name)
+{
+ if (qstrcmp(name,QRadioTunerControl_iid) == 0)
+ return m_control;
+
+ return 0;
+}
+
+
+void V4LRadioService::releaseControl(QMediaControl *)
+{
+}
diff --git a/src/plugins/v4l/radio/v4lradioservice.h b/src/plugins/v4l/radio/v4lradioservice.h
new file mode 100644
index 000000000..f8664467d
--- /dev/null
+++ b/src/plugins/v4l/radio/v4lradioservice.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** 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$
+** 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 V4LRADIOSERVICE_H
+#define V4LRADIOSERVICE_H
+
+#include <QtCore/qobject.h>
+
+#include <qmediaservice.h>
+QT_USE_NAMESPACE
+
+class V4LRadioControl;
+
+class V4LRadioService : public QMediaService
+{
+ Q_OBJECT
+
+public:
+ V4LRadioService(QObject *parent = 0);
+ ~V4LRadioService();
+
+ QMediaControl *requestControl(const char* name);
+ void releaseControl(QMediaControl *);
+
+private:
+ V4LRadioControl *m_control;
+};
+
+#endif
diff --git a/src/plugins/v4l/v4l.pro b/src/plugins/v4l/v4l.pro
new file mode 100644
index 000000000..3242d486b
--- /dev/null
+++ b/src/plugins/v4l/v4l.pro
@@ -0,0 +1,13 @@
+load(qt_module)
+
+TARGET = qtmedia_v4lengine
+QT += multimediakit-private
+PLUGIN_TYPE = mediaservice
+
+load(qt_plugin)
+DESTDIR = $$QT.multimediakit.plugins/$${PLUGIN_TYPE}
+
+HEADERS += v4lserviceplugin.h
+SOURCES += v4lserviceplugin.cpp
+
+include(radio/radio.pri)
diff --git a/src/plugins/v4l/v4lserviceplugin.cpp b/src/plugins/v4l/v4lserviceplugin.cpp
new file mode 100644
index 000000000..3e02be9fa
--- /dev/null
+++ b/src/plugins/v4l/v4lserviceplugin.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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$
+** 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 <QtCore/qstring.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qdir.h>
+
+#include "v4lserviceplugin.h"
+#include "v4lradioservice.h"
+
+#include <qmediaserviceprovider.h>
+
+
+QStringList V4LServicePlugin::keys() const
+{
+ return QStringList() <<
+ QLatin1String(Q_MEDIASERVICE_RADIO);
+}
+
+QMediaService* V4LServicePlugin::create(QString const& key)
+{
+ if (key == QLatin1String(Q_MEDIASERVICE_RADIO))
+ return new V4LRadioService;
+
+ return 0;
+}
+
+void V4LServicePlugin::release(QMediaService *service)
+{
+ delete service;
+}
+
+QList<QByteArray> V4LServicePlugin::devices(const QByteArray &service) const
+{
+ return QList<QByteArray>();
+}
+
+QString V4LServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
+{
+ return QString();
+}
+
+
+Q_EXPORT_PLUGIN2(qtmedia_v4lengine, V4LServicePlugin);
+
diff --git a/src/plugins/v4l/v4lserviceplugin.h b/src/plugins/v4l/v4lserviceplugin.h
new file mode 100644
index 000000000..b95d70358
--- /dev/null
+++ b/src/plugins/v4l/v4lserviceplugin.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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$
+** 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 V4LSERVICEPLUGIN_H
+#define V4LSERVICEPLUGIN_H
+
+#include <qmediaserviceproviderplugin.h>
+
+QT_USE_NAMESPACE
+
+class V4LServicePlugin : public QMediaServiceProviderPlugin, public QMediaServiceSupportedDevicesInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
+public:
+ QStringList keys() const;
+ QMediaService* create(QString const& key);
+ void release(QMediaService *service);
+
+ QList<QByteArray> devices(const QByteArray &service) const;
+ QString deviceDescription(const QByteArray &service, const QByteArray &device);
+};
+
+#endif // V4LSERVICEPLUGIN_H
diff --git a/src/plugins/wmp/qevrvideooverlay.cpp b/src/plugins/wmp/qevrvideooverlay.cpp
new file mode 100644
index 000000000..ff301d109
--- /dev/null
+++ b/src/plugins/wmp/qevrvideooverlay.cpp
@@ -0,0 +1,357 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qevrvideooverlay.h"
+
+#include <d3d9.h>
+#include <wmp.h>
+
+QEvrVideoOverlay::QEvrVideoOverlay(HINSTANCE evrHwnd)
+ : m_ref(1)
+ , m_evrHwnd(evrHwnd)
+ , ptrMFCreateVideoPresenter(0)
+ , m_presenter(0)
+ , m_displayControl(0)
+ , m_aspectRatioMode(Qt::KeepAspectRatio)
+ , m_winId(0)
+ , m_fullScreen(0)
+{
+ ptrMFCreateVideoPresenter = reinterpret_cast<PtrMFCreateVideoPresenter>(
+ GetProcAddress(m_evrHwnd, "MFCreateVideoPresenter"));
+}
+
+QEvrVideoOverlay::~QEvrVideoOverlay()
+{
+ FreeLibrary(m_evrHwnd);
+}
+
+WId QEvrVideoOverlay::winId() const
+{
+ return m_winId;
+}
+
+void QEvrVideoOverlay::setWinId(WId id)
+{
+ m_winId = id;
+
+ if (QWidget *widget = QWidget::find(m_winId)) {
+ const QColor color = widget->palette().color(QPalette::Window);
+
+ m_windowColor = RGB(color.red(), color.green(), color.blue());
+ }
+
+ if (m_displayControl) {
+ m_displayControl->SetVideoWindow(id);
+ m_displayControl->SetAspectRatioMode(m_aspectRatioMode == Qt::KeepAspectRatio
+ ? MFVideoARMode_PreservePicture
+ : MFVideoARMode_None);
+ m_displayControl->SetBorderColor(m_windowColor);
+
+ setDisplayRect(m_displayRect);
+ }
+}
+
+QRect QEvrVideoOverlay::displayRect() const
+{
+ return m_displayRect;
+}
+
+void QEvrVideoOverlay::setDisplayRect(const QRect &rect)
+{
+ if (m_displayControl) {
+ RECT displayRect = { rect.left(), rect.top(), rect.right() + 1, rect.bottom() + 1 };
+
+ if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
+ SIZE size;
+ m_displayControl->GetNativeVideoSize(&size, 0);
+
+ QSize clippedSize = rect.size();
+ clippedSize.scale(size.cx, size.cy, Qt::KeepAspectRatio);
+
+ long x = (size.cx - clippedSize.width()) / 2;
+ long y = (size.cy - clippedSize.height()) / 2;
+
+ MFVideoNormalizedRect sourceRect =
+ {
+ float(x) / size.cx,
+ float(y) / size.cy,
+ float(x + clippedSize.width()) / size.cx,
+ float(y + clippedSize.height()) / size.cy
+ };
+ m_displayControl->SetVideoPosition(&sourceRect, &displayRect);
+ } else {
+ m_displayControl->SetVideoPosition(0, &displayRect);
+ }
+ }
+
+ m_displayRect = rect;
+}
+
+bool QEvrVideoOverlay::isFullScreen() const
+{
+ return m_fullScreen;
+}
+
+void QEvrVideoOverlay::setFullScreen(bool fullScreen)
+{
+ emit fullScreenChanged(m_fullScreen = fullScreen);
+}
+
+QSize QEvrVideoOverlay::nativeSize() const
+{
+ SIZE size;
+
+ if (m_displayControl && m_displayControl->GetNativeVideoSize(&size, 0) == S_OK) {
+ return QSize(size.cx, size.cy);
+ } else {
+ return QSize();
+ }
+}
+
+Qt::AspectRatioMode QEvrVideoOverlay::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void QEvrVideoOverlay::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_aspectRatioMode = mode;
+
+ if (m_displayControl) {
+ m_displayControl->SetAspectRatioMode(mode == Qt::KeepAspectRatio
+ ? MFVideoARMode_PreservePicture
+ : MFVideoARMode_None);
+ setDisplayRect(m_displayRect);
+ }
+}
+
+void QEvrVideoOverlay::repaint()
+{
+ PAINTSTRUCT paint;
+
+ if (HDC dc = ::BeginPaint(m_winId, &paint)) {
+ if (m_displayControl) {
+ m_displayControl->RepaintVideo();
+ } else {
+ HPEN pen = ::CreatePen(PS_SOLID, 1, m_windowColor);
+ HBRUSH brush = ::CreateSolidBrush(m_windowColor);
+ ::SelectObject(dc, pen);
+ ::SelectObject(dc, brush);
+
+ ::Rectangle(
+ dc,
+ paint.rcPaint.left,
+ paint.rcPaint.top,
+ paint.rcPaint.right,
+ paint.rcPaint.bottom);
+
+ ::DeleteObject(pen);
+ ::DeleteObject(brush);
+ }
+
+ ::EndPaint(m_winId, &paint);
+ }
+}
+
+int QEvrVideoOverlay::brightness() const
+{
+ return 0;
+}
+
+void QEvrVideoOverlay::setBrightness(int)
+{
+}
+
+int QEvrVideoOverlay::contrast() const
+{
+ return 0;
+}
+
+void QEvrVideoOverlay::setContrast(int)
+{
+}
+
+int QEvrVideoOverlay::hue() const
+{
+ return 0;
+}
+
+void QEvrVideoOverlay::setHue(int)
+{
+}
+
+int QEvrVideoOverlay::saturation() const
+{
+ return 0;
+}
+
+void QEvrVideoOverlay::setSaturation(int)
+{
+}
+
+void QEvrVideoOverlay::setDisplayControl(IMFVideoDisplayControl *control)
+{
+ if (m_displayControl)
+ m_displayControl->Release();
+
+ m_displayControl = control;
+
+ if (m_displayControl) {
+ m_displayControl->AddRef();
+ m_displayControl->SetVideoWindow(m_winId);
+ m_displayControl->SetAspectRatioMode(m_aspectRatioMode == Qt::KeepAspectRatio
+ ? MFVideoARMode_PreservePicture
+ : MFVideoARMode_None);
+ m_displayControl->SetBorderColor(m_windowColor);
+
+ setDisplayRect(m_displayRect);
+ }
+}
+
+void QEvrVideoOverlay::openStateChanged(long state)
+{
+ if (state == wmposMediaOpen) {
+ setDisplayRect(m_displayRect);
+
+ emit nativeSizeChanged();
+ }
+};
+
+// IUnknown
+HRESULT QEvrVideoOverlay::QueryInterface(REFIID riid, void **object)
+{
+ if (!object) {
+ return E_POINTER;
+ } else if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(IMFAttributes)
+ || riid == __uuidof(IMFActivate)) {
+ *object = static_cast<IMFActivate *>(this);
+ } else {
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+
+ return S_OK;
+}
+
+ULONG QEvrVideoOverlay::AddRef()
+{
+ return InterlockedIncrement(&m_ref);
+}
+
+ULONG QEvrVideoOverlay::Release()
+{
+ ULONG ref = InterlockedDecrement(&m_ref);
+
+ Q_ASSERT(ref != 0);
+
+ return ref;
+}
+
+// IMFActivate
+HRESULT QEvrVideoOverlay::ActivateObject(REFIID riid, void **ppv)
+{
+ if (riid != __uuidof(IMFVideoPresenter)) {
+ return E_NOINTERFACE;
+ } else if (!ptrMFCreateVideoPresenter) {
+ return E_NOINTERFACE;
+ } else if (m_presenter) {
+ *ppv = m_presenter;
+
+ return S_OK;
+ } else {
+ IMFVideoDisplayControl *displayControl = 0;
+
+ IMFGetService *service;
+ HRESULT hr;
+ if ((hr = (*ptrMFCreateVideoPresenter)(
+ 0,
+ __uuidof(IDirect3DDevice9),
+ __uuidof(IMFVideoPresenter),
+ reinterpret_cast<void **>(&m_presenter))) != S_OK) {
+ qWarning("failed to create video presenter");
+ } else if ((hr = m_presenter->QueryInterface(
+ __uuidof(IMFGetService), reinterpret_cast<void **>(&service))) != S_OK) {
+ qWarning("failed to query IMFGetService interface");
+ } else {
+ if ((hr = service->GetService(
+ MR_VIDEO_RENDER_SERVICE,
+ __uuidof(IMFVideoDisplayControl),
+ reinterpret_cast<void **>(&displayControl))) != S_OK) {
+ qWarning("failed to get IMFVideoDisplayControl service");
+ }
+ service->Release();
+ }
+
+ setDisplayControl(displayControl);
+
+ if (m_presenter && hr != S_OK) {
+ m_presenter->Release();
+ m_presenter = 0;
+ }
+
+ *ppv = m_presenter;
+
+ return hr;
+ }
+}
+
+HRESULT QEvrVideoOverlay::ShutdownObject()
+{
+ setDisplayControl(0);
+
+ if (m_presenter) {
+ m_presenter->Release();
+ m_presenter = 0;
+ }
+ return S_OK;
+}
+
+HRESULT QEvrVideoOverlay::DetachObject()
+{
+ if (m_presenter) {
+ m_presenter->Release();
+ m_presenter = 0;
+ }
+
+ return S_OK;
+}
diff --git a/src/plugins/wmp/qevrvideooverlay.h b/src/plugins/wmp/qevrvideooverlay.h
new file mode 100644
index 000000000..247b16e96
--- /dev/null
+++ b/src/plugins/wmp/qevrvideooverlay.h
@@ -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$
+** 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 QEVRVIDEOOVERLAY_H
+#define QEVRVIDEOOVERLAY_H
+
+#include <qvideowindowcontrol.h>
+
+#include "qmfactivate.h"
+
+#include <evr.h>
+
+QT_USE_NAMESPACE
+
+class QEvrVideoOverlay : public QVideoWindowControl, public QMFActivate
+{
+ Q_OBJECT
+public:
+ QEvrVideoOverlay(HINSTANCE evrHwnd);
+ ~QEvrVideoOverlay();
+
+ WId winId() const;
+ void setWinId(WId id);
+
+ QRect displayRect() const;
+ void setDisplayRect(const QRect &rect);
+
+ bool isFullScreen() const;
+ void setFullScreen(bool fullScreen);
+
+ QSize nativeSize() const;
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ void repaint();
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ void setDisplayControl(IMFVideoDisplayControl *control);
+
+ // IUnknown
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **object);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ // IMFActivate
+ HRESULT STDMETHODCALLTYPE ActivateObject(REFIID riid, void **ppv);
+ HRESULT STDMETHODCALLTYPE ShutdownObject();
+ HRESULT STDMETHODCALLTYPE DetachObject();
+
+public Q_SLOTS:
+ void openStateChanged(long state);
+
+private:
+ typedef HRESULT (WINAPI *PtrMFCreateVideoPresenter)(IUnknown*, REFIID, REFIID, void**);
+
+ volatile LONG m_ref;
+ HINSTANCE m_evrHwnd;
+ PtrMFCreateVideoPresenter ptrMFCreateVideoPresenter;
+ IMFVideoPresenter *m_presenter;
+ IMFVideoDisplayControl *m_displayControl;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QSize m_sizeHint;
+ QRect m_displayRect;
+ WId m_winId;
+ COLORREF m_windowColor;
+ bool m_fullScreen;
+};
+
+#endif
diff --git a/src/plugins/wmp/qmfactivate.cpp b/src/plugins/wmp/qmfactivate.cpp
new file mode 100644
index 000000000..8cd64b0e4
--- /dev/null
+++ b/src/plugins/wmp/qmfactivate.cpp
@@ -0,0 +1,296 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qmfactivate.h"
+
+#include <QtCore/qglobal.h>
+
+#include <Mferror.h>
+
+
+// IMFAttributes
+
+HRESULT QMFActivate::GetItem(REFGUID guidKey, PROPVARIANT *pValue)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(pValue);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE *pType)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(pType);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL *pbResult)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(Value);
+ Q_UNUSED(pbResult);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QMFActivate::Compare(IMFAttributes *pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, BOOL *pbResult)
+{
+ Q_UNUSED(pTheirs);
+ Q_UNUSED(MatchType);
+ Q_UNUSED(pbResult);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QMFActivate::GetUINT32(REFGUID guidKey, UINT32 *punValue)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(punValue);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::GetUINT64(REFGUID guidKey, UINT64 *punValue)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(punValue);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::GetDouble(REFGUID guidKey, double *pfValue)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(pfValue);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::GetGUID(REFGUID guidKey, GUID *pguidValue)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(pguidValue);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::GetStringLength(REFGUID guidKey, UINT32 *pcchLength)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(pcchLength);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32 *pcchLength)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(pwszValue);
+ Q_UNUSED(cchBufSize);
+ Q_UNUSED(pcchLength);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::GetAllocatedString(REFGUID guidKey, LPWSTR *ppwszValue, UINT32 *pcchLength)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(ppwszValue);
+ Q_UNUSED(pcchLength);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::GetBlobSize(REFGUID guidKey, UINT32 *pcbBlobSize)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(pcbBlobSize);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::GetBlob(REFGUID guidKey, UINT8 *pBuf, UINT32 cbBufSize, UINT32 *pcbBlobSize)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(pBuf);
+ Q_UNUSED(cbBufSize);
+ Q_UNUSED(pcbBlobSize);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::GetAllocatedBlob(REFGUID guidKey, UINT8 **ppBuf, UINT32 *pcbSize)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(ppBuf);
+ Q_UNUSED(pcbSize);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::GetUnknown(REFGUID guidKey, REFIID riid, LPVOID *ppv)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(riid);
+ Q_UNUSED(ppv);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::SetItem(REFGUID guidKey, REFPROPVARIANT Value)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(Value);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QMFActivate::DeleteItem(REFGUID guidKey)
+{
+ Q_UNUSED(guidKey);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QMFActivate::DeleteAllItems()
+{
+ return E_NOTIMPL;
+}
+
+HRESULT QMFActivate::SetUINT32(REFGUID guidKey, UINT32 unValue)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(unValue);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QMFActivate::SetUINT64(REFGUID guidKey, UINT64 unValue)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(unValue);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QMFActivate::SetDouble(REFGUID guidKey, double fValue)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(fValue);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QMFActivate::SetGUID(REFGUID guidKey, REFGUID guidValue)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(guidValue);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QMFActivate::SetString(REFGUID guidKey, LPCWSTR wszValue)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(wszValue);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QMFActivate::SetBlob(REFGUID guidKey, const UINT8 *pBuf, UINT32 cbBufSize)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(pBuf);
+ Q_UNUSED(cbBufSize);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QMFActivate::SetUnknown(REFGUID guidKey, IUnknown *pUnknown)
+{
+ Q_UNUSED(guidKey);
+ Q_UNUSED(pUnknown);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QMFActivate::LockStore()
+{
+ m_mutex.lock();
+
+ return S_OK;
+}
+
+HRESULT QMFActivate::UnlockStore()
+{
+ m_mutex.unlock();
+
+ return S_OK;
+}
+
+HRESULT QMFActivate::GetCount(UINT32 *pcItems)
+{
+ if (!pcItems) {
+ return E_POINTER;
+ } else {
+ *pcItems = 0;
+
+ return S_OK;
+ }
+}
+
+HRESULT QMFActivate::GetItemByIndex(UINT32 unIndex, GUID *pguidKey, PROPVARIANT *pValue)
+{
+ Q_UNUSED(unIndex);
+ Q_UNUSED(pguidKey);
+ Q_UNUSED(pValue);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
+
+HRESULT QMFActivate::CopyAllItems(IMFAttributes *pDest)
+{
+ Q_UNUSED(pDest);
+
+ return MF_E_ATTRIBUTENOTFOUND;
+}
diff --git a/src/plugins/wmp/qmfactivate.h b/src/plugins/wmp/qmfactivate.h
new file mode 100644
index 000000000..0e1692689
--- /dev/null
+++ b/src/plugins/wmp/qmfactivate.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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$
+** 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 QMFACTIVATE_H
+#define QMFACTIVATE_H
+
+#include <QtCore/qmutex.h>
+
+#include <evr.h>
+
+class QMFActivate : public IMFActivate
+{
+public:
+ // IMFAttributes
+ HRESULT STDMETHODCALLTYPE GetItem(REFGUID guidKey, PROPVARIANT *pValue);
+ HRESULT STDMETHODCALLTYPE GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE *pType);
+ HRESULT STDMETHODCALLTYPE CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL *pbResult);
+ HRESULT STDMETHODCALLTYPE Compare(IMFAttributes *pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, BOOL *pbResult);
+ HRESULT STDMETHODCALLTYPE GetUINT32(REFGUID guidKey, UINT32 *punValue);
+ HRESULT STDMETHODCALLTYPE GetUINT64(REFGUID guidKey, UINT64 *punValue);
+ HRESULT STDMETHODCALLTYPE GetDouble(REFGUID guidKey, double *pfValue);
+ HRESULT STDMETHODCALLTYPE GetGUID(REFGUID guidKey, GUID *pguidValue);
+ HRESULT STDMETHODCALLTYPE GetStringLength(REFGUID guidKey, UINT32 *pcchLength);
+ HRESULT STDMETHODCALLTYPE GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32 *pcchLength);
+ HRESULT STDMETHODCALLTYPE GetAllocatedString(REFGUID guidKey, LPWSTR *ppwszValue, UINT32 *pcchLength);
+ HRESULT STDMETHODCALLTYPE GetBlobSize(REFGUID guidKey, UINT32 *pcbBlobSize);
+ HRESULT STDMETHODCALLTYPE GetBlob(REFGUID guidKey, UINT8 *pBuf, UINT32 cbBufSize, UINT32 *pcbBlobSize);
+ HRESULT STDMETHODCALLTYPE GetAllocatedBlob(REFGUID guidKey, UINT8 **ppBuf, UINT32 *pcbSize);
+ HRESULT STDMETHODCALLTYPE GetUnknown(REFGUID guidKey, REFIID riid, LPVOID *ppv);
+ HRESULT STDMETHODCALLTYPE SetItem(REFGUID guidKey, REFPROPVARIANT Value);
+ HRESULT STDMETHODCALLTYPE DeleteItem(REFGUID guidKey);
+ HRESULT STDMETHODCALLTYPE DeleteAllItems();
+ HRESULT STDMETHODCALLTYPE SetUINT32(REFGUID guidKey, UINT32 unValue);
+ HRESULT STDMETHODCALLTYPE SetUINT64(REFGUID guidKey, UINT64 unValue);
+ HRESULT STDMETHODCALLTYPE SetDouble(REFGUID guidKey, double fValue);
+ HRESULT STDMETHODCALLTYPE SetGUID(REFGUID guidKey, REFGUID guidValue);
+ HRESULT STDMETHODCALLTYPE SetString(REFGUID guidKey, LPCWSTR wszValue);
+ HRESULT STDMETHODCALLTYPE SetBlob(REFGUID guidKey, const UINT8 *pBuf, UINT32 cbBufSize);
+ HRESULT STDMETHODCALLTYPE SetUnknown(REFGUID guidKey, IUnknown *pUnknown);
+ HRESULT STDMETHODCALLTYPE LockStore();
+ HRESULT STDMETHODCALLTYPE UnlockStore();
+ HRESULT STDMETHODCALLTYPE GetCount(UINT32 *pcItems);
+ HRESULT STDMETHODCALLTYPE GetItemByIndex(UINT32 unIndex, GUID *pguidKey, PROPVARIANT *pValue);
+ HRESULT STDMETHODCALLTYPE CopyAllItems(IMFAttributes *pDest);
+
+private:
+ volatile LONG m_ref;
+ QMutex m_mutex;
+};
+
+
+#endif
diff --git a/src/plugins/wmp/qwmpevents.cpp b/src/plugins/wmp/qwmpevents.cpp
new file mode 100644
index 000000000..66df07b4a
--- /dev/null
+++ b/src/plugins/wmp/qwmpevents.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qwmpevents.h"
+
+#include "qwmpglobal.h"
+
+QWmpEvents::QWmpEvents(IUnknown *source, QObject *parent)
+ : QObject(parent)
+ , m_ref(1)
+ , m_connectionPoint(0)
+ , m_adviseCookie(0)
+{
+ HRESULT hr;
+ IConnectionPointContainer *container = 0;
+
+ if ((hr = source->QueryInterface(
+ IID_IConnectionPointContainer, reinterpret_cast<void **>(&container))) != S_OK) {
+ qWarning("No connection point container, %x: %d", hr, qwmp_error_string(hr));
+ } else {
+ if ((hr = container->FindConnectionPoint(
+ __uuidof(IWMPEvents), &m_connectionPoint)) != S_OK) {
+ qWarning("No connection point for IWMPEvents %d", hr);
+ } else if ((hr = m_connectionPoint->Advise(
+ static_cast<IWMPEvents3 *>(this), &m_adviseCookie)) != S_OK) {
+ qWarning("Failed to link to connection point, %x, %s", hr, qwmp_error_string(hr));
+
+ m_connectionPoint->Release();
+ m_connectionPoint = 0;
+ }
+ container->Release();
+ }
+}
+
+QWmpEvents::~QWmpEvents()
+{
+ if (m_connectionPoint) {
+ m_connectionPoint->Unadvise(m_adviseCookie);
+ m_connectionPoint->Release();
+ }
+
+ Q_ASSERT(m_ref == 1);
+}
+
+// IUnknown
+HRESULT QWmpEvents::QueryInterface(REFIID riid, void **object)
+{
+ if (!object) {
+ return E_POINTER;
+ } else if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(IWMPEvents)
+ || riid == __uuidof(IWMPEvents2)
+ || riid == __uuidof(IWMPEvents3)) {
+ *object = static_cast<IWMPEvents3 *>(this);
+
+ AddRef();
+
+ return S_OK;
+ } else {
+ return E_NOINTERFACE;
+ }
+}
+
+ULONG QWmpEvents::AddRef()
+{
+ return InterlockedIncrement(&m_ref);
+}
+
+ULONG QWmpEvents::Release()
+{
+ ULONG ref = InterlockedDecrement(&m_ref);
+
+ Q_ASSERT(ref != 0);
+
+ return ref;
+}
diff --git a/src/plugins/wmp/qwmpevents.h b/src/plugins/wmp/qwmpevents.h
new file mode 100644
index 000000000..1fb40309d
--- /dev/null
+++ b/src/plugins/wmp/qwmpevents.h
@@ -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$
+** 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 QWMPEVENTS_H
+#define QWMPEVENTS_H
+
+#include <QtCore/qobject.h>
+
+#include <wmp.h>
+
+class QWmpEvents : public QObject, public IWMPEvents3
+{
+ Q_OBJECT
+public:
+ QWmpEvents(IUnknown *source, QObject *parent = 0);
+ ~QWmpEvents();
+
+ // IUnknown
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+Q_SIGNALS:
+
+#ifndef Q_MOC_RUN
+ // IWMPEvents
+ void STDMETHODCALLTYPE OpenStateChange(long NewState);
+ void STDMETHODCALLTYPE PlayStateChange(long NewState);
+ void STDMETHODCALLTYPE AudioLanguageChange(long LangID);
+ void STDMETHODCALLTYPE StatusChange();
+ void STDMETHODCALLTYPE ScriptCommand(BSTR scType, BSTR Param);
+ void STDMETHODCALLTYPE NewStream();
+ void STDMETHODCALLTYPE Disconnect(long Result);
+ void STDMETHODCALLTYPE Buffering(VARIANT_BOOL Start);
+ void STDMETHODCALLTYPE Error();
+ void STDMETHODCALLTYPE Warning(long WarningType, long Param, BSTR Description);
+ void STDMETHODCALLTYPE EndOfStream(long Result);
+ void STDMETHODCALLTYPE PositionChange(double oldPosition, double newPosition);
+ void STDMETHODCALLTYPE MarkerHit(long MarkerNum);
+ void STDMETHODCALLTYPE DurationUnitChange(long NewDurationUnit);
+ void STDMETHODCALLTYPE CdromMediaChange(long CdromNum);
+ void STDMETHODCALLTYPE PlaylistChange(IDispatch *Playlist, WMPPlaylistChangeEventType change);
+ void STDMETHODCALLTYPE CurrentPlaylistChange(WMPPlaylistChangeEventType change);
+ void STDMETHODCALLTYPE CurrentPlaylistItemAvailable(BSTR bstrItemName);
+ void STDMETHODCALLTYPE MediaChange(IDispatch *Item);
+ void STDMETHODCALLTYPE CurrentMediaItemAvailable(BSTR bstrItemName);
+ void STDMETHODCALLTYPE CurrentItemChange(IDispatch *pdispMedia);
+ void STDMETHODCALLTYPE MediaCollectionChange();
+ void STDMETHODCALLTYPE MediaCollectionAttributeStringAdded(
+ BSTR bstrAttribName, BSTR bstrAttribVal);
+ void STDMETHODCALLTYPE MediaCollectionAttributeStringRemoved(
+ BSTR bstrAttribName, BSTR bstrAttribVal);
+ void STDMETHODCALLTYPE MediaCollectionAttributeStringChanged(
+ BSTR bstrAttribName, BSTR bstrOldAttribVal, BSTR bstrNewAttribVal);
+ void STDMETHODCALLTYPE PlaylistCollectionChange();
+ void STDMETHODCALLTYPE PlaylistCollectionPlaylistAdded(BSTR bstrPlaylistName);
+ void STDMETHODCALLTYPE PlaylistCollectionPlaylistRemoved(BSTR bstrPlaylistName);
+ void STDMETHODCALLTYPE PlaylistCollectionPlaylistSetAsDeleted(
+ BSTR bstrPlaylistName, VARIANT_BOOL varfIsDeleted);
+ void STDMETHODCALLTYPE ModeChange(BSTR ModeName, VARIANT_BOOL NewValue);
+ void STDMETHODCALLTYPE MediaError(IDispatch *pMediaObject);
+ void STDMETHODCALLTYPE OpenPlaylistSwitch(IDispatch *pItem);
+ void STDMETHODCALLTYPE DomainChange(BSTR strDomain);
+ void STDMETHODCALLTYPE SwitchedToPlayerApplication();
+ void STDMETHODCALLTYPE SwitchedToControl();
+ void STDMETHODCALLTYPE PlayerDockedStateChange();
+ void STDMETHODCALLTYPE PlayerReconnect();
+ void STDMETHODCALLTYPE Click(short nButton, short nShiftState, long fX, long fY);
+ void STDMETHODCALLTYPE DoubleClick(short nButton, short nShiftState, long fX, long fY);
+ void STDMETHODCALLTYPE KeyDown(short nKeyCode, short nShiftState);
+ void STDMETHODCALLTYPE KeyPress(short nKeyAscii);
+ void STDMETHODCALLTYPE KeyUp(short nKeyCode, short nShiftState);
+ void STDMETHODCALLTYPE MouseDown(short nButton, short nShiftState, long fX, long fY);
+ void STDMETHODCALLTYPE MouseMove(short nButton, short nShiftState, long fX, long fY);
+ void STDMETHODCALLTYPE MouseUp(short nButton, short nShiftState, long fX, long fY);
+
+ // IWMPEvents2
+ void STDMETHODCALLTYPE DeviceConnect(IWMPSyncDevice *pDevice);
+ void STDMETHODCALLTYPE DeviceDisconnect(IWMPSyncDevice *pDevice);
+ void STDMETHODCALLTYPE DeviceStatusChange(IWMPSyncDevice *pDevice, WMPDeviceStatus NewStatus);
+ void STDMETHODCALLTYPE DeviceSyncStateChange(IWMPSyncDevice *pDevice, WMPSyncState NewState);
+ void STDMETHODCALLTYPE DeviceSyncError(IWMPSyncDevice *pDevice, IDispatch *pMedia);
+ void STDMETHODCALLTYPE CreatePartnershipComplete(IWMPSyncDevice *pDevice, HRESULT hrResult);
+
+ // IWMPEvents3
+ void STDMETHODCALLTYPE CdromRipStateChange(IWMPCdromRip *pCdromRip, WMPRipState wmprs);
+ void STDMETHODCALLTYPE CdromRipMediaError(IWMPCdromRip *pCdromRip, IDispatch *pMedia);
+ void STDMETHODCALLTYPE CdromBurnStateChange(IWMPCdromBurn *pCdromBurn, WMPBurnState wmpbs);
+ void STDMETHODCALLTYPE CdromBurnMediaError(IWMPCdromBurn *pCdromBurn, IDispatch *pMedia);
+ void STDMETHODCALLTYPE CdromBurnError(IWMPCdromBurn *pCdromBurn, HRESULT hrError);
+ void STDMETHODCALLTYPE LibraryConnect(IWMPLibrary *pLibrary);
+ void STDMETHODCALLTYPE LibraryDisconnect(IWMPLibrary *pLibrary);
+ void STDMETHODCALLTYPE FolderScanStateChange(WMPFolderScanState wmpfss);
+ void STDMETHODCALLTYPE StringCollectionChange(
+ IDispatch *pdispStringCollection,
+ WMPStringCollectionChangeEventType change,
+ long lCollectionIndex);
+ void STDMETHODCALLTYPE MediaCollectionMediaAdded(IDispatch *pdispMedia);
+ void STDMETHODCALLTYPE MediaCollectionMediaRemoved(IDispatch *pdispMedia);
+#else
+ // Declare again without STDMETHODCALLTYPE for moc's benefit.
+
+ // IWMPEvents
+ void OpenStateChange(long NewState);
+ void PlayStateChange(long NewState);
+ void AudioLanguageChange(long LangID);
+ void StatusChange();
+ void ScriptCommand(BSTR scType, BSTR Param);
+ void NewStream();
+ void Disconnect(long Result);
+ void Buffering(VARIANT_BOOL Start);
+ void Error();
+ void Warning(long WarningType, long Param, BSTR Description);
+ void EndOfStream(long Result);
+ void PositionChange(double oldPosition, double newPosition);
+ void MarkerHit(long MarkerNum);
+ void DurationUnitChange(long NewDurationUnit);
+ void CdromMediaChange(long CdromNum);
+ void PlaylistChange(IDispatch *Playlist, WMPPlaylistChangeEventType change);
+ void CurrentPlaylistChange(WMPPlaylistChangeEventType change);
+ void CurrentPlaylistItemAvailable(BSTR bstrItemName);
+ void MediaChange(IDispatch *Item);
+ void CurrentMediaItemAvailable(BSTR bstrItemName);
+ void CurrentItemChange(IDispatch *pdispMedia);
+ void MediaCollectionChange();
+ void MediaCollectionAttributeStringAdded(
+ BSTR bstrAttribName, BSTR bstrAttribVal);
+ void MediaCollectionAttributeStringRemoved(
+ BSTR bstrAttribName, BSTR bstrAttribVal);
+ void MediaCollectionAttributeStringChanged(
+ BSTR bstrAttribName, BSTR bstrOldAttribVal, BSTR bstrNewAttribVal);
+ void PlaylistCollectionChange();
+ void PlaylistCollectionPlaylistAdded(BSTR bstrPlaylistName);
+ void PlaylistCollectionPlaylistRemoved(BSTR bstrPlaylistName);
+ void PlaylistCollectionPlaylistSetAsDeleted(
+ BSTR bstrPlaylistName, VARIANT_BOOL varfIsDeleted);
+ void ModeChange(BSTR ModeName, VARIANT_BOOL NewValue);
+ void MediaError(IDispatch *pMediaObject);
+ void OpenPlaylistSwitch(IDispatch *pItem);
+ void DomainChange(BSTR strDomain);
+ void SwitchedToPlayerApplication();
+ void SwitchedToControl();
+ void PlayerDockedStateChange();
+ void PlayerReconnect();
+ void Click(short nButton, short nShiftState, long fX, long fY);
+ void DoubleClick(short nButton, short nShiftState, long fX, long fY);
+ void KeyDown(short nKeyCode, short nShiftState);
+ void KeyPress(short nKeyAscii);
+ void KeyUp(short nKeyCode, short nShiftState);
+ void MouseDown(short nButton, short nShiftState, long fX, long fY);
+ void MouseMove(short nButton, short nShiftState, long fX, long fY);
+ void MouseUp(short nButton, short nShiftState, long fX, long fY);
+
+ // IWMPEvents2
+ void DeviceConnect(IWMPSyncDevice *pDevice);
+ void DeviceDisconnect(IWMPSyncDevice *pDevice);
+ void DeviceStatusChange(IWMPSyncDevice *pDevice, WMPDeviceStatus NewStatus);
+ void DeviceSyncStateChange(IWMPSyncDevice *pDevice, WMPSyncState NewState);
+ void DeviceSyncError(IWMPSyncDevice *pDevice, IDispatch *pMedia);
+ void CreatePartnershipComplete(IWMPSyncDevice *pDevice, HRESULT hrResult);
+
+ // IWMPEvents3
+ void CdromRipStateChange(IWMPCdromRip *pCdromRip, WMPRipState wmprs);
+ void CdromRipMediaError(IWMPCdromRip *pCdromRip, IDispatch *pMedia);
+ void CdromBurnStateChange(IWMPCdromBurn *pCdromBurn, WMPBurnState wmpbs);
+ void CdromBurnMediaError(IWMPCdromBurn *pCdromBurn, IDispatch *pMedia);
+ void CdromBurnError(IWMPCdromBurn *pCdromBurn, HRESULT hrError);
+ void LibraryConnect(IWMPLibrary *pLibrary);
+ void LibraryDisconnect(IWMPLibrary *pLibrary);
+ void FolderScanStateChange(WMPFolderScanState wmpfss);
+ void StringCollectionChange(
+ IDispatch *pdispStringCollection,
+ WMPStringCollectionChangeEventType change,
+ long lCollectionIndex);
+ void MediaCollectionMediaAdded(IDispatch *pdispMedia);
+ void MediaCollectionMediaRemoved(IDispatch *pdispMedia);
+#endif
+private:
+ volatile LONG m_ref;
+ IConnectionPoint *m_connectionPoint;
+ DWORD m_adviseCookie;
+};
+
+#endif
diff --git a/src/plugins/wmp/qwmpglobal.cpp b/src/plugins/wmp/qwmpglobal.cpp
new file mode 100644
index 000000000..4196bbc4f
--- /dev/null
+++ b/src/plugins/wmp/qwmpglobal.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qwmpglobal.h"
+
+#include <QtCore/qdebug.h>
+
+const char *qwmp_error_string(HRESULT hr)
+{
+ switch (hr) {
+ case S_OK:
+ return "OK";
+ case E_NOINTERFACE:
+ return "No such interface supported";
+ case E_POINTER:
+ return "Invalid pointer";
+ case E_FAIL:
+ return "Unspecified error";
+ case E_NOTIMPL:
+ return "Not implemented";
+ case CLASS_E_NOAGGREGATION:
+ return "Class does not support aggregation (or class object is remote)";
+ case CLASS_E_CLASSNOTAVAILABLE:
+ return "ClassFactory cannot supply requested class";
+ case CLASS_E_NOTLICENSED:
+ return "Class is not licensed for use";
+ default:
+ return "unknown error code";
+ }
+}
diff --git a/src/plugins/wmp/qwmpglobal.h b/src/plugins/wmp/qwmpglobal.h
new file mode 100644
index 000000000..f8152903f
--- /dev/null
+++ b/src/plugins/wmp/qwmpglobal.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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$
+** 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 QWMPGLOBAL_H
+#define QWMPGLOBAL_H
+
+#include <wmp.h>
+
+#include <QtCore/qstring.h>
+#include <QtCore/qurl.h>
+
+const char *qwmp_error_string(HRESULT hr);
+
+class QAutoBStr
+{
+public:
+ inline QAutoBStr(const QString &string)
+ : m_string(::SysAllocString(static_cast<const wchar_t *>(string.utf16())))
+ {
+ }
+
+ inline QAutoBStr(const QUrl &url)
+ : m_string(::SysAllocString(static_cast<const wchar_t *>(url.toString().utf16())))
+ {
+ }
+
+ inline QAutoBStr(const wchar_t *string)
+ : m_string(::SysAllocString(string))
+ {
+ }
+
+ inline ~QAutoBStr()
+ {
+ ::SysFreeString(m_string);
+ }
+
+ inline operator BSTR() const { return m_string; }
+
+private:
+ BSTR m_string;
+};
+
+
+
+#endif
diff --git a/src/plugins/wmp/qwmpmetadata.cpp b/src/plugins/wmp/qwmpmetadata.cpp
new file mode 100644
index 000000000..1f7cd0f88
--- /dev/null
+++ b/src/plugins/wmp/qwmpmetadata.cpp
@@ -0,0 +1,442 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qwmpmetadata.h"
+
+#include "qwmpevents.h"
+#include "qwmpglobal.h"
+
+#include <qmediacontent.h>
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+
+
+struct QWmpMetaDataKeyLookup
+{
+ QtMultimediaKit::MetaData key;
+ const wchar_t *token;
+};
+
+static const QWmpMetaDataKeyLookup qt_wmpMetaDataKeys[] =
+{
+ { QtMultimediaKit::Title, L"Title" },
+ { QtMultimediaKit::SubTitle, L"WM/SubTitle" },
+ { QtMultimediaKit::Author, L"Author" },
+ { QtMultimediaKit::Comment, L"Comment" },
+ { QtMultimediaKit::Description, L"Description" },
+ { QtMultimediaKit::Category, L"WM/Category" },
+ { QtMultimediaKit::Genre, L"WM/Genre" },
+ //{ QtMultimediaKit::Date, 0 },
+ { QtMultimediaKit::Year, L"WM/Year" },
+ { QtMultimediaKit::UserRating, L"UserRating" },
+ //{ QtMultimediaKit::MetaDatawords, 0 },
+ { QtMultimediaKit::Language, L"Language" },
+ { QtMultimediaKit::Publisher, L"WM/Publisher" },
+ { QtMultimediaKit::Copyright, L"Copyright" },
+ { QtMultimediaKit::ParentalRating, L"ParentalRating" },
+ { QtMultimediaKit::RatingOrganisation, L"RatingOrganisation" },
+
+ // Media
+ { QtMultimediaKit::Size, L"FileSize" },
+ { QtMultimediaKit::MediaType, L"MediaType" },
+ { QtMultimediaKit::Duration, L"Duration" },
+
+ // Audio
+ { QtMultimediaKit::AudioBitRate, L"AudioBitrate" },
+ { QtMultimediaKit::AudioCodec, L"AudioCodec" },
+ { QtMultimediaKit::ChannelCount, L"Channels" },
+ { QtMultimediaKit::SampleRate, L"Frequency" },
+
+ // Music
+ { QtMultimediaKit::AlbumTitle, L"WM/AlbumTitle" },
+ { QtMultimediaKit::AlbumArtist, L"WM/AlbumArtist" },
+ { QtMultimediaKit::ContributingArtist, L"Author" },
+ { QtMultimediaKit::Composer, L"WM/Composer" },
+ { QtMultimediaKit::Conductor, L"WM/Conductor" },
+ { QtMultimediaKit::Lyrics, L"WM/Lyrics" },
+ { QtMultimediaKit::Mood, L"WM/Mood" },
+ { QtMultimediaKit::TrackNumber, L"WM/TrackNumber" },
+ //{ QtMultimediaKit::TrackCount, 0 },
+ //{ QtMultimediaKit::CoverArtUrlSmall, 0 },
+ //{ QtMultimediaKit::CoverArtUrlLarge, 0 },
+
+ // Image/Video
+ //{ QtMultimediaKit::Resolution, 0 },
+ //{ QtMultimediaKit::PixelAspectRatio, 0 },
+
+ // Video
+ //{ QtMultimediaKit::FrameRate, 0 },
+ { QtMultimediaKit::VideoBitRate, L"VideoBitRate" },
+ { QtMultimediaKit::VideoCodec, L"VideoCodec" },
+
+ //{ QtMultimediaKit::PosterUrl, 0 },
+
+ // Movie
+ { QtMultimediaKit::ChapterNumber, L"ChapterNumber" },
+ { QtMultimediaKit::Director, L"WM/Director" },
+ { QtMultimediaKit::LeadPerformer, L"LeadPerformer" },
+ { QtMultimediaKit::Writer, L"WM/Writer" },
+
+ // Photos
+ { QtMultimediaKit::CameraManufacturer, L"CameraManufacturer" },
+ { QtMultimediaKit::CameraModel, L"CameraModel" },
+ { QtMultimediaKit::Event, L"Event" },
+ { QtMultimediaKit::Subject, L"Subject" }
+};
+
+QWmpMetaData::QWmpMetaData(IWMPCore3 *player, QWmpEvents *events, QObject *parent)
+ : QMetaDataReaderControl(parent)
+ , m_media(0)
+{
+ player->get_currentMedia(&m_media);
+
+ connect(events, SIGNAL(CurrentItemChange(IDispatch*)),
+ this, SLOT(currentItemChangeEvent(IDispatch*)));
+ connect(events, SIGNAL(MediaChange(IDispatch*)), this, SLOT(mediaChangeEvent(IDispatch*)));
+}
+
+QWmpMetaData::~QWmpMetaData()
+{
+ if (m_media)
+ m_media->Release();
+}
+
+bool QWmpMetaData::isMetaDataAvailable() const
+{
+ return m_media != 0;
+}
+
+bool QWmpMetaData::isWritable() const
+{
+ return m_media != 0;
+}
+
+QVariant QWmpMetaData::metaData(QtMultimediaKit::MetaData key) const
+{
+ static const int count = sizeof(qt_wmpMetaDataKeys) / sizeof(QWmpMetaDataKeyLookup);
+
+ switch (key) {
+ case QtMultimediaKit::Date:
+ {
+ QVariant day = value(m_media, QAutoBStr(L"ReleaseDateDay"));
+ QVariant month = value(m_media, QAutoBStr(L"ReleaseDateMonth"));
+ QVariant year = value(m_media, QAutoBStr(L"ReleaseDateYear"));
+
+ if (!day.isNull() && !month.isNull() && !year.isNull())
+ return QDate(year.toInt(), month.toInt(), day.toInt());
+ }
+ break;
+ case QtMultimediaKit::CoverArtUrlSmall:
+ return albumArtUrl(m_media, "_Small.jpg");
+ case QtMultimediaKit::CoverArtUrlLarge:
+ return albumArtUrl(m_media, "_Large.jpg");
+ case QtMultimediaKit::Resolution:
+ {
+ QVariant width = value(m_media, QAutoBStr(L"WM/VideoWidth"));
+ QVariant height = value(m_media, QAutoBStr(L"WM/VideoHeight"));
+
+ if (!width.isNull() && !height.isNull())
+ return QSize(width.toInt(), height.toInt());
+ }
+ break;
+ case QtMultimediaKit::PixelAspectRatio:
+ {
+ QVariant x = value(m_media, QAutoBStr(L"PixelAspectRatioX"));
+ QVariant y = value(m_media, QAutoBStr(L"PixelAspectRatioY"));
+
+ if (!x.isNull() && !y.isNull())
+ return QSize(x.toInt(), y.toInt());
+ }
+ break;
+ case QtMultimediaKit::VideoFrameRate:
+ break;
+ default:
+ for (int i = 0; i < count; ++i) {
+ if (qt_wmpMetaDataKeys[i].key == key)
+ return value(m_media, QAutoBStr(qt_wmpMetaDataKeys[i].token));
+ }
+ break;
+ }
+ return QVariant();
+}
+
+QList<QtMultimediaKit::MetaData> QWmpMetaData::availableMetaData() const
+{
+ QList<QtMultimediaKit::MetaData> keys;
+
+ if (m_media) {
+ // WMP will return a list of all possible keys so there's no point in filtering the keys
+ // in the lookup table.
+ static const int count = sizeof(qt_wmpMetaDataKeys) / sizeof(QWmpMetaDataKeyLookup);
+ for (int i = 0; i < count; ++i)
+ keys.append(qt_wmpMetaDataKeys[i].key);
+
+ BSTR string = 0;
+ if (m_media->get_sourceURL(&string) == S_OK) {
+ QString url = QString::fromWCharArray(static_cast<const wchar_t *>(string));
+ ::SysFreeString(string);
+
+ if (m_media->getItemInfo(QAutoBStr(L"WM/WMCollectionGroupID"), &string) == S_OK) {
+ QString uuid = QString::fromWCharArray(static_cast<const wchar_t *>(string));
+ ::SysFreeString(string);
+
+ QString albumArtLarge = QLatin1String("AlbumArt_") + uuid + QLatin1String("_Large.jpg");
+ QString albumArtSmall = QLatin1String("AlbumArt_") + uuid + QLatin1String("_Small.jpg");
+
+ QDir dir = QFileInfo(url).absoluteDir();
+
+ if (dir.exists(albumArtLarge))
+ keys.append(QtMultimediaKit::CoverArtUrlLarge);
+ if (dir.exists(albumArtSmall))
+ keys.append(QtMultimediaKit::CoverArtUrlSmall);
+ }
+ }
+ }
+ return keys;
+}
+
+QVariant QWmpMetaData::extendedMetaData(const QString &key) const
+{
+ return value(m_media, QAutoBStr(key));
+}
+
+QStringList QWmpMetaData::availableExtendedMetaData() const
+{
+ return keys(m_media);
+}
+
+void QWmpMetaData::currentItemChangeEvent(IDispatch *dispatch)
+{
+ IWMPMedia *media = m_media;
+
+ m_media = 0;
+ if (dispatch)
+ dispatch->QueryInterface(__uuidof(IWMPMedia), reinterpret_cast<void **>(&m_media));
+
+ if (media) {
+ if (m_media)
+ emit metaDataChanged();
+ else
+ emit metaDataAvailableChanged(false);
+
+ media->Release();
+ } else {
+ if (m_media)
+ emit metaDataAvailableChanged(false);
+ }
+}
+
+void QWmpMetaData::mediaChangeEvent(IDispatch *dispatch)
+{
+ IWMPMedia *media = 0;
+ if (dispatch && dispatch->QueryInterface(
+ __uuidof(IWMPMedia), reinterpret_cast<void **>(&media)) == S_OK) {
+ VARIANT_BOOL isEqual = VARIANT_FALSE;
+ if (media->get_isIdentical(m_media, &isEqual) == S_OK && isEqual)
+ emit metaDataChanged();
+ media->Release();
+ }
+}
+
+
+QStringList QWmpMetaData::keys(IWMPMedia *media)
+{
+ QStringList keys;
+
+ long count = 0;
+ if (media && media->get_attributeCount(&count) == S_OK) {
+ for (long i = 0; i < count; ++i) {
+ BSTR string;
+ if (media->getAttributeName(i, &string) == S_OK) {
+ keys.append(QString::fromWCharArray(string, ::SysStringLen(string)));
+
+ ::SysFreeString(string);
+ }
+ }
+ }
+ return keys;
+}
+
+QVariant QWmpMetaData::value(IWMPMedia *media, BSTR key)
+{
+ QVariantList values;
+ IWMPMedia3 *media3 = 0;
+ if (media && media->QueryInterface(
+ __uuidof(IWMPMedia3), reinterpret_cast<void **>(&media3)) == S_OK) {
+ long count = 0;
+ media3->getAttributeCountByType(key, 0, &count);
+
+ // The count appears to only be valid for static properties, dynamic properties like
+ // PlaylistIndex will have a count of zero but return a value for index 0.
+ if (count == 0)
+ count = 1;
+
+ for (long i = 0; i < count; ++i) {
+ VARIANT var;
+ VariantInit(&var);
+
+ if (media3->getItemInfoByType(key, 0, i, &var) == S_OK) {
+ QVariant value = convertVariant(var);
+
+ if (!value.isNull())
+ values.append(value);
+
+ VariantClear(&var);
+ }
+ }
+ media3->Release();
+ }
+
+ switch (values.count()) {
+ case 0:
+ return QVariant();
+ case 1:
+ return values.first();
+ default:
+ return values;
+ }
+}
+
+QMediaContent QWmpMetaData::resources(IWMPMedia *media)
+{
+ QMediaContent content;
+
+ BSTR string = 0;
+ if (media->get_sourceURL(&string) == S_OK) {
+ QString url = QString::fromWCharArray(static_cast<const wchar_t *>(string));
+ ::SysFreeString(string);
+
+ content = QMediaContent(QUrl(url));
+ }
+
+ return content;
+}
+
+QVariant QWmpMetaData::convertVariant(const VARIANT &variant)
+{
+ switch (variant.vt) {
+ case VT_I2:
+ return variant.iVal;
+ case VT_I4:
+ return variant.lVal;
+ case VT_I8:
+ return variant.llVal;
+ case VT_UI2:
+ return variant.uiVal;
+ case VT_UI4:
+ return quint32(variant.ulVal);
+ case VT_UI8:
+ return variant.ullVal;
+ case VT_INT:
+ return variant.intVal;
+ case VT_UINT:
+ return variant.uintVal;
+ case VT_BSTR:
+ return QString::fromWCharArray(variant.bstrVal, ::SysStringLen(variant.bstrVal));
+ case VT_DISPATCH:
+ {
+ IWMPMetadataPicture *picture = 0;
+ IWMPMetadataText *text = 0;
+
+ if (variant.pdispVal->QueryInterface(
+ __uuidof(IWMPMetadataPicture), reinterpret_cast<void **>(&picture)) == S_OK) {
+ QUrl url;
+ BSTR string;
+ if (picture->get_URL(&string) == S_OK) {
+ url = QUrl(QString::fromWCharArray(string, ::SysStringLen(string)));
+
+ ::SysFreeString(string);
+ }
+ picture->Release();
+ return qVariantFromValue(url);
+ } else if (variant.pdispVal->QueryInterface(
+ __uuidof(IWMPMetadataText), reinterpret_cast<void **>(&text)) == S_OK) {
+ QString description;
+ BSTR string;
+ if (text->get_description(&string) == S_OK) {
+ description = QString::fromWCharArray(string, SysStringLen(string));
+
+ ::SysFreeString(string);
+ }
+ text->Release();
+ return description;
+ } else {
+ qWarning("Unknown dispatch type");
+ }
+ }
+ break;
+ default:
+ qWarning("Unsupported Type %d %x", variant.vt, variant.vt);
+ break;
+ }
+
+ return QVariant();
+}
+
+QVariant QWmpMetaData::albumArtUrl(IWMPMedia *media, const char *suffix)
+{
+ BSTR string = 0;
+ if (media && media->get_sourceURL(&string) == S_OK) {
+ QString url = QString::fromWCharArray(static_cast<const wchar_t *>(string));
+ ::SysFreeString(string);
+
+ if (media->getItemInfo(QAutoBStr(L"WM/WMCollectionGroupID"), &string) == S_OK) {
+ QString uuid = QString::fromWCharArray(static_cast<const wchar_t *>(string));
+ ::SysFreeString(string);
+
+ QString fileName = QLatin1String("AlbumArt_") + uuid + QLatin1String(suffix);
+
+ QDir dir = QFileInfo(url).absoluteDir();
+
+ if (dir.exists(fileName)) {
+ return qVariantFromValue(
+ QUrl(QLatin1String("file:///") + dir.absoluteFilePath(fileName)));
+ }
+ }
+ }
+ return QVariant();
+}
diff --git a/src/plugins/wmp/qwmpmetadata.h b/src/plugins/wmp/qwmpmetadata.h
new file mode 100644
index 000000000..b01a05c4e
--- /dev/null
+++ b/src/plugins/wmp/qwmpmetadata.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** 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$
+** 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 QWMPMETADATA_H
+#define QWMPMETADATA_H
+
+#include <qmetadatareadercontrol.h>
+#include <qmediaresource.h>
+
+#include <wmp.h>
+
+QT_BEGIN_NAMESPACE
+class QMediaContent;
+QT_END_NAMESPACE
+
+class QWmpEvents;
+
+QT_USE_NAMESPACE
+
+class QWmpMetaData : public QMetaDataReaderControl
+{
+ Q_OBJECT
+public:
+ QWmpMetaData(IWMPCore3 *player, QWmpEvents *events, QObject *parent = 0);
+ ~QWmpMetaData();
+
+ bool isMetaDataAvailable() const;
+ bool isWritable() const;
+
+ QVariant metaData(QtMultimediaKit::MetaData key) const;
+ QList<QtMultimediaKit::MetaData> availableMetaData() const;
+
+ QVariant extendedMetaData(const QString &key) const ;
+ QStringList availableExtendedMetaData() const;
+
+ static QStringList keys(IWMPMedia *media);
+ static QVariant value(IWMPMedia *media, BSTR key);
+ static QMediaContent resources(IWMPMedia *media);
+ static QVariant convertVariant(const VARIANT &variant);
+ static QVariant albumArtUrl(IWMPMedia *media, const char *suffix);
+
+private Q_SLOTS:
+ void currentItemChangeEvent(IDispatch *dispatch);
+ void mediaChangeEvent(IDispatch *dispatch);
+
+private:
+ IWMPMedia *m_media;
+};
+
+#endif
diff --git a/src/plugins/wmp/qwmpplayercontrol.cpp b/src/plugins/wmp/qwmpplayercontrol.cpp
new file mode 100644
index 000000000..be8f107b8
--- /dev/null
+++ b/src/plugins/wmp/qwmpplayercontrol.cpp
@@ -0,0 +1,465 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qwmpplayercontrol.h"
+
+#include "qwmpevents.h"
+#include "qwmpglobal.h"
+#include "qwmpmetadata.h"
+#include "qwmpplaylist.h"
+
+#include <qmediaplayer.h>
+#include <qmediaplaylist.h>
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+
+QWmpPlayerControl::QWmpPlayerControl(IWMPCore3 *player, QWmpEvents *events, QObject *parent)
+ : QMediaPlayerControl(parent)
+ , m_player(player)
+ , m_controls(0)
+ , m_settings(0)
+ , m_state(QMediaPlayer::StoppedState)
+ , m_changes(0)
+ , m_buffering(false)
+ , m_audioAvailable(false)
+ , m_videoAvailable(false)
+{
+ m_player->get_controls(&m_controls);
+ m_player->get_settings(&m_settings);
+ m_player->get_network(&m_network);
+
+ if (m_settings)
+ m_settings->put_autoStart(FALSE);
+
+ WMPPlayState state = wmppsUndefined;
+ if (m_player->get_playState(&state) == S_OK)
+ playStateChangeEvent(state);
+
+ connect(events, SIGNAL(Buffering(VARIANT_BOOL)), this, SLOT(bufferingEvent(VARIANT_BOOL)));
+ connect(events, SIGNAL(PositionChange(double,double)),
+ this, SLOT(positionChangeEvent(double,double)));
+ connect(events, SIGNAL(PlayStateChange(long)), this, SLOT(playStateChangeEvent(long)));
+ connect(events, SIGNAL(CurrentItemChange(IDispatch*)),
+ this, SLOT(currentItemChangeEvent(IDispatch*)));
+ connect(events, SIGNAL(MediaChange(IDispatch*)), this, SLOT(mediaChangeEvent(IDispatch*)));
+}
+
+QWmpPlayerControl::~QWmpPlayerControl()
+{
+ if (m_controls) m_controls->Release();
+ if (m_settings) m_settings->Release();
+ if (m_network) m_network->Release();
+}
+
+QMediaPlayer::State QWmpPlayerControl::state() const
+{
+ return m_state;
+}
+
+QMediaPlayer::MediaStatus QWmpPlayerControl::mediaStatus() const
+{
+ return m_status;
+}
+
+qint64 QWmpPlayerControl::duration() const
+{
+ double duration = 0.;
+
+ IWMPMedia *media = 0;
+ if (m_controls && m_controls->get_currentItem(&media) == S_OK) {
+ media->get_duration(&duration);
+ media->Release();
+ }
+
+ return duration * 1000;
+}
+
+qint64 QWmpPlayerControl::position() const
+{
+ double position = 0.0;
+
+ if (m_controls)
+ m_controls->get_currentPosition(&position);
+
+ return position * 1000;
+}
+
+void QWmpPlayerControl::setPosition(qint64 position)
+{
+ if (m_controls)
+ m_controls->put_currentPosition(double(position) / 1000.);
+}
+
+int QWmpPlayerControl::volume() const
+{
+ long volume = 0;
+
+ if (m_settings)
+ m_settings->get_volume(&volume);
+
+ return volume;
+}
+
+void QWmpPlayerControl::setVolume(int volume)
+{
+ if (m_settings && m_settings->put_volume(volume) == S_OK)
+ emit volumeChanged(volume);
+}
+
+bool QWmpPlayerControl::isMuted() const
+{
+ VARIANT_BOOL mute = FALSE;
+
+ if (m_settings)
+ m_settings->get_mute(&mute);
+
+ return mute;
+}
+
+void QWmpPlayerControl::setMuted(bool muted)
+{
+ if (m_settings && m_settings->put_mute(muted ? TRUE : FALSE) == S_OK)
+ emit mutedChanged(muted);
+
+}
+
+int QWmpPlayerControl::bufferStatus() const
+{
+ long progress = 0;
+
+ if (m_network)
+ m_network->get_bufferingProgress(&progress);
+
+ return progress;
+}
+
+bool QWmpPlayerControl::isVideoAvailable() const
+{
+ return m_videoAvailable;
+}
+
+bool QWmpPlayerControl::isAudioAvailable() const
+{
+ return m_audioAvailable;
+}
+
+void QWmpPlayerControl::setAudioAvailable(bool available)
+{
+ if (m_audioAvailable != available)
+ emit audioAvailableChanged(m_audioAvailable = available);
+}
+
+void QWmpPlayerControl::setVideoAvailable(bool available)
+{
+ if (m_videoAvailable != available)
+ emit videoAvailableChanged(m_videoAvailable = available);
+}
+
+bool QWmpPlayerControl::isSeekable() const
+{
+ return true;
+}
+
+QMediaTimeRange QWmpPlayerControl::availablePlaybackRanges() const
+{
+ QMediaTimeRange ranges;
+
+ IWMPMedia *media = 0;
+ if (m_controls && m_controls->get_currentItem(&media) == S_OK) {
+ double duration = 0;
+ media->get_duration(&duration);
+ media->Release();
+
+ if(duration > 0)
+ ranges.addInterval(0, duration * 1000);
+ }
+
+ return ranges;
+}
+
+qreal QWmpPlayerControl::playbackRate() const
+{
+ double rate = 0.;
+
+ if (m_settings)
+ m_settings->get_rate(&rate);
+
+ return rate;
+}
+
+void QWmpPlayerControl::setPlaybackRate(qreal rate)
+{
+ if (m_settings)
+ m_settings->put_rate(rate);
+}
+
+void QWmpPlayerControl::play()
+{
+ if (m_controls)
+ m_controls->play();
+}
+
+void QWmpPlayerControl::pause()
+{
+ if (m_controls)
+ m_controls->pause();
+}
+
+void QWmpPlayerControl::stop()
+{
+ if (m_controls)
+ m_controls->stop();
+}
+
+QMediaContent QWmpPlayerControl::media() const
+{
+ QMediaResourceList resources;
+
+ QUrl tmpUrl = url();
+
+ if (!tmpUrl.isEmpty())
+ resources << QMediaResource(tmpUrl);
+
+ return resources;
+}
+
+const QIODevice *QWmpPlayerControl::mediaStream() const
+{
+ return 0;
+}
+
+void QWmpPlayerControl::setMedia(const QMediaContent &content, QIODevice *stream)
+{
+ if (!content.isNull() && !stream)
+ setUrl(content.canonicalUrl());
+ else
+ setUrl(QUrl());
+}
+
+bool QWmpPlayerControl::event(QEvent *event)
+{
+ if (event->type() == QEvent::UpdateRequest) {
+ const int changes = m_changes;
+ m_changes = 0;
+
+ if (changes & DurationChanged)
+ emit durationChanged(duration());
+ if (changes & PositionChanged)
+ emit positionChanged(position());
+ if (changes & StatusChanged)
+ emit mediaStatusChanged(m_status);
+ if (changes & StateChanged)
+ emit stateChanged(m_state);
+
+ return true;
+ } else {
+ return QMediaPlayerControl::event(event);
+ }
+}
+
+void QWmpPlayerControl::scheduleUpdate(int change)
+{
+ if (m_changes == 0)
+ QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
+
+ m_changes |= change;
+}
+
+void QWmpPlayerControl::bufferingEvent(VARIANT_BOOL buffering)
+{
+ if (m_state != QMediaPlayer::StoppedState) {
+ m_status = buffering
+ ? QMediaPlayer::BufferingMedia
+ : QMediaPlayer::BufferedMedia;
+
+ scheduleUpdate(StatusChanged);
+ }
+}
+
+void QWmpPlayerControl::currentItemChangeEvent(IDispatch *)
+{
+ scheduleUpdate(DurationChanged);
+}
+
+void QWmpPlayerControl::mediaChangeEvent(IDispatch *dispatch)
+{
+ IWMPMedia *media = 0;
+ if (dispatch && dispatch->QueryInterface(
+ __uuidof(IWMPMedia), reinterpret_cast<void **>(&media)) == S_OK) {
+ IWMPMedia *currentMedia = 0;
+ if (m_controls && m_controls->get_currentItem(&currentMedia) == S_OK) {
+ VARIANT_BOOL isEqual = VARIANT_FALSE;
+ if (media->get_isIdentical(currentMedia, &isEqual) == S_OK && isEqual)
+ scheduleUpdate(DurationChanged);
+
+ currentMedia->Release();
+ }
+ media->Release();
+ }
+}
+
+void QWmpPlayerControl::positionChangeEvent(double , double)
+{
+ scheduleUpdate(PositionChanged);
+}
+
+void QWmpPlayerControl::playStateChangeEvent(long state)
+{
+ switch (state) {
+ case wmppsUndefined:
+ m_state = QMediaPlayer::StoppedState;
+ m_status = QMediaPlayer::UnknownMediaStatus;
+ scheduleUpdate(StatusChanged | StateChanged);
+ break;
+ case wmppsStopped:
+ if (m_state != QMediaPlayer::StoppedState) {
+ m_state = QMediaPlayer::StoppedState;
+ scheduleUpdate(StateChanged);
+
+ if (m_status != QMediaPlayer::EndOfMedia) {
+ m_status = QMediaPlayer::LoadedMedia;
+ scheduleUpdate(StatusChanged);
+ }
+ }
+ break;
+ case wmppsPaused:
+ if (m_state != QMediaPlayer::PausedState && m_status != QMediaPlayer::BufferedMedia) {
+ m_state = QMediaPlayer::PausedState;
+ m_status = QMediaPlayer::BufferedMedia;
+ scheduleUpdate(StatusChanged | StateChanged);
+ } else if (m_state != QMediaPlayer::PausedState) {
+ m_state = QMediaPlayer::PausedState;
+ scheduleUpdate(StateChanged);
+ } else if (m_status != QMediaPlayer::BufferedMedia) {
+ m_status = QMediaPlayer::BufferedMedia;
+
+ scheduleUpdate(StatusChanged);
+ }
+ break;
+ case wmppsPlaying:
+ case wmppsScanForward:
+ case wmppsScanReverse:
+ if (m_state != QMediaPlayer::PlayingState && m_status != QMediaPlayer::BufferedMedia) {
+ m_state = QMediaPlayer::PlayingState;
+ m_status = QMediaPlayer::BufferedMedia;
+ scheduleUpdate(StatusChanged | StateChanged);
+ } else if (m_state != QMediaPlayer::PlayingState) {
+ m_state = QMediaPlayer::PlayingState;
+ scheduleUpdate(StateChanged);
+ } else if (m_status != QMediaPlayer::BufferedMedia) {
+ m_status = QMediaPlayer::BufferedMedia;
+ scheduleUpdate(StatusChanged);
+ }
+
+ if (m_state != QMediaPlayer::PlayingState) {
+ m_state = QMediaPlayer::PlayingState;
+ scheduleUpdate(StateChanged);
+ }
+ if (m_status != QMediaPlayer::BufferedMedia) {
+ m_status = QMediaPlayer::BufferedMedia;
+ scheduleUpdate(StatusChanged);
+ }
+ break;
+ case wmppsBuffering:
+ case wmppsWaiting:
+ if (m_status != QMediaPlayer::StalledMedia && m_state != QMediaPlayer::StoppedState) {
+ m_status = QMediaPlayer::StalledMedia;
+ scheduleUpdate(StatusChanged);
+ }
+ break;
+ case wmppsMediaEnded:
+ if (m_status != QMediaPlayer::EndOfMedia && m_state != QMediaPlayer::StoppedState) {
+ m_state = QMediaPlayer::StoppedState;
+ m_status = QMediaPlayer::EndOfMedia;
+ scheduleUpdate(StatusChanged | StateChanged);
+ }
+ break;
+ case wmppsTransitioning:
+ break;
+ case wmppsReady:
+ if (m_status != QMediaPlayer::LoadedMedia) {
+ m_status = QMediaPlayer::LoadedMedia;
+ scheduleUpdate(StatusChanged);
+ }
+
+ if (m_state != QMediaPlayer::StoppedState) {
+ m_state = QMediaPlayer::StoppedState;
+ scheduleUpdate(StateChanged);
+ }
+ break;
+ case wmppsReconnecting:
+ if (m_status != QMediaPlayer::StalledMedia && m_state != QMediaPlayer::StoppedState) {
+ m_status = QMediaPlayer::StalledMedia;
+ scheduleUpdate(StatusChanged);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+QUrl QWmpPlayerControl::url() const
+{
+ BSTR string;
+ if (m_player && m_player->get_URL(&string) == S_OK) {
+ QUrl url(QString::fromWCharArray(string, SysStringLen(string)), QUrl::StrictMode);
+
+ SysFreeString(string);
+
+ return url;
+ } else {
+ return QUrl();
+ }
+}
+
+void QWmpPlayerControl::setUrl(const QUrl &url)
+{
+ if (url != QWmpPlayerControl::url() && m_player) {
+ BSTR string = SysAllocString(reinterpret_cast<const wchar_t *>(url.toString().unicode()));
+
+ m_player->put_URL(string);
+
+ SysFreeString(string);
+ }
+}
diff --git a/src/plugins/wmp/qwmpplayercontrol.h b/src/plugins/wmp/qwmpplayercontrol.h
new file mode 100644
index 000000000..d966b38b2
--- /dev/null
+++ b/src/plugins/wmp/qwmpplayercontrol.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QWMPPLAYERCONTROL_H
+#define QWMPPLAYERCONTROL_H
+
+#include <qmediaplayercontrol.h>
+
+#include <wmp.h>
+
+class QWmpEvents;
+class QWmpPlaylist;
+
+QT_USE_NAMESPACE
+class QWmpPlayerControl : public QMediaPlayerControl
+{
+ Q_OBJECT
+public:
+ QWmpPlayerControl(
+ IWMPCore3 *player, QWmpEvents *events, QObject *parent = 0);
+ ~QWmpPlayerControl();
+
+ QMediaPlayer::State state() const;
+ QMediaPlayer::MediaStatus mediaStatus() const;
+
+ QMediaPlaylist* mediaPlaylist() const;
+ bool setMediaPlaylist(QMediaPlaylist *playlist);
+
+ qint64 duration() const;
+
+ qint64 position() const;
+ void setPosition(qint64 position);
+
+ int playlistPosition() const;
+ void setPlaylistPosition(int position);
+
+ int volume() const;
+ void setVolume(int volume);
+
+ bool isMuted() const;
+ void setMuted(bool muted);
+
+ int bufferStatus() const;
+
+ bool isAudioAvailable() const;
+ void setAudioAvailable(bool available);
+
+ bool isVideoAvailable() const;
+ void setVideoAvailable(bool available);
+
+ qreal playbackRate() const;
+ void setPlaybackRate(qreal rate);
+
+ bool isSeekable() const;
+ QMediaTimeRange availablePlaybackRanges() const;
+
+ void play();
+ void pause();
+ void stop();
+
+ QMediaContent media() const;
+ const QIODevice *mediaStream() const;
+ void setMedia(const QMediaContent &content, QIODevice *stream);
+
+ QUrl url() const;
+ void setUrl(const QUrl &url);
+
+ bool event(QEvent *event);
+
+ using QMediaPlayerControl::positionChanged;
+
+private Q_SLOTS:
+
+ void bufferingEvent(VARIANT_BOOL buffering);
+ void currentItemChangeEvent(IDispatch *dispatch);
+ void mediaChangeEvent(IDispatch *dispatch);
+ void positionChangeEvent(double from, double to);
+ void playStateChangeEvent(long state);
+
+private:
+ enum Change
+ {
+ StateChanged = 0x01,
+ StatusChanged = 0x02,
+ PositionChanged = 0x04,
+ DurationChanged = 0x08
+ };
+
+ void scheduleUpdate(int change);
+
+ IWMPCore3 *m_player;
+ IWMPControls *m_controls;
+ IWMPSettings *m_settings;
+ IWMPNetwork *m_network;
+ QMediaPlayer::State m_state;
+ QMediaPlayer::MediaStatus m_status;
+ int m_changes;
+ bool m_buffering;
+ bool m_audioAvailable;
+ bool m_videoAvailable;
+};
+
+#endif
diff --git a/src/plugins/wmp/qwmpplayerservice.cpp b/src/plugins/wmp/qwmpplayerservice.cpp
new file mode 100644
index 000000000..e185aaf46
--- /dev/null
+++ b/src/plugins/wmp/qwmpplayerservice.cpp
@@ -0,0 +1,355 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qwmpplayerservice.h"
+
+#ifdef QWMP_EVR
+#include "qevrvideooverlay.h"
+#endif
+
+#include "qwmpglobal.h"
+#include "qwmpmetadata.h"
+#include "qwmpplayercontrol.h"
+#include "qwmpplaylist.h"
+#include "qwmpplaylistcontrol.h"
+#include "qwmpvideooverlay.h"
+
+#include <qmediaplayer.h>
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/quuid.h>
+#include <QtCore/qvariant.h>
+#include <QtGui/qevent.h>
+
+#include <d3d9.h>
+#include <wmprealestate.h>
+
+QWmpPlayerService::QWmpPlayerService(EmbedMode mode, QObject *parent)
+ : QMediaService(parent)
+ , m_ref(1)
+ , m_embedMode(mode)
+ , m_player(0)
+ , m_oleObject(0)
+ , m_events(0)
+ , m_control(0)
+ , m_metaData(0)
+ , m_playlist(0)
+ , m_activeVideoOverlay(0)
+ , m_oleVideoOverlay(0)
+#ifdef QWMP_EVR
+ , m_evrVideoOverlay(0)
+#endif
+{
+ HRESULT hr;
+
+ if ((hr = CoCreateInstance(
+ __uuidof(WindowsMediaPlayer),
+ 0,
+ CLSCTX_INPROC_SERVER,
+ __uuidof(IWMPPlayer4),
+ reinterpret_cast<void **>(&m_player))) != S_OK) {
+ qWarning("failed to create media player control, %x: %s", hr, qwmp_error_string(hr));
+ } else {
+ m_events = new QWmpEvents(m_player);
+
+ if ((hr = m_player->QueryInterface(
+ __uuidof(IOleObject), reinterpret_cast<void **>(&m_oleObject))) != S_OK) {
+ qWarning("No IOleObject interface, %x: %s", hr, qwmp_error_string(hr));
+ } else if ((hr = m_oleObject->SetClientSite(this)) != S_OK) {
+ qWarning("Failed to set site, %x: %s", hr, qwmp_error_string(hr));
+ }
+
+ if (m_embedMode == LocalEmbed)
+ m_oleVideoOverlay = new QWmpVideoOverlay(m_player, m_oleObject, this);
+
+ m_metaData = new QWmpMetaData(m_player, m_events);
+ m_playlist = new QWmpPlaylistControl(m_player, m_events);
+ m_control = new QWmpPlayerControl(m_player, m_events);
+ }
+}
+
+QWmpPlayerService::~QWmpPlayerService()
+{
+ delete m_control;
+ delete m_metaData;
+ delete m_playlist;
+ delete m_events;
+
+ if (m_oleObject) {
+ m_oleObject->SetClientSite(0);
+ m_oleObject->Release();
+ delete m_oleVideoOverlay;
+ }
+
+#ifdef QWMP_EVR
+ delete m_evrVideoOverlay;
+#endif
+
+
+ if (m_player)
+ m_player->Release();
+
+ Q_ASSERT(m_ref == 1);
+}
+
+QMediaControl *QWmpPlayerService::requestControl(const char *name)
+{
+ if (qstrcmp(name, QMediaPlayerControl_iid) == 0) {
+ return m_control;
+ } else if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) {
+ return m_metaData;
+ } else if (qstrcmp(name, QMediaPlaylistControl_iid) == 0) {
+ return m_playlist;
+ } else if (qstrcmp(name, QVideoWindowControl_iid) == 0
+ && m_embedMode == LocalEmbed
+ && m_player
+ && !m_activeVideoOverlay) {
+#ifdef QWMP_EVR
+ IWMPVideoRenderConfig *config = 0;
+ if (m_player->QueryInterface(
+ __uuidof(IWMPVideoRenderConfig), reinterpret_cast<void **>(&config)) == S_OK) {
+ if (HINSTANCE evrHwnd = LoadLibrary(L"evr")) {
+ m_evrVideoOverlay = new QEvrVideoOverlay(evrHwnd);
+
+ if (SUCCEEDED(config->put_presenterActivate(
+ static_cast<IMFActivate *>(m_evrVideoOverlay)))) {
+ connect(m_events, SIGNAL(OpenStateChange(long)),
+ m_evrVideoOverlay, SLOT(openStateChanged(long)));
+ } else {
+ delete m_evrVideoOverlay;
+
+ m_evrVideoOverlay = 0;
+ }
+ }
+ config->Release();
+ }
+
+ if (m_evrVideoOverlay) {
+ m_activeVideoOverlay = m_evrVideoOverlay;
+
+ return m_evrVideoOverlay;
+ } else
+#endif
+ if (SUCCEEDED(m_player->put_uiMode(QAutoBStr(L"none")))) {
+ m_activeVideoOverlay = m_oleVideoOverlay;
+
+ return m_oleVideoOverlay;
+ }
+ }
+ return 0;
+}
+
+void QWmpPlayerService::releaseControl(QMediaControl *control)
+{
+ if (!control) {
+ qWarning("QMediaService::releaseControl():"
+ " Attempted release of null control");
+#ifdef QWMP_EVR
+ } else if (control == m_evrVideoOverlay) {
+
+ IWMPVideoRenderConfig *config = 0;
+ if (m_player->QueryInterface(
+ __uuidof(IWMPVideoRenderConfig), reinterpret_cast<void **>(&config)) == S_OK) {
+ config->put_presenterActivate(0);
+ config->Release();
+ }
+
+ delete m_evrVideoOverlay;
+
+ m_evrVideoOverlay = 0;
+ m_activeVideoOverlay = 0;
+#endif
+ } else if (control == m_oleVideoOverlay) {
+ m_player->put_uiMode(QAutoBStr(L"invisible"));
+ m_oleVideoOverlay->setWinId(0);
+
+ m_activeVideoOverlay = 0;
+ }
+}
+
+// IUnknown
+HRESULT QWmpPlayerService::QueryInterface(REFIID riid, void **object)
+{
+ if (!object) {
+ return E_POINTER;
+ } else if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(IOleClientSite)) {
+ *object = static_cast<IOleClientSite *>(this);
+ } else if (riid == __uuidof(IServiceProvider)) {
+ *object = static_cast<IServiceProvider *>(this);
+ } else if (riid == __uuidof(IWMPRemoteMediaServices)) {
+ *object = static_cast<IWMPRemoteMediaServices *>(this);
+ } else if (riid == __uuidof(IOleWindow)
+ || riid == __uuidof(IOleInPlaceSite)) {
+ *object = static_cast<IOleInPlaceSite *>(m_oleVideoOverlay);
+ } else if (riid == __uuidof(IOleInPlaceUIWindow)
+ || riid == __uuidof(IOleInPlaceFrame)) {
+ *object = static_cast<IOleInPlaceFrame *>(m_oleVideoOverlay);
+ } else {
+ *object = 0;
+ }
+
+ if (*object) {
+ AddRef();
+
+ return S_OK;
+ } else {
+ return E_NOINTERFACE;
+ }
+}
+
+ULONG QWmpPlayerService::AddRef()
+{
+ return InterlockedIncrement(&m_ref);
+}
+
+ULONG QWmpPlayerService::Release()
+{
+ ULONG ref = InterlockedDecrement(&m_ref);
+
+ Q_ASSERT(ref != 0);
+
+ return ref;
+}
+
+// IOleClientSite
+HRESULT QWmpPlayerService::SaveObject()
+{
+ return E_NOTIMPL;
+}
+
+HRESULT QWmpPlayerService::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk)
+{
+ Q_UNUSED(dwAssign);
+ Q_UNUSED(dwWhichMoniker);
+ Q_UNUSED(ppmk);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QWmpPlayerService::GetContainer(IOleContainer **ppContainer)
+{
+ if (!ppContainer) {
+ return E_POINTER;
+ } else {
+ *ppContainer = 0;
+
+ return E_NOINTERFACE;
+ }
+}
+
+HRESULT QWmpPlayerService::ShowObject()
+{
+ return S_OK;
+}
+
+HRESULT QWmpPlayerService::OnShowWindow(BOOL fShow)
+{
+ Q_UNUSED(fShow);
+
+ return S_OK;
+}
+
+HRESULT QWmpPlayerService::RequestNewObjectLayout()
+{
+ return E_NOTIMPL;
+}
+
+// IServiceProvider
+HRESULT QWmpPlayerService::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
+{
+ Q_UNUSED(guidService);
+
+ if (!ppvObject) {
+ return E_POINTER;
+ } else if (riid == __uuidof(IWMPRemoteMediaServices)) {
+ *ppvObject = static_cast<IWMPRemoteMediaServices *>(this);
+
+ AddRef();
+
+ return S_OK;
+ } else {
+ return E_NOINTERFACE;
+ }
+}
+
+// IWMPRemoteMediaServices
+HRESULT QWmpPlayerService::GetServiceType(BSTR *pbstrType)
+{
+ if (!pbstrType) {
+ return E_POINTER;
+ } else if (m_embedMode == RemoteEmbed) {
+ *pbstrType = ::SysAllocString(L"Remote");
+
+ return S_OK;
+ } else {
+ *pbstrType = ::SysAllocString(L"Local");
+
+ return S_OK;
+ }
+}
+
+HRESULT QWmpPlayerService::GetApplicationName(BSTR *pbstrName)
+{
+ if (!pbstrName) {
+ return E_POINTER;
+ } else {
+ *pbstrName = ::SysAllocString(static_cast<const wchar_t *>(
+ QCoreApplication::applicationName().utf16()));
+
+ return S_OK;
+ }
+}
+
+HRESULT QWmpPlayerService::GetScriptableObject(BSTR *pbstrName, IDispatch **ppDispatch)
+{
+ Q_UNUSED(pbstrName);
+ Q_UNUSED(ppDispatch);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QWmpPlayerService::GetCustomUIMode(BSTR *pbstrFile)
+{
+ Q_UNUSED(pbstrFile);
+
+ return E_NOTIMPL;
+}
diff --git a/src/plugins/wmp/qwmpplayerservice.h b/src/plugins/wmp/qwmpplayerservice.h
new file mode 100644
index 000000000..ba79a9a68
--- /dev/null
+++ b/src/plugins/wmp/qwmpplayerservice.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** 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$
+** 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 QWMPPLAYERSERVICE_H
+#define QWMPPLAYERSERVICE_H
+
+#include "qwmpevents.h"
+
+#include <qmediaservice.h>
+
+QT_BEGIN_NAMESPACE
+class QMediaMetaData;
+class QMediaPlayerControl;
+class QMediaPlaylist;
+class QVideoWindowControl;
+QT_END_NAMESPACE
+
+#ifdef QWMP_EVR
+class QEvrVideoOverlay;
+#endif
+
+class QWmpMetaData;
+class QWmpPlayerControl;
+class QWmpPlaylist;
+class QWmpPlaylistControl;
+class QWmpVideoOverlay;
+
+QT_USE_NAMESPACE
+class QWmpPlayerService
+ : public QMediaService
+ , public IOleClientSite
+ , public IServiceProvider
+ , public IWMPRemoteMediaServices
+{
+ Q_OBJECT
+public:
+ enum EmbedMode
+ {
+ LocalEmbed,
+ RemoteEmbed
+ };
+
+ QWmpPlayerService(EmbedMode mode, QObject *parent = 0);
+ ~QWmpPlayerService();
+
+ QMediaControl *requestControl(const char *name);
+ void releaseControl(QMediaControl *control);
+
+ // IUnknown
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **object);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ // IOleClientSite
+ HRESULT STDMETHODCALLTYPE SaveObject();
+ HRESULT STDMETHODCALLTYPE GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk);
+ HRESULT STDMETHODCALLTYPE GetContainer(IOleContainer **ppContainer);
+ HRESULT STDMETHODCALLTYPE ShowObject();
+ HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL fShow);
+ HRESULT STDMETHODCALLTYPE RequestNewObjectLayout();
+
+ // IServiceProvider
+ HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
+
+ // IWMPRemoteMediaServices
+ HRESULT STDMETHODCALLTYPE GetServiceType(BSTR *pbstrType);
+ HRESULT STDMETHODCALLTYPE GetApplicationName(BSTR *pbstrName);
+ HRESULT STDMETHODCALLTYPE GetScriptableObject(BSTR *pbstrName, IDispatch **ppDispatch);
+ HRESULT STDMETHODCALLTYPE GetCustomUIMode(BSTR *pbstrFile);
+
+private:
+ volatile LONG m_ref;
+ const EmbedMode m_embedMode;
+ IWMPPlayer4 *m_player;
+ IOleObject *m_oleObject;
+ QWmpEvents *m_events;
+ QWmpPlayerControl *m_control;
+ QWmpMetaData *m_metaData;
+ QWmpPlaylistControl *m_playlist;
+ QVideoWindowControl *m_activeVideoOverlay;
+ QWmpVideoOverlay *m_oleVideoOverlay;
+#ifdef QWMP_EVR
+ QEvrVideoOverlay *m_evrVideoOverlay;
+#endif
+};
+
+#endif
diff --git a/src/plugins/wmp/qwmpplaylist.cpp b/src/plugins/wmp/qwmpplaylist.cpp
new file mode 100644
index 000000000..10ce753b1
--- /dev/null
+++ b/src/plugins/wmp/qwmpplaylist.cpp
@@ -0,0 +1,296 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qwmpplaylist.h"
+
+#include "qwmpevents.h"
+#include "qwmpmetadata.h"
+#include "qwmpglobal.h"
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+
+QWmpPlaylist::QWmpPlaylist(IWMPCore3 *player, QWmpEvents *events, QObject *parent)
+ : QMediaPlaylistProvider(parent)
+ , m_player(player)
+ , m_playlist(0)
+ , m_count(0)
+{
+ if (m_player && m_player->get_currentPlaylist(&m_playlist) == S_OK)
+ m_playlist->get_count(&m_count);
+
+ connect(events, SIGNAL(CurrentPlaylistChange(WMPPlaylistChangeEventType)),
+ this, SLOT(currentPlaylistChangeEvent(WMPPlaylistChangeEventType)));
+ connect(events, SIGNAL(OpenPlaylistSwitch(IDispatch*)),
+ this, SLOT(openPlaylistChangeEvent(IDispatch*)));
+ connect(events, SIGNAL(MediaChange(IDispatch*)), this, SLOT(mediaChangeEvent(IDispatch*)));
+}
+
+QWmpPlaylist::~QWmpPlaylist()
+{
+ if (m_playlist)
+ m_playlist->Release();
+}
+
+bool QWmpPlaylist::load(const QString &location, const char *format)
+{
+ Q_UNUSED(location);
+ Q_UNUSED(format);
+
+ return false;
+}
+
+bool QWmpPlaylist::load(QIODevice * device, const char *format)
+{
+ Q_UNUSED(device);
+ Q_UNUSED(format);
+
+ return false;
+}
+
+bool QWmpPlaylist::save(const QString &location, const char *format)
+{
+ Q_UNUSED(location);
+ Q_UNUSED(format);
+
+ return false;
+}
+
+bool QWmpPlaylist::save(QIODevice * device, const char *format)
+{
+ Q_UNUSED(device);
+ Q_UNUSED(format);
+
+ return false;
+}
+
+int QWmpPlaylist::mediaCount() const
+{
+ return m_count;
+}
+
+QMediaContent QWmpPlaylist::media(int pos) const
+{
+ QMediaContent content;
+
+ IWMPMedia *media = 0;
+ if (m_playlist && m_playlist->get_item(pos, &media) == S_OK) {
+ content = QWmpMetaData::resources(media);
+
+ media->Release();
+ }
+
+ return content;
+}
+
+bool QWmpPlaylist::isReadOnly() const
+{
+ return false;
+}
+
+bool QWmpPlaylist::addMedia(const QMediaContent &content)
+{
+ bool appended = false;
+
+ IWMPMedia *media = 0;
+ if (!content.isNull() && m_playlist && m_player && m_player->newMedia(
+ QAutoBStr(content.canonicalUrl()), &media) == S_OK) {
+ appended = m_playlist->appendItem(media) == S_OK;
+
+ media->Release();
+ }
+
+ return appended;
+}
+
+bool QWmpPlaylist::insertMedia(int pos, const QMediaContent &content)
+{
+ bool inserted = false;
+
+ IWMPMedia *media = 0;
+ if (m_playlist && m_player && m_player->newMedia(
+ QAutoBStr(content.canonicalUrl()), &media) == S_OK) {
+ inserted = m_playlist->insertItem(pos, media) == S_OK;
+
+ media->Release();
+ }
+
+ return inserted;
+}
+
+bool QWmpPlaylist::removeMedia(int pos)
+{
+ IWMPMedia *media = 0;
+ if (m_playlist->get_item(pos, &media) == S_OK) {
+ bool removed = m_playlist->removeItem(media) == S_OK;
+
+ media->Release();
+
+ return removed;
+ } else {
+ return false;
+ }
+}
+
+bool QWmpPlaylist::removeMedia(int start, int end)
+{
+ if (!m_playlist)
+ return false;
+
+ for (int i = start; i <= end; ++i) {
+ IWMPMedia *media = 0;
+ if (m_playlist->get_item(start, &media) == S_OK) {
+ bool removed = m_playlist->removeItem(media) == S_OK;
+
+ media->Release();
+
+ if (!removed)
+ return false;
+ }
+ }
+ return true;
+}
+
+bool QWmpPlaylist::clear()
+{
+ return m_playlist && m_playlist->clear() == S_OK;
+}
+
+QStringList QWmpPlaylist::keys(int index) const
+{
+ QStringList keys;
+
+ IWMPMedia *media = 0;
+ if (m_playlist && m_playlist->get_item(index, &media) == S_OK) {
+ keys = QWmpMetaData::keys(media);
+
+ media->Release();
+ }
+
+ return keys;
+}
+
+QVariant QWmpPlaylist::value(int index, const QString &key) const
+{
+ QVariant v;
+
+ IWMPMedia *media = 0;
+ if (m_playlist && m_playlist->get_item(index, &media) == S_OK) {
+ v = QWmpMetaData::value(media, QAutoBStr(key));
+
+ media->Release();
+ }
+
+ return v;
+}
+
+void QWmpPlaylist::shuffle()
+{
+}
+
+
+void QWmpPlaylist::currentPlaylistChangeEvent(WMPPlaylistChangeEventType change)
+{
+ Q_UNUSED(change);
+
+ long count = 0;
+ if (m_playlist && m_playlist->get_count(&count) == S_OK && count > 0) {
+ if (count > m_count) {
+ emit mediaAboutToBeInserted(m_count, count - 1);
+ m_count = count;
+ emit mediaInserted(count, m_count - 1);
+ } else if (count < m_count) {
+ emit mediaAboutToBeRemoved(count, m_count - 1);
+ m_count = count;
+ emit mediaRemoved(count, m_count - 1);
+ }
+ }
+ if (m_count > 0)
+ emit mediaChanged(0, m_count - 1);
+}
+
+void QWmpPlaylist::openPlaylistChangeEvent(IDispatch *dispatch)
+{
+ if (m_playlist && m_count > 0) {
+ emit mediaAboutToBeRemoved(0, m_count - 1);
+ m_playlist->Release();
+ m_playlist = 0;
+ m_count = 0;
+ emit mediaRemoved(0, m_count - 1);
+ } else if (m_playlist) {
+ m_playlist->Release();
+ m_playlist = 0;
+ }
+
+ IWMPPlaylist *playlist = 0;
+ if (dispatch && dispatch->QueryInterface(
+ __uuidof(IWMPPlaylist), reinterpret_cast<void **>(&playlist))) {
+
+ long count = 0;
+ if (playlist->get_count(&count) == S_OK && count > 0) {
+ emit mediaAboutToBeInserted(0, count - 1);
+ m_playlist = playlist;
+ m_count = count;
+ emit mediaInserted(0, count - 1);
+ } else {
+ m_playlist = playlist;
+ }
+ }
+}
+
+void QWmpPlaylist::mediaChangeEvent(IDispatch *dispatch)
+{
+
+ IWMPMedia *media = 0;
+ if (dispatch && dispatch->QueryInterface(
+ __uuidof(IWMPMedia), reinterpret_cast<void **>(&media)) == S_OK) {
+ VARIANT_BOOL isMember = VARIANT_FALSE;
+
+ if (media->isMemberOf(m_playlist, &isMember) == S_OK && isMember) {
+ int index = QWmpMetaData::value(media, QAutoBStr(L"PlaylistIndex")).toInt();
+
+ if (index >= 0)
+ emit mediaChanged(index, index);
+ }
+ media->Release();
+ }
+}
diff --git a/src/plugins/wmp/qwmpplaylist.h b/src/plugins/wmp/qwmpplaylist.h
new file mode 100644
index 000000000..be168a7b5
--- /dev/null
+++ b/src/plugins/wmp/qwmpplaylist.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** 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$
+** 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 QWMPPLAYLIST_H
+#define QWMPPLAYLIST_H
+
+#include <qmediaplaylistprovider.h>
+
+#include <QtCore/qvariant.h>
+
+#include <wmp.h>
+
+class QWmpEvents;
+
+QT_USE_NAMESPACE
+class QWmpPlaylist : public QMediaPlaylistProvider
+{
+ Q_OBJECT
+public:
+ QWmpPlaylist(IWMPCore3 *player, QWmpEvents *events, QObject *parent = 0);
+ ~QWmpPlaylist();
+
+ bool load(const QString &location, const char *format = 0);
+ bool load(QIODevice * device, const char *format = 0);
+ bool save(const QString &location, const char *format = 0);
+ bool save(QIODevice * device, const char *format);
+
+ int mediaCount() const;
+ QMediaContent media(int pos) const;
+
+ bool isReadOnly() const;
+
+ bool addMedia(const QMediaContent &content);
+ bool insertMedia(int pos, const QMediaContent &content);
+ bool removeMedia(int pos);
+ bool removeMedia(int start, int end);
+ bool clear();
+
+ QStringList keys(int index) const;
+ QVariant value(int index, const QString &key) const;
+
+public Q_SLOTS:
+ virtual void shuffle();
+
+private Q_SLOTS:
+ void currentPlaylistChangeEvent(WMPPlaylistChangeEventType change);
+ void openPlaylistChangeEvent(IDispatch *dispatch);
+ void mediaChangeEvent(IDispatch *dispatch);
+
+private:
+ IWMPCore3 *m_player;
+ IWMPPlaylist *m_playlist;
+ long m_count;
+};
+
+#endif
diff --git a/src/plugins/wmp/qwmpplaylistcontrol.cpp b/src/plugins/wmp/qwmpplaylistcontrol.cpp
new file mode 100644
index 000000000..f4cc12f7f
--- /dev/null
+++ b/src/plugins/wmp/qwmpplaylistcontrol.cpp
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qwmpplaylistcontrol.h"
+
+#include "qwmpevents.h"
+#include "qwmpglobal.h"
+#include "qwmpmetadata.h"
+#include "qwmpplaylist.h"
+
+QWmpPlaylistControl::QWmpPlaylistControl(IWMPCore3 *player, QWmpEvents *events, QObject *parent)
+ : QMediaPlaylistControl(parent)
+ , m_player(player)
+ , m_controls(0)
+ , m_playlist(new QWmpPlaylist(player, events))
+ , m_playbackMode(QMediaPlaylist::Sequential)
+{
+ m_player->get_controls(&m_controls);
+
+ connect(events, SIGNAL(CurrentItemChange(IDispatch*)),
+ this, SLOT(currentItemChangeEvent(IDispatch*)));
+}
+
+QWmpPlaylistControl::~QWmpPlaylistControl()
+{
+ if (m_controls)
+ m_controls->Release();
+
+ delete m_playlist;
+}
+
+QMediaPlaylistProvider *QWmpPlaylistControl::playlistProvider() const
+{
+ return m_playlist;
+}
+
+bool QWmpPlaylistControl::setPlaylistProvider(QMediaPlaylistProvider *playlist)
+{
+ Q_UNUSED(playlist);
+
+ return false;
+}
+
+int QWmpPlaylistControl::currentIndex() const
+{
+ int position = 0;
+
+ IWMPMedia *media = 0;
+ if (m_controls && m_player->get_currentMedia(&media) == S_OK) {
+ position = QWmpMetaData::value(media, QAutoBStr(L"PlaylistIndex")).toInt();
+
+ media->Release();
+ }
+
+ return position;
+}
+
+void QWmpPlaylistControl::setCurrentIndex(int position)
+{
+
+ IWMPPlaylist *playlist = 0;
+ if (m_player->get_currentPlaylist(&playlist) == S_OK) {
+ IWMPMedia *media = 0;
+ if (playlist->get_item(position, &media) == S_OK) {
+ m_player->put_currentMedia(media);
+
+ media->Release();
+ }
+ playlist->Release();
+ }
+}
+
+int QWmpPlaylistControl::nextIndex(int steps) const
+{
+ return currentIndex() + steps;
+}
+
+int QWmpPlaylistControl::previousIndex(int steps) const
+{
+ return currentIndex() - steps;
+}
+
+void QWmpPlaylistControl::next()
+{
+ if (m_controls)
+ m_controls->next();
+}
+
+void QWmpPlaylistControl::previous()
+{
+ if (m_controls)
+ m_controls->previous();
+}
+
+QMediaPlaylist::PlaybackMode QWmpPlaylistControl::playbackMode() const
+{
+ return m_playbackMode;
+}
+
+void QWmpPlaylistControl::setPlaybackMode(QMediaPlaylist::PlaybackMode mode)
+{
+ m_playbackMode = mode;
+}
+
+void QWmpPlaylistControl::currentItemChangeEvent(IDispatch *dispatch)
+{
+ IWMPMedia *media = 0;
+ if (dispatch && dispatch->QueryInterface(
+ __uuidof(IWMPMedia), reinterpret_cast<void **>(&media)) == S_OK) {
+ int index = QWmpMetaData::value(media, QAutoBStr(L"PlaylistIndex")).toInt();
+
+ emit currentIndexChanged(index);
+ emit currentMediaChanged(m_playlist->media(index));
+ }
+}
diff --git a/src/plugins/wmp/qwmpplaylistcontrol.h b/src/plugins/wmp/qwmpplaylistcontrol.h
new file mode 100644
index 000000000..cf519aebb
--- /dev/null
+++ b/src/plugins/wmp/qwmpplaylistcontrol.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 QWMPPLAYLISTCONTROL_H
+#define QWMPPLAYLISTCONTROL_H
+
+#include <qmediaplaylistcontrol.h>
+
+#include <wmp.h>
+
+class QWmpEvents;
+class QWmpPlaylist;
+
+QT_USE_NAMESPACE
+class QWmpPlaylistControl : public QMediaPlaylistControl
+{
+ Q_OBJECT
+public:
+ QWmpPlaylistControl(IWMPCore3 *player, QWmpEvents *events, QObject *parent = 0);
+ ~QWmpPlaylistControl();
+
+ QMediaPlaylistProvider *playlistProvider() const;
+ bool setPlaylistProvider(QMediaPlaylistProvider *playlist);
+
+ int currentIndex() const;
+ void setCurrentIndex(int position);
+
+ int nextIndex(int steps) const;
+ int previousIndex(int steps) const;
+
+ void next();
+ void previous();
+
+ QMediaPlaylist::PlaybackMode playbackMode() const;
+ void setPlaybackMode(QMediaPlaylist::PlaybackMode mode);
+
+private slots:
+ void currentItemChangeEvent(IDispatch *dispatch);
+
+private:
+ IWMPCore3 *m_player;
+ IWMPControls *m_controls;
+ QWmpPlaylist *m_playlist;
+ QMediaPlaylist::PlaybackMode m_playbackMode;
+};
+
+#endif
diff --git a/src/plugins/wmp/qwmpserviceprovider.cpp b/src/plugins/wmp/qwmpserviceprovider.cpp
new file mode 100644
index 000000000..eec06008e
--- /dev/null
+++ b/src/plugins/wmp/qwmpserviceprovider.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 "qwmpserviceprovider.h"
+
+#include "qwmpplayerservice.h"
+
+QStringList QWmpServiceProviderPlugin::keys() const
+{
+ return QStringList()
+ << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)
+ << QLatin1String("windowsmediaplayer");
+}
+
+QMediaService *QWmpServiceProviderPlugin::create(const QString &key)
+{
+ if (QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER) == key) {
+ QByteArray providerKey = qgetenv("QT_MEDIAPLAYER_PROVIDER");
+ if (!providerKey.isNull() && qstrcmp(providerKey.constData(), "windowsmediaplayer") == 0)
+ return new QWmpPlayerService(QWmpPlayerService::RemoteEmbed);
+
+ return new QWmpPlayerService(QWmpPlayerService::LocalEmbed);
+ }
+ else if (QLatin1String("windowsmediaplayer") == key)
+ return new QWmpPlayerService(QWmpPlayerService::RemoteEmbed);
+
+ return 0;
+}
+
+void QWmpServiceProviderPlugin::release(QMediaService *service)
+{
+ delete service;
+}
+
+
+Q_EXPORT_PLUGIN2(qtmedia_wmp, QWmpServiceProviderPlugin);
diff --git a/src/plugins/wmp/qwmpserviceprovider.h b/src/plugins/wmp/qwmpserviceprovider.h
new file mode 100644
index 000000000..d58fb3bc8
--- /dev/null
+++ b/src/plugins/wmp/qwmpserviceprovider.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** 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$
+** 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 QWMPSERVICEPROVIDER_H
+#define QWMPSERVICEPROVIDER_H
+
+#include <qmediaserviceprovider.h>
+#include <qmediaserviceproviderplugin.h>
+
+QT_USE_NAMESPACE
+class QWmpServiceProviderPlugin : public QMediaServiceProviderPlugin
+{
+ Q_OBJECT
+public:
+ QStringList keys() const;
+ QMediaService *create(const QString &key);
+ void release(QMediaService *service);
+};
+
+#endif
diff --git a/src/plugins/wmp/qwmpvideooverlay.cpp b/src/plugins/wmp/qwmpvideooverlay.cpp
new file mode 100644
index 000000000..95ff77b6b
--- /dev/null
+++ b/src/plugins/wmp/qwmpvideooverlay.cpp
@@ -0,0 +1,462 @@
+/****************************************************************************
+**
+** 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$
+** 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 "qwmpvideooverlay.h"
+
+#include "qwmpglobal.h"
+
+QWmpVideoOverlay::QWmpVideoOverlay(IWMPPlayer4 *player, IOleObject *object, QWmpPlayerService *service)
+ : m_service(service)
+ , m_player(player)
+ , m_object(object)
+ , m_inPlaceObject(0)
+ , m_winId(0)
+ , m_aspectRatioMode(Qt::KeepAspectRatio)
+ , m_fullScreen(false)
+{
+ HRESULT hr;
+
+ if ((hr = m_object->QueryInterface(
+ __uuidof(IOleInPlaceObject),
+ reinterpret_cast<void **>(&m_inPlaceObject))) != S_OK) {
+ qWarning("No IOleInPlaceObject interface, %x: %s", hr, qwmp_error_string(hr));
+ }
+}
+
+QWmpVideoOverlay::~QWmpVideoOverlay()
+{
+ if (m_inPlaceObject)
+ m_inPlaceObject->Release();
+}
+
+WId QWmpVideoOverlay::winId() const
+{
+ return m_winId;
+}
+
+void QWmpVideoOverlay::setWinId(WId id)
+{
+ m_winId = id;
+
+ if (QWidget *widget = QWidget::find(m_winId)) {
+ const QColor color = widget->palette().color(QPalette::Window);
+
+ m_windowColor = RGB(color.red(), color.green(), color.blue());
+ }
+
+ if (m_inPlaceObject && m_winId) {
+ RECT rcPos =
+ {
+ m_displayRect.left(),
+ m_displayRect.top(),
+ m_displayRect.right(),
+ m_displayRect.bottom()
+ };
+
+ m_inPlaceObject->InPlaceDeactivate();
+ m_object->DoVerb(OLEIVERB_INPLACEACTIVATE, 0, m_service, 0, m_winId, &rcPos);
+ }
+
+
+}
+
+extern HDC Q_GUI_EXPORT qt_win_display_dc();
+
+#define HIMETRIC_PER_INCH 2540
+#define MAP_PIX_TO_LOGHIM(x,ppli) ((HIMETRIC_PER_INCH*(x) + ((ppli)>>1)) / (ppli))
+#define MAP_LOGHIM_TO_PIX(x,ppli) (((ppli)*(x) + HIMETRIC_PER_INCH/2) / HIMETRIC_PER_INCH)
+
+QRect QWmpVideoOverlay::displayRect() const
+{
+ return m_displayRect;
+}
+
+void QWmpVideoOverlay::setDisplayRect(const QRect &rect)
+{
+ m_displayRect = rect;
+
+ if (m_inPlaceObject) {
+ HDC gdc = QT_PREPEND_NAMESPACE(qt_win_display_dc)();
+
+ SIZEL hmSize = {
+ MAP_PIX_TO_LOGHIM(rect.width(), GetDeviceCaps(gdc, LOGPIXELSX)),
+ MAP_PIX_TO_LOGHIM(rect.height(), GetDeviceCaps(gdc, LOGPIXELSY)) };
+
+ m_object->SetExtent(DVASPECT_CONTENT, &hmSize);
+
+ RECT rcClip = { rect.left(), rect.top(), rect.right(), rect.bottom() };
+
+ if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
+ QSize size = m_sizeHint;
+ size.scale(rect.width(), rect.height(), Qt::KeepAspectRatioByExpanding);
+
+ QRect positionRect(QPoint(0, 0), size);
+ positionRect.moveCenter(rect.center());
+
+ RECT rcPos =
+ {
+ positionRect.left(),
+ positionRect.top(),
+ positionRect.right(),
+ positionRect.bottom()
+ };
+
+ m_inPlaceObject->SetObjectRects(&rcPos, &rcClip);
+ } else {
+ m_inPlaceObject->SetObjectRects(&rcClip, &rcClip);
+ }
+ }
+}
+
+bool QWmpVideoOverlay::isFullScreen() const
+{
+ return m_fullScreen;
+}
+
+void QWmpVideoOverlay::setFullScreen(bool fullScreen)
+{
+ m_player->put_fullScreen(fullScreen);
+
+ emit fullScreenChanged(m_fullScreen = fullScreen);
+}
+
+QSize QWmpVideoOverlay::nativeSize() const
+{
+ return m_sizeHint;
+}
+
+void QWmpVideoOverlay::setNativeSize(const QSize &size)
+{
+ if (m_sizeHint != size) {
+ m_sizeHint = size;
+
+ emit nativeSizeChanged();
+ }
+}
+
+Qt::AspectRatioMode QWmpVideoOverlay::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void QWmpVideoOverlay::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_aspectRatioMode = mode;
+
+ m_player->put_stretchToFit(mode != Qt::KeepAspectRatio);
+
+ setDisplayRect(m_displayRect);
+}
+
+void QWmpVideoOverlay::repaint()
+{
+ PAINTSTRUCT paint;
+
+ if (HDC dc = ::BeginPaint(m_winId, &paint)) {
+ HPEN pen = ::CreatePen(PS_SOLID, 1, m_windowColor);
+ HBRUSH brush = ::CreateSolidBrush(m_windowColor);
+ ::SelectObject(dc, pen);
+ ::SelectObject(dc, brush);
+
+ ::Rectangle(
+ dc,
+ m_displayRect.left(),
+ m_displayRect.top(),
+ m_displayRect.right() + 1,
+ m_displayRect.bottom() + 1);
+
+ ::DeleteObject(pen);
+ ::DeleteObject(brush);
+
+ ::EndPaint(m_winId, &paint);
+ }
+}
+
+int QWmpVideoOverlay::brightness() const
+{
+ return 0;
+}
+
+void QWmpVideoOverlay::setBrightness(int)
+{
+}
+
+int QWmpVideoOverlay::contrast() const
+{
+ return 0;
+}
+
+void QWmpVideoOverlay::setContrast(int)
+{
+}
+
+int QWmpVideoOverlay::hue() const
+{
+ return 0;
+}
+
+void QWmpVideoOverlay::setHue(int)
+{
+}
+
+int QWmpVideoOverlay::saturation() const
+{
+ return 0;
+}
+
+void QWmpVideoOverlay::setSaturation(int)
+{
+}
+
+// IUnknown
+HRESULT QWmpVideoOverlay::QueryInterface(REFIID riid, void **object)
+{
+ return m_service->QueryInterface(riid, object);
+}
+
+ULONG QWmpVideoOverlay::AddRef()
+{
+ return m_service->AddRef();
+}
+
+ULONG QWmpVideoOverlay::Release()
+{
+ return m_service->Release();
+}
+
+// IOleWindow
+HRESULT QWmpVideoOverlay::GetWindow(HWND *phwnd)
+{
+ if (!phwnd) {
+ return E_POINTER;
+ } else {
+ *phwnd = m_winId;
+ return S_OK;
+ }
+}
+
+HRESULT QWmpVideoOverlay::ContextSensitiveHelp(BOOL fEnterMode)
+{
+ Q_UNUSED(fEnterMode);
+
+ return E_NOTIMPL;
+}
+
+// IOleInPlaceSite
+HRESULT QWmpVideoOverlay::CanInPlaceActivate()
+{
+ return S_OK;
+}
+
+HRESULT QWmpVideoOverlay::OnInPlaceActivate()
+{
+ return S_OK;
+}
+
+HRESULT QWmpVideoOverlay::OnUIActivate()
+{
+ return S_OK;
+}
+
+HRESULT QWmpVideoOverlay::GetWindowContext(
+ IOleInPlaceFrame **ppFrame,
+ IOleInPlaceUIWindow **ppDoc,
+ LPRECT lprcPosRect,
+ LPRECT lprcClipRect,
+ LPOLEINPLACEFRAMEINFO lpFrameInfo)
+{
+ if (!ppFrame || !ppDoc || !lprcPosRect || !lprcClipRect || !lpFrameInfo)
+ return E_POINTER;
+
+ QueryInterface(IID_IOleInPlaceFrame, reinterpret_cast<void **>(ppFrame));
+ QueryInterface(IID_IOleInPlaceUIWindow, reinterpret_cast<void **>(ppDoc));
+
+ if (m_winId) {
+ SetRect(lprcClipRect,
+ m_displayRect.left(),
+ m_displayRect.top(),
+ m_displayRect.right(),
+ m_displayRect.bottom());
+
+ if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
+ QSize size = m_sizeHint;
+ size.scale(
+ m_displayRect.width(),
+ m_displayRect.height(),
+ Qt::KeepAspectRatioByExpanding);
+
+ QRect positionRect(QPoint(0, 0), size);
+ positionRect.moveCenter(m_displayRect.center());
+
+ SetRect(lprcPosRect,
+ positionRect.left(),
+ positionRect.top(),
+ positionRect.right(),
+ positionRect.bottom());
+ } else {
+ *lprcPosRect = *lprcClipRect;
+ }
+ } else {
+ SetRectEmpty(lprcPosRect);
+ SetRectEmpty(lprcClipRect);
+ }
+
+ lpFrameInfo->fMDIApp = FALSE;
+ lpFrameInfo->haccel = 0;
+ lpFrameInfo->cAccelEntries = 0;
+ lpFrameInfo->hwndFrame = m_winId;
+
+ return S_OK;
+}
+
+HRESULT QWmpVideoOverlay::Scroll(SIZE scrollExtant)
+{
+ Q_UNUSED(scrollExtant);
+
+ return S_FALSE;
+}
+
+HRESULT QWmpVideoOverlay::OnUIDeactivate(BOOL fUndoable)
+{
+ Q_UNUSED(fUndoable);
+
+ return S_OK;
+}
+
+HRESULT QWmpVideoOverlay::OnInPlaceDeactivate()
+{
+ return S_OK;
+}
+
+HRESULT QWmpVideoOverlay::DiscardUndoState()
+{
+ return S_OK;
+}
+
+HRESULT QWmpVideoOverlay::DeactivateAndUndo()
+{
+ if (m_inPlaceObject)
+ m_inPlaceObject->UIDeactivate();
+
+ return S_OK;
+}
+
+HRESULT QWmpVideoOverlay::OnPosRectChange(LPCRECT lprcPosRect)
+{
+ Q_UNUSED(lprcPosRect);
+
+ return S_OK;
+}
+
+// IOleInPlaceUIWindow
+HRESULT QWmpVideoOverlay::GetBorder(LPRECT lprectBorder)
+{
+ Q_UNUSED(lprectBorder);
+
+ return INPLACE_E_NOTOOLSPACE;
+}
+
+HRESULT QWmpVideoOverlay::RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
+{
+ Q_UNUSED(pborderwidths);
+
+ return INPLACE_E_NOTOOLSPACE;
+}
+
+HRESULT QWmpVideoOverlay::SetBorderSpace(LPCBORDERWIDTHS pborderwidths)
+{
+ Q_UNUSED(pborderwidths);
+
+ return OLE_E_INVALIDRECT;
+}
+
+HRESULT QWmpVideoOverlay::SetActiveObject(
+ IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
+{
+ Q_UNUSED(pActiveObject);
+ Q_UNUSED(pszObjName);
+
+ return S_OK;
+}
+
+// IOleInPlaceFrame
+HRESULT QWmpVideoOverlay::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
+{
+ Q_UNUSED(hmenuShared);
+ Q_UNUSED(lpMenuWidths);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QWmpVideoOverlay::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
+{
+ Q_UNUSED(hmenuShared);
+ Q_UNUSED(holemenu);
+ Q_UNUSED(hwndActiveObject);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QWmpVideoOverlay::RemoveMenus(HMENU hmenuShared)
+{
+ Q_UNUSED(hmenuShared);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QWmpVideoOverlay::SetStatusText(LPCOLESTR pszStatusText)
+{
+ Q_UNUSED(pszStatusText);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QWmpVideoOverlay::EnableModeless(BOOL fEnable)
+{
+ Q_UNUSED(fEnable);
+
+ return E_NOTIMPL;
+}
+
+HRESULT QWmpVideoOverlay::TranslateAccelerator(LPMSG lpmsg, WORD wID)
+{
+ return TranslateAccelerator(lpmsg, static_cast<DWORD>(wID));
+}
diff --git a/src/plugins/wmp/qwmpvideooverlay.h b/src/plugins/wmp/qwmpvideooverlay.h
new file mode 100644
index 000000000..3bc1005a7
--- /dev/null
+++ b/src/plugins/wmp/qwmpvideooverlay.h
@@ -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$
+** 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 QWMPVIDEOOVERLAY_H
+#define QWMPVIDEOOVERLAY_H
+
+#include <qvideowindowcontrol.h>
+
+#include "qwmpplayerservice.h"
+
+#include <wmp.h>
+
+QT_USE_NAMESPACE
+class QWmpVideoOverlay
+ : public QVideoWindowControl
+ , public IOleInPlaceSite
+ , public IOleInPlaceFrame
+{
+ Q_OBJECT
+public:
+ QWmpVideoOverlay(IWMPPlayer4 *player, IOleObject *object, QWmpPlayerService *service);
+ ~QWmpVideoOverlay();
+
+ WId winId() const;
+ void setWinId(WId id);
+
+ QRect displayRect() const;
+ void setDisplayRect(const QRect &rect);
+
+ bool isFullScreen() const;
+ void setFullScreen(bool fullScreen);
+
+ void repaint();
+
+ QSize nativeSize() const;
+ void setNativeSize(const QSize &size);
+
+ Qt::AspectRatioMode aspectRatioMode() const;
+ void setAspectRatioMode(Qt::AspectRatioMode mode);
+
+ int brightness() const;
+ void setBrightness(int brightness);
+
+ int contrast() const;
+ void setContrast(int contrast);
+
+ int hue() const;
+ void setHue(int hue);
+
+ int saturation() const;
+ void setSaturation(int saturation);
+
+ // IUnknown
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **object);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ // IOleWindow
+ HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd);
+ HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
+
+ // IOleInPlaceSite
+ HRESULT STDMETHODCALLTYPE CanInPlaceActivate();
+ HRESULT STDMETHODCALLTYPE OnInPlaceActivate();
+ HRESULT STDMETHODCALLTYPE OnUIActivate();
+ HRESULT STDMETHODCALLTYPE GetWindowContext(
+ IOleInPlaceFrame **ppFrame,
+ IOleInPlaceUIWindow **ppDoc,
+ LPRECT lprcPosRect,
+ LPRECT lprcClipRect,
+ LPOLEINPLACEFRAMEINFO lpFrameInfo);
+ HRESULT STDMETHODCALLTYPE Scroll(SIZE scrollExtant);
+ HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL fUndoable);
+ HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate();
+ HRESULT STDMETHODCALLTYPE DiscardUndoState();
+ HRESULT STDMETHODCALLTYPE DeactivateAndUndo();
+ HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect);
+
+ // IOleInPlaceUIWindow
+ HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprectBorder);
+ HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS pborderwidths);
+ HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS pborderwidths);
+ HRESULT STDMETHODCALLTYPE SetActiveObject(
+ IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName);
+
+ // IOleInPlaceFrame
+ HRESULT STDMETHODCALLTYPE InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths);
+ HRESULT STDMETHODCALLTYPE SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject);
+ HRESULT STDMETHODCALLTYPE RemoveMenus(HMENU hmenuShared);
+ HRESULT STDMETHODCALLTYPE SetStatusText(LPCOLESTR pszStatusText);
+ HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable);
+ HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD wID);
+
+private:
+ QWmpPlayerService *m_service;
+ IWMPPlayer4 *m_player;
+ IOleObject *m_object;
+ IOleInPlaceObject *m_inPlaceObject;
+ WId m_winId;
+ COLORREF m_windowColor;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QSize m_sizeHint;
+ QRect m_displayRect;
+ bool m_fullScreen;
+};
+
+#endif
diff --git a/src/plugins/wmp/wmp.pro b/src/plugins/wmp/wmp.pro
new file mode 100644
index 000000000..1b544bbeb
--- /dev/null
+++ b/src/plugins/wmp/wmp.pro
@@ -0,0 +1,47 @@
+TEMPLATE = lib
+CONFIG += plugin
+TARGET = $$qtLibraryTarget(qtmedia_wmp)
+
+PLUGIN_TYPE=mediaservice
+
+INCLUDEPATH+=../../../src/multimedia
+include(../../../common.pri)
+
+CONFIG += mobility
+MOBILITY = multimedia
+LIBS += -lstrmiids -lole32 -lOleaut32 -luser32 -lgdi32
+
+HEADERS = \
+ qmfactivate.h \
+ qwmpevents.h \
+ qwmpglobal.h \
+ qwmpmetadata.h \
+ qwmpplayercontrol.h \
+ qwmpplayerservice.h \
+ qwmpplaylist.h \
+ qwmpplaylistcontrol.h \
+ qwmpserviceprovider.h \
+ qwmpvideooverlay.h
+
+SOURCES = \
+ qmfactivate.cpp \
+ qwmpevents.cpp \
+ qwmpglobal.cpp \
+ qwmpmetadata.cpp \
+ qwmpplayercontrol.cpp \
+ qwmpplayerservice.cpp \
+ qwmpplaylist.cpp \
+ qwmpplaylistcontrol.cpp \
+ qwmpserviceprovider.cpp \
+ qwmpvideooverlay.cpp
+
+contains(evr_enabled, yes) {
+ HEADERS += \
+ qevrvideooverlay.h
+
+ SOURCES += \
+ qevrvideooverlay.cpp
+
+ DEFINES += \
+ QWMP_EVR
+}
diff --git a/src/s60installs/backup_registration.xml b/src/s60installs/backup_registration.xml
new file mode 100644
index 000000000..37d61681c
--- /dev/null
+++ b/src/s60installs/backup_registration.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" standalone="yes"?>
+<backup_registration>
+ <system_backup/>
+ <passive_backup>
+ <include_directory name = "\" />
+ </passive_backup>
+ <restore requires_reboot = "no"/>
+</backup_registration>
diff --git a/src/s60installs/bwins/QtMultimediaKitu.def b/src/s60installs/bwins/QtMultimediaKitu.def
new file mode 100644
index 000000000..c1cff0781
--- /dev/null
+++ b/src/s60installs/bwins/QtMultimediaKitu.def
@@ -0,0 +1,1624 @@
+EXPORTS
+ ?tr@QMediaRecorderControl@@SA?AVQString@@PBD0H@Z @ 1 NONAME ; class QString QMediaRecorderControl::tr(char const *, char const *, int)
+ ?tr@QAbstractVideoSurface@@SA?AVQString@@PBD0@Z @ 2 NONAME ; class QString QAbstractVideoSurface::tr(char const *, char const *)
+ ?stop@QRadioTuner@@QAEXXZ @ 3 NONAME ; void QRadioTuner::stop(void)
+ ?setSampleRate@QAudioFormat@@QAEXH@Z @ 4 NONAME ; void QAudioFormat::setSampleRate(int)
+ ??1QMediaServiceProvider@@UAE@XZ @ 5 NONAME ; QMediaServiceProvider::~QMediaServiceProvider(void)
+ ??0QMediaTimeInterval@@QAE@XZ @ 6 NONAME ; QMediaTimeInterval::QMediaTimeInterval(void)
+ ?metaObject@QAbstractAudioDeviceInfo@@UBEPBUQMetaObject@@XZ @ 7 NONAME ; struct QMetaObject const * QAbstractAudioDeviceInfo::metaObject(void) const
+ ?tr@QAbstractAudioOutput@@SA?AVQString@@PBD0@Z @ 8 NONAME ; class QString QAbstractAudioOutput::tr(char const *, char const *)
+ ?qt_metacall@QAudioCaptureSource@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 9 NONAME ; int QAudioCaptureSource::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?mediaRemoved@QMediaPlaylist@@IAEXHH@Z @ 10 NONAME ; void QMediaPlaylist::mediaRemoved(int, int)
+ ?isSearching@QRadioTuner@@QBE_NXZ @ 11 NONAME ; bool QRadioTuner::isSearching(void) const
+ ??0QMediaResource@@QAE@ABVQNetworkRequest@@ABVQString@@@Z @ 12 NONAME ; QMediaResource::QMediaResource(class QNetworkRequest const &, class QString const &)
+ ?devicesChanged@QVideoDeviceControl@@IAEXXZ @ 13 NONAME ; void QVideoDeviceControl::devicesChanged(void)
+ ?supportedVideoCodecs@QMediaRecorder@@QBE?AVQStringList@@XZ @ 14 NONAME ; class QStringList QMediaRecorder::supportedVideoCodecs(void) const
+ ?searchForward@QRadioTuner@@QAEXXZ @ 15 NONAME ; void QRadioTuner::searchForward(void)
+ ?saturation@QVideoWidget@@QBEHXZ @ 16 NONAME ; int QVideoWidget::saturation(void) const
+ ?mediaInserted@QMediaPlaylistProvider@@IAEXHH@Z @ 17 NONAME ; void QMediaPlaylistProvider::mediaInserted(int, int)
+ ?insertMedia@QMediaPlaylist@@QAE_NHABVQMediaContent@@@Z @ 18 NONAME ; bool QMediaPlaylist::insertMedia(int, class QMediaContent const &)
+ ?availableMetaData@QMediaRecorder@@QBE?AV?$QList@W4MetaData@QtMultimediaKit@@@@XZ @ 19 NONAME ; class QList<enum QtMultimediaKit::MetaData> QMediaRecorder::availableMetaData(void) const
+ ?staticMetaObject@QGraphicsVideoItem@@2UQMetaObject@@B @ 20 NONAME ; struct QMetaObject const QGraphicsVideoItem::staticMetaObject
+ ?qt_metacall@QAbstractAudioDeviceInfo@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 21 NONAME ; int QAbstractAudioDeviceInfo::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??_EQMediaServiceSupportedFormatsInterface@@UAE@I@Z @ 22 NONAME ; QMediaServiceSupportedFormatsInterface::~QMediaServiceSupportedFormatsInterface(unsigned int)
+ ??0QAbstractVideoBuffer@@IAE@AAVQAbstractVideoBufferPrivate@@W4HandleType@0@@Z @ 23 NONAME ; QAbstractVideoBuffer::QAbstractVideoBuffer(class QAbstractVideoBufferPrivate &, enum QAbstractVideoBuffer::HandleType)
+ ?staticMetaObject@QVideoDeviceControl@@2UQMetaObject@@B @ 24 NONAME ; struct QMetaObject const QVideoDeviceControl::staticMetaObject
+ ?tr@QImageEncoderControl@@SA?AVQString@@PBD0H@Z @ 25 NONAME ; class QString QImageEncoderControl::tr(char const *, char const *, int)
+ ??1QAbstractVideoBuffer@@UAE@XZ @ 26 NONAME ; QAbstractVideoBuffer::~QAbstractVideoBuffer(void)
+ ?stop@QAudioOutput@@QAEXXZ @ 27 NONAME ; void QAudioOutput::stop(void)
+ ?stateChanged@QMediaRecorder@@IAEXW4State@1@@Z @ 28 NONAME ; void QMediaRecorder::stateChanged(enum QMediaRecorder::State)
+ ?isEmpty@QMediaPlaylist@@QBE_NXZ @ 29 NONAME ; bool QMediaPlaylist::isEmpty(void) const
+ ?insertMedia@QMediaPlaylist@@QAE_NHABV?$QList@VQMediaContent@@@@@Z @ 30 NONAME ; bool QMediaPlaylist::insertMedia(int, class QList<class QMediaContent> const &)
+ ?bytesFree@QAudioOutput@@QBEHXZ @ 31 NONAME ; int QAudioOutput::bytesFree(void) const
+ ??1QMediaTimeRange@@QAE@XZ @ 32 NONAME ; QMediaTimeRange::~QMediaTimeRange(void)
+ ?trUtf8@QAbstractAudioOutput@@SA?AVQString@@PBD0H@Z @ 33 NONAME ; class QString QAbstractAudioOutput::trUtf8(char const *, char const *, int)
+ ?playlistChanged@QMediaPlaylistSourceControl@@IAEXPAVQMediaPlaylist@@@Z @ 34 NONAME ; void QMediaPlaylistSourceControl::playlistChanged(class QMediaPlaylist *)
+ ?staticMetaObject@QSoundEffect@@2UQMetaObject@@B @ 35 NONAME ; struct QMetaObject const QSoundEffect::staticMetaObject
+ ?error@QMediaPlayerControl@@IAEXHABVQString@@@Z @ 36 NONAME ; void QMediaPlayerControl::error(int, class QString const &)
+ ?d_func@QMediaPlaylist@@ABEPBVQMediaPlaylistPrivate@@XZ @ 37 NONAME ; class QMediaPlaylistPrivate const * QMediaPlaylist::d_func(void) const
+ ?metaObject@QRadioTuner@@UBEPBUQMetaObject@@XZ @ 38 NONAME ; struct QMetaObject const * QRadioTuner::metaObject(void) const
+ ?bits@QVideoFrame@@QBEPBEXZ @ 39 NONAME ; unsigned char const * QVideoFrame::bits(void) const
+ ?staticMetaObject@QVideoWidget@@2UQMetaObject@@B @ 40 NONAME ; struct QMetaObject const QVideoWidget::staticMetaObject
+ ??_EQMediaControl@@UAE@I@Z @ 41 NONAME ; QMediaControl::~QMediaControl(unsigned int)
+ ?media@QMediaPlaylist@@QBE?AVQMediaContent@@H@Z @ 42 NONAME ; class QMediaContent QMediaPlaylist::media(int) const
+ ?mapMode@QVideoFrame@@QBE?AW4MapMode@QAbstractVideoBuffer@@XZ @ 43 NONAME ; enum QAbstractVideoBuffer::MapMode QVideoFrame::mapMode(void) const
+ ??0QAudioCaptureSource@@QAE@PAVQObject@@PAVQMediaServiceProvider@@@Z @ 44 NONAME ; QAudioCaptureSource::QAudioCaptureSource(class QObject *, class QMediaServiceProvider *)
+ ??1QMediaControl@@UAE@XZ @ 45 NONAME ; QMediaControl::~QMediaControl(void)
+ ?staticMetaObject@QMediaObject@@2UQMetaObject@@B @ 46 NONAME ; struct QMetaObject const QMediaObject::staticMetaObject
+ ?qt_metacast@QMediaPlaylistProvider@@UAEPAXPBD@Z @ 47 NONAME ; void * QMediaPlaylistProvider::qt_metacast(char const *)
+ ??0QMediaServiceProviderHint@@QAE@ABVQByteArray@@@Z @ 48 NONAME ; QMediaServiceProviderHint::QMediaServiceProviderHint(class QByteArray const &)
+ ?trUtf8@QAudioOutput@@SA?AVQString@@PBD0@Z @ 49 NONAME ; class QString QAudioOutput::trUtf8(char const *, char const *)
+ ?qt_metacast@QSoundEffect@@UAEPAXPBD@Z @ 50 NONAME ; void * QSoundEffect::qt_metacast(char const *)
+ ?searchingChanged@QRadioTunerControl@@IAEX_N@Z @ 51 NONAME ; void QRadioTunerControl::searchingChanged(bool)
+ ?tr@QMediaObject@@SA?AVQString@@PBD0@Z @ 52 NONAME ; class QString QMediaObject::tr(char const *, char const *)
+ ?trUtf8@QMediaPlaylistControl@@SA?AVQString@@PBD0H@Z @ 53 NONAME ; class QString QMediaPlaylistControl::trUtf8(char const *, char const *, int)
+ ?end@QMediaTimeInterval@@QBE_JXZ @ 54 NONAME ; long long QMediaTimeInterval::end(void) const
+ ??0QImageEncoderControl@@IAE@PAVQObject@@@Z @ 55 NONAME ; QImageEncoderControl::QImageEncoderControl(class QObject *)
+ ?format@QAudioOutput@@QBE?AVQAudioFormat@@XZ @ 56 NONAME ; class QAudioFormat QAudioOutput::format(void) const
+ ?d_func@QGraphicsVideoItem@@AAEPAVQGraphicsVideoItemPrivate@@XZ @ 57 NONAME ; class QGraphicsVideoItemPrivate * QGraphicsVideoItem::d_func(void)
+ ?d_func@QRadioTuner@@AAEPAVQRadioTunerPrivate@@XZ @ 58 NONAME ; class QRadioTunerPrivate * QRadioTuner::d_func(void)
+ ?trUtf8@QMediaPlaylistProvider@@SA?AVQString@@PBD0H@Z @ 59 NONAME ; class QString QMediaPlaylistProvider::trUtf8(char const *, char const *, int)
+ ?staticMetaObject@QMediaPlaylistIOPlugin@@2UQMetaObject@@B @ 60 NONAME ; struct QMetaObject const QMediaPlaylistIOPlugin::staticMetaObject
+ ?isStereo@QRadioTuner@@QBE_NXZ @ 61 NONAME ; bool QRadioTuner::isStereo(void) const
+ ?tr@QAudioEndpointSelector@@SA?AVQString@@PBD0H@Z @ 62 NONAME ; class QString QAudioEndpointSelector::tr(char const *, char const *, int)
+ ?tr@QMediaImageViewer@@SA?AVQString@@PBD0@Z @ 63 NONAME ; class QString QMediaImageViewer::tr(char const *, char const *)
+ ??_EQMediaServiceProvider@@UAE@I@Z @ 64 NONAME ; QMediaServiceProvider::~QMediaServiceProvider(unsigned int)
+ ?setStereoMode@QRadioTuner@@QAEXW4StereoMode@1@@Z @ 65 NONAME ; void QRadioTuner::setStereoMode(enum QRadioTuner::StereoMode)
+ ?qt_metacall@QMediaServiceProvider@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 66 NONAME ; int QMediaServiceProvider::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?trUtf8@QMediaObject@@SA?AVQString@@PBD0H@Z @ 67 NONAME ; class QString QMediaObject::trUtf8(char const *, char const *, int)
+ ?supportedSampleTypes@QAudioDeviceInfo@@QBE?AV?$QList@W4SampleType@QAudioFormat@@@@XZ @ 68 NONAME ; class QList<enum QAudioFormat::SampleType> QAudioDeviceInfo::supportedSampleTypes(void) const
+ ?metaObject@QVideoEncoderControl@@UBEPBUQMetaObject@@XZ @ 69 NONAME ; struct QMetaObject const * QVideoEncoderControl::metaObject(void) const
+ ??_EQVideoEncoderControl@@UAE@I@Z @ 70 NONAME ; QVideoEncoderControl::~QVideoEncoderControl(unsigned int)
+ ?getStaticMetaObject@QGraphicsVideoItem@@SAABUQMetaObject@@XZ @ 71 NONAME ; struct QMetaObject const & QGraphicsVideoItem::getStaticMetaObject(void)
+ ?isWritable@QVideoFrame@@QBE_NXZ @ 72 NONAME ; bool QVideoFrame::isWritable(void) const
+ ??0QAudioOutput@@QAE@ABVQAudioFormat@@PAVQObject@@@Z @ 73 NONAME ; QAudioOutput::QAudioOutput(class QAudioFormat const &, class QObject *)
+ ??1QAudioEncoderSettings@@QAE@XZ @ 74 NONAME ; QAudioEncoderSettings::~QAudioEncoderSettings(void)
+ ?metaDataChanged@QMediaRecorder@@IAEXXZ @ 75 NONAME ; void QMediaRecorder::metaDataChanged(void)
+ ??1QMediaBindableInterface@@UAE@XZ @ 76 NONAME ; QMediaBindableInterface::~QMediaBindableInterface(void)
+ ??1QRadioTunerControl@@UAE@XZ @ 77 NONAME ; QRadioTunerControl::~QRadioTunerControl(void)
+ ?staticMetaObject@QAbstractAudioInput@@2UQMetaObject@@B @ 78 NONAME ; struct QMetaObject const QAbstractAudioInput::staticMetaObject
+ ?tr@QAbstractAudioInput@@SA?AVQString@@PBD0@Z @ 79 NONAME ; class QString QAbstractAudioInput::tr(char const *, char const *)
+ ??1QMediaContainerControl@@UAE@XZ @ 80 NONAME ; QMediaContainerControl::~QMediaContainerControl(void)
+ ?channelCount@QAudioFormat@@QBEHXZ @ 81 NONAME ; int QAudioFormat::channelCount(void) const
+ ?previousIndex@QMediaPlaylistNavigator@@QBEHH@Z @ 82 NONAME ; int QMediaPlaylistNavigator::previousIndex(int) const
+ ?trUtf8@QGraphicsVideoItem@@SA?AVQString@@PBD0H@Z @ 83 NONAME ; class QString QGraphicsVideoItem::trUtf8(char const *, char const *, int)
+ ?positionChanged@QMediaPlayerControl@@IAEX_J@Z @ 84 NONAME ; void QMediaPlayerControl::positionChanged(long long)
+ ?metaObject@QMediaServiceProviderPlugin@@UBEPBUQMetaObject@@XZ @ 85 NONAME ; struct QMetaObject const * QMediaServiceProviderPlugin::metaObject(void) const
+ ?currentMediaChanged@QMediaPlaylist@@IAEXABVQMediaContent@@@Z @ 86 NONAME ; void QMediaPlaylist::currentMediaChanged(class QMediaContent const &)
+ ?searchBackward@QRadioTuner@@QAEXXZ @ 87 NONAME ; void QRadioTuner::searchBackward(void)
+ ?getStaticMetaObject@QMediaPlaylist@@SAABUQMetaObject@@XZ @ 88 NONAME ; struct QMetaObject const & QMediaPlaylist::getStaticMetaObject(void)
+ ?setPixelAspectRatio@QVideoSurfaceFormat@@QAEXABVQSize@@@Z @ 89 NONAME ; void QVideoSurfaceFormat::setPixelAspectRatio(class QSize const &)
+ ?qt_metacast@QMediaPlaylistControl@@UAEPAXPBD@Z @ 90 NONAME ; void * QMediaPlaylistControl::qt_metacast(char const *)
+ ?audioSettings@QMediaRecorder@@QBE?AVQAudioEncoderSettings@@XZ @ 91 NONAME ; class QAudioEncoderSettings QMediaRecorder::audioSettings(void) const
+ ?yCbCrColorSpace@QVideoSurfaceFormat@@QBE?AW4YCbCrColorSpace@1@XZ @ 92 NONAME ; enum QVideoSurfaceFormat::YCbCrColorSpace QVideoSurfaceFormat::yCbCrColorSpace(void) const
+ ?qt_metacast@QVideoEncoderControl@@UAEPAXPBD@Z @ 93 NONAME ; void * QVideoEncoderControl::qt_metacast(char const *)
+ ?staticMetaObject@QAbstractAudioOutput@@2UQMetaObject@@B @ 94 NONAME ; struct QMetaObject const QAbstractAudioOutput::staticMetaObject
+ ??_EQAbstractAudioOutput@@UAE@I@Z @ 95 NONAME ; QAbstractAudioOutput::~QAbstractAudioOutput(unsigned int)
+ ?addMedia@QLocalMediaPlaylistProvider@@UAE_NABV?$QList@VQMediaContent@@@@@Z @ 96 NONAME ; bool QLocalMediaPlaylistProvider::addMedia(class QList<class QMediaContent> const &)
+ ?staticMetaObject@QLocalMediaPlaylistProvider@@2UQMetaObject@@B @ 97 NONAME ; struct QMetaObject const QLocalMediaPlaylistProvider::staticMetaObject
+ ?supportedSampleSizes@QAudioDeviceInfo@@QBE?AV?$QList@H@@XZ @ 98 NONAME ; class QList<int> QAudioDeviceInfo::supportedSampleSizes(void) const
+ ?addMedia@QMediaPlaylist@@QAE_NABV?$QList@VQMediaContent@@@@@Z @ 99 NONAME ; bool QMediaPlaylist::addMedia(class QList<class QMediaContent> const &)
+ ?hueChanged@QVideoWidget@@IAEXH@Z @ 100 NONAME ; void QVideoWidget::hueChanged(int)
+ ??4QVideoEncoderSettings@@QAEAAV0@ABV0@@Z @ 101 NONAME ; class QVideoEncoderSettings & QVideoEncoderSettings::operator=(class QVideoEncoderSettings const &)
+ ?qt_metacast@QVideoWidget@@UAEPAXPBD@Z @ 102 NONAME ; void * QVideoWidget::qt_metacast(char const *)
+ ?activeAudioInput@QAudioCaptureSource@@QBE?AVQString@@XZ @ 103 NONAME ; class QString QAudioCaptureSource::activeAudioInput(void) const
+ ??0QVideoSurfaceFormat@@QAE@XZ @ 104 NONAME ; QVideoSurfaceFormat::QVideoSurfaceFormat(void)
+ ?supportedChannelCounts@QAudioDeviceInfo@@QBE?AV?$QList@H@@XZ @ 105 NONAME ; class QList<int> QAudioDeviceInfo::supportedChannelCounts(void) const
+ ?getStaticMetaObject@QMediaPlaylistControl@@SAABUQMetaObject@@XZ @ 106 NONAME ; struct QMetaObject const & QMediaPlaylistControl::getStaticMetaObject(void)
+ ?setMuted@QMediaRecorder@@QAEX_N@Z @ 107 NONAME ; void QMediaRecorder::setMuted(bool)
+ ?qt_metacall@QMetaDataReaderControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 108 NONAME ; int QMetaDataReaderControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??H@YA?AVQMediaTimeRange@@ABV0@0@Z @ 109 NONAME ; class QMediaTimeRange operator+(class QMediaTimeRange const &, class QMediaTimeRange const &)
+ ?record@QMediaRecorder@@QAEXXZ @ 110 NONAME ; void QMediaRecorder::record(void)
+ ?metaObject@QMediaService@@UBEPBUQMetaObject@@XZ @ 111 NONAME ; struct QMetaObject const * QMediaService::metaObject(void) const
+ ?isMuted@QRadioTuner@@QBE_NXZ @ 112 NONAME ; bool QRadioTuner::isMuted(void) const
+ ?availabilityChanged@QMediaObject@@IAEX_N@Z @ 113 NONAME ; void QMediaObject::availabilityChanged(bool)
+ ?trUtf8@QVideoEncoderControl@@SA?AVQString@@PBD0@Z @ 114 NONAME ; class QString QVideoEncoderControl::trUtf8(char const *, char const *)
+ ?trUtf8@QMetaDataReaderControl@@SA?AVQString@@PBD0@Z @ 115 NONAME ; class QString QMetaDataReaderControl::trUtf8(char const *, char const *)
+ ?setLanguage@QMediaResource@@QAEXABVQString@@@Z @ 116 NONAME ; void QMediaResource::setLanguage(class QString const &)
+ ??0QMediaResource@@QAE@ABVQUrl@@ABVQString@@@Z @ 117 NONAME ; QMediaResource::QMediaResource(class QUrl const &, class QString const &)
+ ?volume@QSoundEffect@@QBEMXZ @ 118 NONAME ; float QSoundEffect::volume(void) const
+ ?mutedChanged@QRadioTuner@@IAEX_N@Z @ 119 NONAME ; void QRadioTuner::mutedChanged(bool)
+ ?currentIndex@QMediaPlaylist@@QBEHXZ @ 120 NONAME ; int QMediaPlaylist::currentIndex(void) const
+ ?setNotifyInterval@QAudioInput@@QAEXH@Z @ 121 NONAME ; void QAudioInput::setNotifyInterval(int)
+ ?aspectRatioMode@QGraphicsVideoItem@@QBE?AW4AspectRatioMode@Qt@@XZ @ 122 NONAME ; enum Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode(void) const
+ ??0QMediaTimeRange@@QAE@ABVQMediaTimeInterval@@@Z @ 123 NONAME ; QMediaTimeRange::QMediaTimeRange(class QMediaTimeInterval const &)
+ ?qt_metacall@QMediaPlaylistProvider@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 124 NONAME ; int QMediaPlaylistProvider::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??_EQVideoWidgetControl@@UAE@I@Z @ 125 NONAME ; QVideoWidgetControl::~QVideoWidgetControl(unsigned int)
+ ?trUtf8@QVideoDeviceControl@@SA?AVQString@@PBD0H@Z @ 126 NONAME ; class QString QVideoDeviceControl::trUtf8(char const *, char const *, int)
+ ?seekableChanged@QMediaPlayer@@IAEX_N@Z @ 127 NONAME ; void QMediaPlayer::seekableChanged(bool)
+ ?unbind@QMediaPlayer@@UAEXPAVQObject@@@Z @ 128 NONAME ; void QMediaPlayer::unbind(class QObject *)
+ ?tr@QMediaPlaylistControl@@SA?AVQString@@PBD0@Z @ 129 NONAME ; class QString QMediaPlaylistControl::tr(char const *, char const *)
+ ?setVolume@QMediaPlayer@@QAEXH@Z @ 130 NONAME ; void QMediaPlayer::setVolume(int)
+ ?setPlaylist@QMediaPlaylistNavigator@@QAEXPAVQMediaPlaylistProvider@@@Z @ 131 NONAME ; void QMediaPlaylistNavigator::setPlaylist(class QMediaPlaylistProvider *)
+ ?setMuted@QSoundEffect@@QAEX_N@Z @ 132 NONAME ; void QSoundEffect::setMuted(bool)
+ ?trUtf8@QAudioEncoderControl@@SA?AVQString@@PBD0@Z @ 133 NONAME ; class QString QAudioEncoderControl::trUtf8(char const *, char const *)
+ ?sampleRate@QAudioFormat@@QBEHXZ @ 134 NONAME ; int QAudioFormat::sampleRate(void) const
+ ?staticMetaObject@QAudioOutput@@2UQMetaObject@@B @ 135 NONAME ; struct QMetaObject const QAudioOutput::staticMetaObject
+ ?setQuality@QAudioEncoderSettings@@QAEXW4EncodingQuality@QtMultimediaKit@@@Z @ 136 NONAME ; void QAudioEncoderSettings::setQuality(enum QtMultimediaKit::EncodingQuality)
+ ?getStaticMetaObject@QMediaObject@@SAABUQMetaObject@@XZ @ 137 NONAME ; struct QMetaObject const & QMediaObject::getStaticMetaObject(void)
+ ??1QMediaServiceProviderHint@@QAE@XZ @ 138 NONAME ; QMediaServiceProviderHint::~QMediaServiceProviderHint(void)
+ ?mediaCount@QMediaPlaylist@@QBEHXZ @ 139 NONAME ; int QMediaPlaylist::mediaCount(void) const
+ ?load@QMediaPlaylist@@QAEXABVQUrl@@PBD@Z @ 140 NONAME ; void QMediaPlaylist::load(class QUrl const &, char const *)
+ ?earliestTime@QMediaTimeRange@@QBE_JXZ @ 141 NONAME ; long long QMediaTimeRange::earliestTime(void) const
+ ?frameSize@QVideoSurfaceFormat@@QBE?AVQSize@@XZ @ 142 NONAME ; class QSize QVideoSurfaceFormat::frameSize(void) const
+ ?tr@QMediaContainerControl@@SA?AVQString@@PBD0H@Z @ 143 NONAME ; class QString QMediaContainerControl::tr(char const *, char const *, int)
+ ?bits@QVideoFrame@@QAEPAEXZ @ 144 NONAME ; unsigned char * QVideoFrame::bits(void)
+ ?setSource@QSoundEffect@@QAEXABVQUrl@@@Z @ 145 NONAME ; void QSoundEffect::setSource(class QUrl const &)
+ ?setExtendedMetaData@QMediaRecorder@@QAEXABVQString@@ABVQVariant@@@Z @ 146 NONAME ; void QMediaRecorder::setExtendedMetaData(class QString const &, class QVariant const &)
+ ??0QMediaPlaylistSourceControl@@IAE@PAVQObject@@@Z @ 147 NONAME ; QMediaPlaylistSourceControl::QMediaPlaylistSourceControl(class QObject *)
+ ?qt_metacast@QMetaDataReaderControl@@UAEPAXPBD@Z @ 148 NONAME ; void * QMetaDataReaderControl::qt_metacast(char const *)
+ ?tr@QVideoWidget@@SA?AVQString@@PBD0@Z @ 149 NONAME ; class QString QVideoWidget::tr(char const *, char const *)
+ ?getStaticMetaObject@QMediaPlaylistNavigator@@SAABUQMetaObject@@XZ @ 150 NONAME ; struct QMetaObject const & QMediaPlaylistNavigator::getStaticMetaObject(void)
+ ??0QMediaControl@@IAE@AAVQMediaControlPrivate@@PAVQObject@@@Z @ 151 NONAME ; QMediaControl::QMediaControl(class QMediaControlPrivate &, class QObject *)
+ ?videoAvailableChanged@QMediaPlayerControl@@IAEX_N@Z @ 152 NONAME ; void QMediaPlayerControl::videoAvailableChanged(bool)
+ ?tr@QLocalMediaPlaylistProvider@@SA?AVQString@@PBD0@Z @ 153 NONAME ; class QString QLocalMediaPlaylistProvider::tr(char const *, char const *)
+ ?supportedResolutions@QMediaRecorder@@QBE?AV?$QList@VQSize@@@@ABVQVideoEncoderSettings@@PA_N@Z @ 154 NONAME ; class QList<class QSize> QMediaRecorder::supportedResolutions(class QVideoEncoderSettings const &, bool *) const
+ ?removeMedia@QLocalMediaPlaylistProvider@@UAE_NH@Z @ 155 NONAME ; bool QLocalMediaPlaylistProvider::removeMedia(int)
+ ?qt_metacast@QMediaImageViewer@@UAEPAXPBD@Z @ 156 NONAME ; void * QMediaImageViewer::qt_metacast(char const *)
+ ?contrast@QVideoWidget@@QBEHXZ @ 157 NONAME ; int QVideoWidget::contrast(void) const
+ ??_EQMetaDataWriterControl@@UAE@I@Z @ 158 NONAME ; QMetaDataWriterControl::~QMetaDataWriterControl(unsigned int)
+ ?previous@QMediaPlaylistNavigator@@QAEXXZ @ 159 NONAME ; void QMediaPlaylistNavigator::previous(void)
+ ?qt_metacall@QAudioSystemPlugin@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 160 NONAME ; int QAudioSystemPlugin::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?start@QAudioInput@@QAEXPAVQIODevice@@@Z @ 161 NONAME ; void QAudioInput::start(class QIODevice *)
+ ?isValid@QVideoFrame@@QBE_NXZ @ 162 NONAME ; bool QVideoFrame::isValid(void) const
+ ?fullScreenChanged@QVideoWidget@@IAEX_N@Z @ 163 NONAME ; void QVideoWidget::fullScreenChanged(bool)
+ ?setSaturation@QVideoWidget@@QAEXH@Z @ 164 NONAME ; void QVideoWidget::setSaturation(int)
+ ?bandChanged@QRadioTuner@@IAEXW4Band@1@@Z @ 165 NONAME ; void QRadioTuner::bandChanged(enum QRadioTuner::Band)
+ ?d_func@QMediaPlayer@@ABEPBVQMediaPlayerPrivate@@XZ @ 166 NONAME ; class QMediaPlayerPrivate const * QMediaPlayer::d_func(void) const
+ ?notify@QAudioInput@@IAEXXZ @ 167 NONAME ; void QAudioInput::notify(void)
+ ?loadFailed@QMediaPlaylistProvider@@IAEXW4Error@QMediaPlaylist@@ABVQString@@@Z @ 168 NONAME ; void QMediaPlaylistProvider::loadFailed(enum QMediaPlaylist::Error, class QString const &)
+ ??_EQMediaPlayer@@UAE@I@Z @ 169 NONAME ; QMediaPlayer::~QMediaPlayer(unsigned int)
+ ?tr@QSoundEffect@@SA?AVQString@@PBD0@Z @ 170 NONAME ; class QString QSoundEffect::tr(char const *, char const *)
+ ?mimeType@QMediaResource@@QBE?AVQString@@XZ @ 171 NONAME ; class QString QMediaResource::mimeType(void) const
+ ??0QAudioEncoderSettings@@QAE@ABV0@@Z @ 172 NONAME ; QAudioEncoderSettings::QAudioEncoderSettings(class QAudioEncoderSettings const &)
+ ?videoAvailableChanged@QMediaPlayer@@IAEX_N@Z @ 173 NONAME ; void QMediaPlayer::videoAvailableChanged(bool)
+ ?stateChanged@QMediaRecorderControl@@IAEXW4State@QMediaRecorder@@@Z @ 174 NONAME ; void QMediaRecorderControl::stateChanged(enum QMediaRecorder::State)
+ ?pixelFormat@QVideoSurfaceFormat@@QBE?AW4PixelFormat@QVideoFrame@@XZ @ 175 NONAME ; enum QVideoFrame::PixelFormat QVideoSurfaceFormat::pixelFormat(void) const
+ ?map@QMemoryVideoBuffer@@UAEPAEW4MapMode@QAbstractVideoBuffer@@PAH1@Z @ 176 NONAME ; unsigned char * QMemoryVideoBuffer::map(enum QAbstractVideoBuffer::MapMode, int *, int *)
+ ?sampleRate@QMediaResource@@QBEHXZ @ 177 NONAME ; int QMediaResource::sampleRate(void) const
+ ??0QRadioTunerControl@@IAE@PAVQObject@@@Z @ 178 NONAME ; QRadioTunerControl::QRadioTunerControl(class QObject *)
+ ?staticMetaObject@QMediaPlaylist@@2UQMetaObject@@B @ 179 NONAME ; struct QMetaObject const QMediaPlaylist::staticMetaObject
+ ?state@QAudioInput@@QBE?AW4State@QAudio@@XZ @ 180 NONAME ; enum QAudio::State QAudioInput::state(void) const
+ ??0QMediaContent@@QAE@ABV?$QList@VQMediaResource@@@@@Z @ 181 NONAME ; QMediaContent::QMediaContent(class QList<class QMediaResource> const &)
+ ?qt_metacast@QMediaServiceProviderPlugin@@UAEPAXPBD@Z @ 182 NONAME ; void * QMediaServiceProviderPlugin::qt_metacast(char const *)
+ ??0QVideoSurfaceFormat@@QAE@ABV0@@Z @ 183 NONAME ; QVideoSurfaceFormat::QVideoSurfaceFormat(class QVideoSurfaceFormat const &)
+ ?deviceDescription@QMediaServiceProvider@@UAE?AVQString@@ABVQByteArray@@0@Z @ 184 NONAME ; class QString QMediaServiceProvider::deviceDescription(class QByteArray const &, class QByteArray const &)
+ ??9@YA_NABVQMediaTimeInterval@@0@Z @ 185 NONAME ; bool operator!=(class QMediaTimeInterval const &, class QMediaTimeInterval const &)
+ ??_EQVideoRendererControl@@UAE@I@Z @ 186 NONAME ; QVideoRendererControl::~QVideoRendererControl(unsigned int)
+ ?setAudioBitRate@QMediaResource@@QAEXH@Z @ 187 NONAME ; void QMediaResource::setAudioBitRate(int)
+ ?setFullScreen@QVideoWidget@@QAEX_N@Z @ 188 NONAME ; void QVideoWidget::setFullScreen(bool)
+ ?metaObject@QGraphicsVideoItem@@UBEPBUQMetaObject@@XZ @ 189 NONAME ; struct QMetaObject const * QGraphicsVideoItem::metaObject(void) const
+ ??0QVideoWidget@@QAE@PAVQWidget@@@Z @ 190 NONAME ; QVideoWidget::QVideoWidget(class QWidget *)
+ ?metaObject@QAbstractAudioOutput@@UBEPBUQMetaObject@@XZ @ 191 NONAME ; struct QMetaObject const * QAbstractAudioOutput::metaObject(void) const
+ ??_EQMediaPlayerControl@@UAE@I@Z @ 192 NONAME ; QMediaPlayerControl::~QMediaPlayerControl(unsigned int)
+ ?setLoops@QSoundEffect@@QAEXH@Z @ 193 NONAME ABSENT ; void QSoundEffect::setLoops(int)
+ ?viewport@QVideoSurfaceFormat@@QBE?AVQRect@@XZ @ 194 NONAME ; class QRect QVideoSurfaceFormat::viewport(void) const
+ ?d_func@QMediaService@@AAEPAVQMediaServicePrivate@@XZ @ 195 NONAME ; class QMediaServicePrivate * QMediaService::d_func(void)
+ ?resume@QAudioInput@@QAEXXZ @ 196 NONAME ; void QAudioInput::resume(void)
+ ?audioCodecDescription@QMediaRecorder@@QBE?AVQString@@ABV2@@Z @ 197 NONAME ; class QString QMediaRecorder::audioCodecDescription(class QString const &) const
+ ?setAspectRatioMode@QGraphicsVideoItem@@QAEXW4AspectRatioMode@Qt@@@Z @ 198 NONAME ; void QGraphicsVideoItem::setAspectRatioMode(enum Qt::AspectRatioMode)
+ ?encodingMode@QAudioEncoderSettings@@QBE?AW4EncodingMode@QtMultimediaKit@@XZ @ 199 NONAME ; enum QtMultimediaKit::EncodingMode QAudioEncoderSettings::encodingMode(void) const
+ ?isVideoAvailable@QMediaPlayer@@QBE_NXZ @ 200 NONAME ; bool QMediaPlayer::isVideoAvailable(void) const
+ ?playbackMode@QMediaPlaylist@@QBE?AW4PlaybackMode@1@XZ @ 201 NONAME ; enum QMediaPlaylist::PlaybackMode QMediaPlaylist::playbackMode(void) const
+ ?metaDataChanged@QMediaObject@@IAEXXZ @ 202 NONAME ; void QMediaObject::metaDataChanged(void)
+ ??0QVideoSurfaceFormat@@QAE@ABVQSize@@W4PixelFormat@QVideoFrame@@W4HandleType@QAbstractVideoBuffer@@@Z @ 203 NONAME ; QVideoSurfaceFormat::QVideoSurfaceFormat(class QSize const &, enum QVideoFrame::PixelFormat, enum QAbstractVideoBuffer::HandleType)
+ ?trUtf8@QAudioCaptureSource@@SA?AVQString@@PBD0@Z @ 204 NONAME ; class QString QAudioCaptureSource::trUtf8(char const *, char const *)
+ ?frameHeight@QVideoSurfaceFormat@@QBEHXZ @ 205 NONAME ; int QVideoSurfaceFormat::frameHeight(void) const
+ ?unmap@QImageVideoBuffer@@UAEXXZ @ 206 NONAME ; void QImageVideoBuffer::unmap(void)
+ ?translated@QMediaTimeInterval@@QBE?AV1@_J@Z @ 207 NONAME ; class QMediaTimeInterval QMediaTimeInterval::translated(long long) const
+ ?trUtf8@QGraphicsVideoItem@@SA?AVQString@@PBD0@Z @ 208 NONAME ; class QString QGraphicsVideoItem::trUtf8(char const *, char const *)
+ ??1QAbstractAudioInput@@UAE@XZ @ 209 NONAME ; QAbstractAudioInput::~QAbstractAudioInput(void)
+ ?supportedAudioSampleRates@QMediaRecorder@@QBE?AV?$QList@H@@ABVQAudioEncoderSettings@@PA_N@Z @ 210 NONAME ; class QList<int> QMediaRecorder::supportedAudioSampleRates(class QAudioEncoderSettings const &, bool *) const
+ ?save@QMediaPlaylist@@QAE_NPAVQIODevice@@PBD@Z @ 211 NONAME ; bool QMediaPlaylist::save(class QIODevice *, char const *)
+ ?setFrameSize@QVideoSurfaceFormat@@QAEXABVQSize@@@Z @ 212 NONAME ; void QVideoSurfaceFormat::setFrameSize(class QSize const &)
+ ?setPlaylist@QMediaPlayer@@QAEXPAVQMediaPlaylist@@@Z @ 213 NONAME ; void QMediaPlayer::setPlaylist(class QMediaPlaylist *)
+ ?setMediaObject@QMediaRecorder@@MAE_NPAVQMediaObject@@@Z @ 214 NONAME ; bool QMediaRecorder::setMediaObject(class QMediaObject *)
+ ?metaObject@QMetaDataReaderControl@@UBEPBUQMetaObject@@XZ @ 215 NONAME ; struct QMetaObject const * QMetaDataReaderControl::metaObject(void) const
+ ?itemAt@QMediaPlaylistNavigator@@QBE?AVQMediaContent@@H@Z @ 216 NONAME ; class QMediaContent QMediaPlaylistNavigator::itemAt(int) const
+ ?start@QAudioOutput@@QAEPAVQIODevice@@XZ @ 217 NONAME ; class QIODevice * QAudioOutput::start(void)
+ ?mediaStatus@QMediaPlayer@@QBE?AW4MediaStatus@1@XZ @ 218 NONAME ; enum QMediaPlayer::MediaStatus QMediaPlayer::mediaStatus(void) const
+ ?bitRate@QVideoEncoderSettings@@QBEHXZ @ 219 NONAME ; int QVideoEncoderSettings::bitRate(void) const
+ ?d_func@QMediaControl@@ABEPBVQMediaControlPrivate@@XZ @ 220 NONAME ; class QMediaControlPrivate const * QMediaControl::d_func(void) const
+ ?staticMetaObject@QAbstractAudioDeviceInfo@@2UQMetaObject@@B @ 221 NONAME ; struct QMetaObject const QAbstractAudioDeviceInfo::staticMetaObject
+ ??1QAudioInput@@UAE@XZ @ 222 NONAME ; QAudioInput::~QAudioInput(void)
+ ?setEndTime@QVideoFrame@@QAEX_J@Z @ 223 NONAME ; void QVideoFrame::setEndTime(long long)
+ ?tr@QMediaPlaylistIOPlugin@@SA?AVQString@@PBD0H@Z @ 224 NONAME ; class QString QMediaPlaylistIOPlugin::tr(char const *, char const *, int)
+ ?extendedMetaData@QMediaObject@@QBE?AVQVariant@@ABVQString@@@Z @ 225 NONAME ; class QVariant QMediaObject::extendedMetaData(class QString const &) const
+ ?duration@QMediaPlayer@@QBE_JXZ @ 226 NONAME ; long long QMediaPlayer::duration(void) const
+ ?audioAvailableChanged@QMediaPlayer@@IAEX_N@Z @ 227 NONAME ; void QMediaPlayer::audioAvailableChanged(bool)
+ ?mutedChanged@QMediaPlayerControl@@IAEX_N@Z @ 228 NONAME ; void QMediaPlayerControl::mutedChanged(bool)
+ ?getStaticMetaObject@QMediaServiceProviderPlugin@@SAABUQMetaObject@@XZ @ 229 NONAME ; struct QMetaObject const & QMediaServiceProviderPlugin::getStaticMetaObject(void)
+ ??9QAudioEncoderSettings@@QBE_NABV0@@Z @ 230 NONAME ; bool QAudioEncoderSettings::operator!=(class QAudioEncoderSettings const &) const
+ ?bufferSize@QAudioOutput@@QBEHXZ @ 231 NONAME ; int QAudioOutput::bufferSize(void) const
+ ?getStaticMetaObject@QVideoWidget@@SAABUQMetaObject@@XZ @ 232 NONAME ; struct QMetaObject const & QVideoWidget::getStaticMetaObject(void)
+ ??1QMediaPlaylistSourceControl@@UAE@XZ @ 233 NONAME ; QMediaPlaylistSourceControl::~QMediaPlaylistSourceControl(void)
+ ?tr@QVideoWindowControl@@SA?AVQString@@PBD0@Z @ 234 NONAME ; class QString QVideoWindowControl::tr(char const *, char const *)
+ ??1QMediaContent@@QAE@XZ @ 235 NONAME ; QMediaContent::~QMediaContent(void)
+ ??0QRadioTuner@@QAE@PAVQObject@@PAVQMediaServiceProvider@@@Z @ 236 NONAME ; QRadioTuner::QRadioTuner(class QObject *, class QMediaServiceProvider *)
+ ?tr@QAbstractVideoSurface@@SA?AVQString@@PBD0H@Z @ 237 NONAME ; class QString QAbstractVideoSurface::tr(char const *, char const *, int)
+ ?qt_metacall@QVideoWidget@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 238 NONAME ; int QVideoWidget::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?setSampleRate@QAudioEncoderSettings@@QAEXH@Z @ 239 NONAME ; void QAudioEncoderSettings::setSampleRate(int)
+ ?setFrameRate@QVideoSurfaceFormat@@QAEXM@Z @ 240 NONAME ; void QVideoSurfaceFormat::setFrameRate(float)
+ ?qt_metacall@QMediaServiceProviderPlugin@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 241 NONAME ; int QMediaServiceProviderPlugin::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?tr@QVideoRendererControl@@SA?AVQString@@PBD0H@Z @ 242 NONAME ; class QString QVideoRendererControl::tr(char const *, char const *, int)
+ ?type@QMediaServiceProviderHint@@QBE?AW4Type@1@XZ @ 243 NONAME ; enum QMediaServiceProviderHint::Type QMediaServiceProviderHint::type(void) const
+ ?staticMetaObject@QVideoWidgetControl@@2UQMetaObject@@B @ 244 NONAME ; struct QMetaObject const QVideoWidgetControl::staticMetaObject
+ ?isNormal@QMediaTimeInterval@@QBE_NXZ @ 245 NONAME ; bool QMediaTimeInterval::isNormal(void) const
+ ??_EQMediaService@@UAE@I@Z @ 246 NONAME ; QMediaService::~QMediaService(unsigned int)
+ ?setChannelCount@QAudioEncoderSettings@@QAEXH@Z @ 247 NONAME ; void QAudioEncoderSettings::setChannelCount(int)
+ ?qt_metacall@QRadioTunerControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 248 NONAME ; int QRadioTunerControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?sampleSize@QAudioFormat@@QBEHXZ @ 249 NONAME ; int QAudioFormat::sampleSize(void) const
+ ?height@QVideoFrame@@QBEHXZ @ 250 NONAME ; int QVideoFrame::height(void) const
+ ?activeAudioInputChanged@QAudioCaptureSource@@IAEXABVQString@@@Z @ 251 NONAME ; void QAudioCaptureSource::activeAudioInputChanged(class QString const &)
+ ?d_func@QMediaObject@@ABEPBVQMediaObjectPrivate@@XZ @ 252 NONAME ; class QMediaObjectPrivate const * QMediaObject::d_func(void) const
+ ??0QAudioFormat@@QAE@XZ @ 253 NONAME ; QAudioFormat::QAudioFormat(void)
+ ?startTime@QVideoFrame@@QBE_JXZ @ 254 NONAME ; long long QVideoFrame::startTime(void) const
+ ??_EQAudioSystemPlugin@@UAE@I@Z @ 255 NONAME ; QAudioSystemPlugin::~QAudioSystemPlugin(unsigned int)
+ ?errorString@QMediaPlaylist@@QBE?AVQString@@XZ @ 256 NONAME ; class QString QMediaPlaylist::errorString(void) const
+ ?trUtf8@QRadioTunerControl@@SA?AVQString@@PBD0H@Z @ 257 NONAME ; class QString QRadioTunerControl::trUtf8(char const *, char const *, int)
+ ?getStaticMetaObject@QSoundEffect@@SAABUQMetaObject@@XZ @ 258 NONAME ; struct QMetaObject const & QSoundEffect::getStaticMetaObject(void)
+ ?trUtf8@QAudioSystemPlugin@@SA?AVQString@@PBD0H@Z @ 259 NONAME ; class QString QAudioSystemPlugin::trUtf8(char const *, char const *, int)
+ ?trUtf8@QMediaPlayerControl@@SA?AVQString@@PBD0@Z @ 260 NONAME ; class QString QMediaPlayerControl::trUtf8(char const *, char const *)
+ ?bytesPerLine@QVideoFrame@@QBEHXZ @ 261 NONAME ; int QVideoFrame::bytesPerLine(void) const
+ ??1QMediaPlayer@@UAE@XZ @ 262 NONAME ; QMediaPlayer::~QMediaPlayer(void)
+ ?isBandSupported@QRadioTuner@@QBE_NW4Band@1@@Z @ 263 NONAME ; bool QRadioTuner::isBandSupported(enum QRadioTuner::Band) const
+ ?trUtf8@QMediaPlayer@@SA?AVQString@@PBD0H@Z @ 264 NONAME ; class QString QMediaPlayer::trUtf8(char const *, char const *, int)
+ ?supportedAudioCodecs@QMediaRecorder@@QBE?AVQStringList@@XZ @ 265 NONAME ; class QStringList QMediaRecorder::supportedAudioCodecs(void) const
+ ??0QMediaContainerControl@@IAE@PAVQObject@@@Z @ 266 NONAME ; QMediaContainerControl::QMediaContainerControl(class QObject *)
+ ??0QMediaContent@@QAE@ABVQUrl@@@Z @ 267 NONAME ; QMediaContent::QMediaContent(class QUrl const &)
+ ?mediaStatusChanged@QMediaPlayerControl@@IAEXW4MediaStatus@QMediaPlayer@@@Z @ 268 NONAME ; void QMediaPlayerControl::mediaStatusChanged(enum QMediaPlayer::MediaStatus)
+ ?trUtf8@QRadioTuner@@SA?AVQString@@PBD0H@Z @ 269 NONAME ; class QString QRadioTuner::trUtf8(char const *, char const *, int)
+ ?trUtf8@QMediaPlaylist@@SA?AVQString@@PBD0H@Z @ 270 NONAME ; class QString QMediaPlaylist::trUtf8(char const *, char const *, int)
+ ??_EQMediaPlaylistReader@@UAE@I@Z @ 271 NONAME ; QMediaPlaylistReader::~QMediaPlaylistReader(unsigned int)
+ ?channelCount@QMediaResource@@QBEHXZ @ 272 NONAME ; int QMediaResource::channelCount(void) const
+ ?tr@QSoundEffect@@SA?AVQString@@PBD0H@Z @ 273 NONAME ; class QString QSoundEffect::tr(char const *, char const *, int)
+ ?qt_metacall@QMediaRecorderControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 274 NONAME ; int QMediaRecorderControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?setHue@QVideoWidget@@QAEXH@Z @ 275 NONAME ; void QVideoWidget::setHue(int)
+ ?tr@QGraphicsVideoItem@@SA?AVQString@@PBD0@Z @ 276 NONAME ; class QString QGraphicsVideoItem::tr(char const *, char const *)
+ ?activeChanged@QAbstractVideoSurface@@IAEX_N@Z @ 277 NONAME ; void QAbstractVideoSurface::activeChanged(bool)
+ ?imageFormatFromPixelFormat@QVideoFrame@@SA?AW4Format@QImage@@W4PixelFormat@1@@Z @ 278 NONAME ; enum QImage::Format QVideoFrame::imageFormatFromPixelFormat(enum QVideoFrame::PixelFormat)
+ ?contrastChanged@QVideoWindowControl@@IAEXH@Z @ 279 NONAME ; void QVideoWindowControl::contrastChanged(int)
+ ?stateChanged@QAudioOutput@@IAEXW4State@QAudio@@@Z @ 280 NONAME ; void QAudioOutput::stateChanged(enum QAudio::State)
+ ?addMedia@QMediaPlaylistProvider@@UAE_NABV?$QList@VQMediaContent@@@@@Z @ 281 NONAME ; bool QMediaPlaylistProvider::addMedia(class QList<class QMediaContent> const &)
+ ?error@QMediaRecorderControl@@IAEXHABVQString@@@Z @ 282 NONAME ; void QMediaRecorderControl::error(int, class QString const &)
+ ??0QMediaTimeInterval@@QAE@_J0@Z @ 283 NONAME ; QMediaTimeInterval::QMediaTimeInterval(long long, long long)
+ ??0QMediaPlaylistNavigator@@QAE@PAVQMediaPlaylistProvider@@PAVQObject@@@Z @ 284 NONAME ; QMediaPlaylistNavigator::QMediaPlaylistNavigator(class QMediaPlaylistProvider *, class QObject *)
+ ?latestTime@QMediaTimeRange@@QBE_JXZ @ 285 NONAME ; long long QMediaTimeRange::latestTime(void) const
+ ??_EQAbstractVideoBuffer@@UAE@I@Z @ 286 NONAME ; QAbstractVideoBuffer::~QAbstractVideoBuffer(unsigned int)
+ ??_EQAudioCaptureSource@@UAE@I@Z @ 287 NONAME ; QAudioCaptureSource::~QAudioCaptureSource(unsigned int)
+ ?d_func@QMediaRecorder@@ABEPBVQMediaRecorderPrivate@@XZ @ 288 NONAME ; class QMediaRecorderPrivate const * QMediaRecorder::d_func(void) const
+ ?setChannelCount@QAudioFormat@@QAEXH@Z @ 289 NONAME ; void QAudioFormat::setChannelCount(int)
+ ??0QMediaRecorder@@QAE@PAVQMediaObject@@PAVQObject@@@Z @ 290 NONAME ; QMediaRecorder::QMediaRecorder(class QMediaObject *, class QObject *)
+ ?qt_metacall@QMediaPlayerControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 291 NONAME ; int QMediaPlayerControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?reset@QAudioOutput@@QAEXXZ @ 292 NONAME ; void QAudioOutput::reset(void)
+ ?d_func@QMediaPlaylist@@AAEPAVQMediaPlaylistPrivate@@XZ @ 293 NONAME ; class QMediaPlaylistPrivate * QMediaPlaylist::d_func(void)
+ ?trUtf8@QAudioEndpointSelector@@SA?AVQString@@PBD0@Z @ 294 NONAME ; class QString QAudioEndpointSelector::trUtf8(char const *, char const *)
+ ?shuffle@QMediaPlaylist@@QAEXXZ @ 295 NONAME ; void QMediaPlaylist::shuffle(void)
+ ?metaObject@QSoundEffect@@UBEPBUQMetaObject@@XZ @ 296 NONAME ; struct QMetaObject const * QSoundEffect::metaObject(void) const
+ ?loops@QSoundEffect@@QBEHXZ @ 297 NONAME ABSENT ; int QSoundEffect::loops(void) const
+ ??_EQMediaPlaylist@@UAE@I@Z @ 298 NONAME ; QMediaPlaylist::~QMediaPlaylist(unsigned int)
+ ??0QVideoWindowControl@@IAE@PAVQObject@@@Z @ 299 NONAME ; QVideoWindowControl::QVideoWindowControl(class QObject *)
+ ?trUtf8@QMediaPlaylistIOPlugin@@SA?AVQString@@PBD0@Z @ 300 NONAME ; class QString QMediaPlaylistIOPlugin::trUtf8(char const *, char const *)
+ ?stateChanged@QRadioTunerControl@@IAEXW4State@QRadioTuner@@@Z @ 301 NONAME ; void QRadioTunerControl::stateChanged(enum QRadioTuner::State)
+ ?addMedia@QLocalMediaPlaylistProvider@@UAE_NABVQMediaContent@@@Z @ 302 NONAME ; bool QLocalMediaPlaylistProvider::addMedia(class QMediaContent const &)
+ ?qt_metacast@QMediaStreamsControl@@UAEPAXPBD@Z @ 303 NONAME ; void * QMediaStreamsControl::qt_metacast(char const *)
+ ?searchingChanged@QRadioTuner@@IAEX_N@Z @ 304 NONAME ; void QRadioTuner::searchingChanged(bool)
+ ?seekableChanged@QMediaPlayerControl@@IAEX_N@Z @ 305 NONAME ; void QMediaPlayerControl::seekableChanged(bool)
+ ?getStaticMetaObject@QRadioTunerControl@@SAABUQMetaObject@@XZ @ 306 NONAME ; struct QMetaObject const & QRadioTunerControl::getStaticMetaObject(void)
+ ?isValid@QAudioFormat@@QBE_NXZ @ 307 NONAME ; bool QAudioFormat::isValid(void) const
+ ??0QMediaServiceProviderHint@@QAE@ABV0@@Z @ 308 NONAME ; QMediaServiceProviderHint::QMediaServiceProviderHint(class QMediaServiceProviderHint const &)
+ ??_EQMediaPlaylistNavigator@@UAE@I@Z @ 309 NONAME ; QMediaPlaylistNavigator::~QMediaPlaylistNavigator(unsigned int)
+ ?qt_metacall@QMediaRecorder@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 310 NONAME ; int QMediaRecorder::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??0QAudioEncoderSettings@@QAE@XZ @ 311 NONAME ; QAudioEncoderSettings::QAudioEncoderSettings(void)
+ ?supportedFrequencies@QAudioDeviceInfo@@QBE?AV?$QList@H@@XZ @ 312 NONAME ; class QList<int> QAudioDeviceInfo::supportedFrequencies(void) const
+ ?setCodec@QImageEncoderSettings@@QAEXABVQString@@@Z @ 313 NONAME ; void QImageEncoderSettings::setCodec(class QString const &)
+ ?getStaticMetaObject@QMediaPlaylistSourceControl@@SAABUQMetaObject@@XZ @ 314 NONAME ; struct QMetaObject const & QMediaPlaylistSourceControl::getStaticMetaObject(void)
+ ??1QVideoFrame@@QAE@XZ @ 315 NONAME ; QVideoFrame::~QVideoFrame(void)
+ ?notifyInterval@QAudioInput@@QBEHXZ @ 316 NONAME ; int QAudioInput::notifyInterval(void) const
+ ?metaObject@QMediaServiceProvider@@UBEPBUQMetaObject@@XZ @ 317 NONAME ; struct QMetaObject const * QMediaServiceProvider::metaObject(void) const
+ ?setTimeout@QMediaImageViewer@@QAEXH@Z @ 318 NONAME ; void QMediaImageViewer::setTimeout(int)
+ ??0QMediaRecorderControl@@IAE@PAVQObject@@@Z @ 319 NONAME ; QMediaRecorderControl::QMediaRecorderControl(class QObject *)
+ ?staticMetaObject@QVideoWindowControl@@2UQMetaObject@@B @ 320 NONAME ; struct QMetaObject const QVideoWindowControl::staticMetaObject
+ ?channels@QAudioFormat@@QBEHXZ @ 321 NONAME ; int QAudioFormat::channels(void) const
+ ?setVolume@QRadioTuner@@QAEXH@Z @ 322 NONAME ; void QRadioTuner::setVolume(int)
+ ?qt_metacall@QAudioEndpointSelector@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 323 NONAME ; int QAudioEndpointSelector::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?setFrequency@QRadioTuner@@QAEXH@Z @ 324 NONAME ; void QRadioTuner::setFrequency(int)
+ ?cancelSearch@QRadioTuner@@QAEXXZ @ 325 NONAME ; void QRadioTuner::cancelSearch(void)
+ ?metaObject@QMediaPlaylistProvider@@UBEPBUQMetaObject@@XZ @ 326 NONAME ; struct QMetaObject const * QMediaPlaylistProvider::metaObject(void) const
+ ?mediaCount@QLocalMediaPlaylistProvider@@UBEHXZ @ 327 NONAME ; int QLocalMediaPlaylistProvider::mediaCount(void) const
+ ?tr@QMediaServiceProviderPlugin@@SA?AVQString@@PBD0H@Z @ 328 NONAME ; class QString QMediaServiceProviderPlugin::tr(char const *, char const *, int)
+ ?staticMetaObject@QImageEncoderControl@@2UQMetaObject@@B @ 329 NONAME ; struct QMetaObject const QImageEncoderControl::staticMetaObject
+ ?stop@QMediaPlayer@@QAEXXZ @ 330 NONAME ; void QMediaPlayer::stop(void)
+ ?tr@QMediaService@@SA?AVQString@@PBD0@Z @ 331 NONAME ; class QString QMediaService::tr(char const *, char const *)
+ ?bind@QMediaPlayer@@UAE_NPAVQObject@@@Z @ 332 NONAME ; bool QMediaPlayer::bind(class QObject *)
+ ?writableChanged@QMetaDataWriterControl@@IAEX_N@Z @ 333 NONAME ; void QMetaDataWriterControl::writableChanged(bool)
+ ?staticMetaObject@QMediaPlaylistSourceControl@@2UQMetaObject@@B @ 334 NONAME ; struct QMetaObject const QMediaPlaylistSourceControl::staticMetaObject
+ ?availableExtendedMetaData@QMediaRecorder@@QBE?AVQStringList@@XZ @ 335 NONAME ; class QStringList QMediaRecorder::availableExtendedMetaData(void) const
+ ?trUtf8@QAbstractAudioDeviceInfo@@SA?AVQString@@PBD0@Z @ 336 NONAME ; class QString QAbstractAudioDeviceInfo::trUtf8(char const *, char const *)
+ ?qt_metacast@QMediaObject@@UAEPAXPBD@Z @ 337 NONAME ; void * QMediaObject::qt_metacast(char const *)
+ ??0QVideoFrame@@QAE@XZ @ 338 NONAME ; QVideoFrame::QVideoFrame(void)
+ ?qt_metacast@QMediaPlaylistIOPlugin@@UAEPAXPBD@Z @ 339 NONAME ; void * QMediaPlaylistIOPlugin::qt_metacast(char const *)
+ ?media@QMediaImageViewer@@QBE?AVQMediaContent@@XZ @ 340 NONAME ; class QMediaContent QMediaImageViewer::media(void) const
+ ?isNull@QMediaServiceProviderHint@@QBE_NXZ @ 341 NONAME ; bool QMediaServiceProviderHint::isNull(void) const
+ ?setBufferSize@QAudioOutput@@QAEXH@Z @ 342 NONAME ; void QAudioOutput::setBufferSize(int)
+ ?metaObject@QRadioTunerControl@@UBEPBUQMetaObject@@XZ @ 343 NONAME ; struct QMetaObject const * QRadioTunerControl::metaObject(void) const
+ ?metaObject@QMediaRecorderControl@@UBEPBUQMetaObject@@XZ @ 344 NONAME ; struct QMetaObject const * QMediaRecorderControl::metaObject(void) const
+ ??1QMediaObject@@UAE@XZ @ 345 NONAME ; QMediaObject::~QMediaObject(void)
+ ?metaObject@QAudioSystemPlugin@@UBEPBUQMetaObject@@XZ @ 346 NONAME ; struct QMetaObject const * QAudioSystemPlugin::metaObject(void) const
+ ??_EQRadioTunerControl@@UAE@I@Z @ 347 NONAME ; QRadioTunerControl::~QRadioTunerControl(unsigned int)
+ ?paintEvent@QVideoWidget@@MAEXPAVQPaintEvent@@@Z @ 348 NONAME ; void QVideoWidget::paintEvent(class QPaintEvent *)
+ ?bufferStatusChanged@QMediaPlayerControl@@IAEXH@Z @ 349 NONAME ; void QMediaPlayerControl::bufferStatusChanged(int)
+ ?addMedia@QMediaPlaylistProvider@@UAE_NABVQMediaContent@@@Z @ 350 NONAME ; bool QMediaPlaylistProvider::addMedia(class QMediaContent const &)
+ ??0QMediaPlaylistIOPlugin@@QAE@PAVQObject@@@Z @ 351 NONAME ; QMediaPlaylistIOPlugin::QMediaPlaylistIOPlugin(class QObject *)
+ ??4QMediaServiceProviderHint@@QAEAAV0@ABV0@@Z @ 352 NONAME ; class QMediaServiceProviderHint & QMediaServiceProviderHint::operator=(class QMediaServiceProviderHint const &)
+ ?qt_metacast@QVideoRendererControl@@UAEPAXPBD@Z @ 353 NONAME ; void * QVideoRendererControl::qt_metacast(char const *)
+ ?containerMimeType@QMediaRecorder@@QBE?AVQString@@XZ @ 354 NONAME ; class QString QMediaRecorder::containerMimeType(void) const
+ ??YQMediaTimeRange@@QAEAAV0@ABVQMediaTimeInterval@@@Z @ 355 NONAME ; class QMediaTimeRange & QMediaTimeRange::operator+=(class QMediaTimeInterval const &)
+ ??9QVideoEncoderSettings@@QBE_NABV0@@Z @ 356 NONAME ; bool QVideoEncoderSettings::operator!=(class QVideoEncoderSettings const &) const
+ ?error@QMediaPlaylist@@QBE?AW4Error@1@XZ @ 357 NONAME ; enum QMediaPlaylist::Error QMediaPlaylist::error(void) const
+ ??8@YA_NABVQMediaTimeRange@@0@Z @ 358 NONAME ; bool operator==(class QMediaTimeRange const &, class QMediaTimeRange const &)
+ ?qt_metacall@QImageEncoderControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 359 NONAME ; int QImageEncoderControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??0QVideoEncoderSettings@@QAE@ABV0@@Z @ 360 NONAME ; QVideoEncoderSettings::QVideoEncoderSettings(class QVideoEncoderSettings const &)
+ ??0QMediaImageViewer@@QAE@PAVQObject@@@Z @ 361 NONAME ; QMediaImageViewer::QMediaImageViewer(class QObject *)
+ ?device@QMediaServiceProviderHint@@QBE?AVQByteArray@@XZ @ 362 NONAME ; class QByteArray QMediaServiceProviderHint::device(void) const
+ ?qt_metacast@QMediaRecorder@@UAEPAXPBD@Z @ 363 NONAME ; void * QMediaRecorder::qt_metacast(char const *)
+ ?supportedFormatsChanged@QAbstractVideoSurface@@IAEXXZ @ 364 NONAME ; void QAbstractVideoSurface::supportedFormatsChanged(void)
+ ?trUtf8@QAbstractAudioInput@@SA?AVQString@@PBD0@Z @ 365 NONAME ; class QString QAbstractAudioInput::trUtf8(char const *, char const *)
+ ??0QMediaServiceProviderHint@@QAE@ABVQString@@ABVQStringList@@@Z @ 366 NONAME ; QMediaServiceProviderHint::QMediaServiceProviderHint(class QString const &, class QStringList const &)
+ ?staticMetaObject@QRadioTuner@@2UQMetaObject@@B @ 367 NONAME ; struct QMetaObject const QRadioTuner::staticMetaObject
+ ?mutedChanged@QMediaRecorder@@IAEX_N@Z @ 368 NONAME ; void QMediaRecorder::mutedChanged(bool)
+ ?trUtf8@QVideoWidget@@SA?AVQString@@PBD0H@Z @ 369 NONAME ; class QString QVideoWidget::trUtf8(char const *, char const *, int)
+ ?playbackModeChanged@QMediaPlaylistControl@@IAEXW4PlaybackMode@QMediaPlaylist@@@Z @ 370 NONAME ; void QMediaPlaylistControl::playbackModeChanged(enum QMediaPlaylist::PlaybackMode)
+ ??1QImageEncoderControl@@UAE@XZ @ 371 NONAME ; QImageEncoderControl::~QImageEncoderControl(void)
+ ?volume@QRadioTuner@@QBEHXZ @ 372 NONAME ; int QRadioTuner::volume(void) const
+ ?trUtf8@QMediaStreamsControl@@SA?AVQString@@PBD0H@Z @ 373 NONAME ; class QString QMediaStreamsControl::trUtf8(char const *, char const *, int)
+ ??1QAudioSystemPlugin@@UAE@XZ @ 374 NONAME ; QAudioSystemPlugin::~QAudioSystemPlugin(void)
+ ?load@QMediaPlaylistProvider@@UAE_NABVQUrl@@PBD@Z @ 375 NONAME ; bool QMediaPlaylistProvider::load(class QUrl const &, char const *)
+ ??9QMediaContent@@QBE_NABV0@@Z @ 376 NONAME ; bool QMediaContent::operator!=(class QMediaContent const &) const
+ ?sizeHint@QVideoSurfaceFormat@@QBE?AVQSize@@XZ @ 377 NONAME ; class QSize QVideoSurfaceFormat::sizeHint(void) const
+ ?setError@QAbstractVideoSurface@@IAEXW4Error@1@@Z @ 378 NONAME ; void QAbstractVideoSurface::setError(enum QAbstractVideoSurface::Error)
+ ?hueChanged@QVideoWidgetControl@@IAEXH@Z @ 379 NONAME ; void QVideoWidgetControl::hueChanged(int)
+ ?tr@QMediaPlaylistControl@@SA?AVQString@@PBD0H@Z @ 380 NONAME ; class QString QMediaPlaylistControl::tr(char const *, char const *, int)
+ ?sampleType@QAudioFormat@@QBE?AW4SampleType@1@XZ @ 381 NONAME ; enum QAudioFormat::SampleType QAudioFormat::sampleType(void) const
+ ?setChannelCount@QMediaResource@@QAEXH@Z @ 382 NONAME ; void QMediaResource::setChannelCount(int)
+ ?qt_metacast@QRadioTuner@@UAEPAXPBD@Z @ 383 NONAME ; void * QRadioTuner::qt_metacast(char const *)
+ ?isReadOnly@QMediaPlaylistProvider@@UBE_NXZ @ 384 NONAME ; bool QMediaPlaylistProvider::isReadOnly(void) const
+ ?trUtf8@QMediaPlaylistProvider@@SA?AVQString@@PBD0@Z @ 385 NONAME ; class QString QMediaPlaylistProvider::trUtf8(char const *, char const *)
+ ?pixelFormat@QVideoFrame@@QBE?AW4PixelFormat@1@XZ @ 386 NONAME ; enum QVideoFrame::PixelFormat QVideoFrame::pixelFormat(void) const
+ ?audioAvailableChanged@QMediaPlayerControl@@IAEX_N@Z @ 387 NONAME ; void QMediaPlayerControl::audioAvailableChanged(bool)
+ ?timerEvent@QGraphicsVideoItem@@MAEXPAVQTimerEvent@@@Z @ 388 NONAME ; void QGraphicsVideoItem::timerEvent(class QTimerEvent *)
+ ?nextIndex@QMediaPlaylistNavigator@@QBEHH@Z @ 389 NONAME ; int QMediaPlaylistNavigator::nextIndex(int) const
+ ??8QAudioEncoderSettings@@QBE_NABV0@@Z @ 390 NONAME ; bool QAudioEncoderSettings::operator==(class QAudioEncoderSettings const &) const
+ ?qt_metacall@QMediaStreamsControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 391 NONAME ; int QMediaStreamsControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?mediaObject@QGraphicsVideoItem@@UBEPAVQMediaObject@@XZ @ 392 NONAME ; class QMediaObject * QGraphicsVideoItem::mediaObject(void) const
+ ?tr@QVideoEncoderControl@@SA?AVQString@@PBD0H@Z @ 393 NONAME ; class QString QVideoEncoderControl::tr(char const *, char const *, int)
+ ?trUtf8@QMediaPlaylist@@SA?AVQString@@PBD0@Z @ 394 NONAME ; class QString QMediaPlaylist::trUtf8(char const *, char const *)
+ ?availableMetaData@QMediaObject@@QBE?AV?$QList@W4MetaData@QtMultimediaKit@@@@XZ @ 395 NONAME ; class QList<enum QtMultimediaKit::MetaData> QMediaObject::availableMetaData(void) const
+ ?getStaticMetaObject@QAudioCaptureSource@@SAABUQMetaObject@@XZ @ 396 NONAME ; struct QMetaObject const & QAudioCaptureSource::getStaticMetaObject(void)
+ ?isContinuous@QMediaTimeRange@@QBE_NXZ @ 397 NONAME ; bool QMediaTimeRange::isContinuous(void) const
+ ?insertMedia@QMediaPlaylistProvider@@UAE_NHABV?$QList@VQMediaContent@@@@@Z @ 398 NONAME ; bool QMediaPlaylistProvider::insertMedia(int, class QList<class QMediaContent> const &)
+ ?staticMetaObject@QMediaStreamsControl@@2UQMetaObject@@B @ 399 NONAME ; struct QMetaObject const QMediaStreamsControl::staticMetaObject
+ ?qt_metacast@QMediaPlaylistNavigator@@UAEPAXPBD@Z @ 400 NONAME ; void * QMediaPlaylistNavigator::qt_metacast(char const *)
+ ?activeEndpointChanged@QAudioEndpointSelector@@IAEXABVQString@@@Z @ 401 NONAME ; void QAudioEndpointSelector::activeEndpointChanged(class QString const &)
+ ?save@QMediaPlaylist@@QAE_NABVQUrl@@PBD@Z @ 402 NONAME ; bool QMediaPlaylist::save(class QUrl const &, char const *)
+ ?supportedChannels@QAudioDeviceInfo@@QBE?AV?$QList@H@@XZ @ 403 NONAME ; class QList<int> QAudioDeviceInfo::supportedChannels(void) const
+ ?setCodec@QVideoEncoderSettings@@QAEXABVQString@@@Z @ 404 NONAME ; void QVideoEncoderSettings::setCodec(class QString const &)
+ ?d_func@QAudioCaptureSource@@ABEPBVQAudioCaptureSourcePrivate@@XZ @ 405 NONAME ; class QAudioCaptureSourcePrivate const * QAudioCaptureSource::d_func(void) const
+ ?trUtf8@QMediaImageViewer@@SA?AVQString@@PBD0@Z @ 406 NONAME ; class QString QMediaImageViewer::trUtf8(char const *, char const *)
+ ?pause@QMediaPlayer@@QAEXXZ @ 407 NONAME ; void QMediaPlayer::pause(void)
+ ?staticMetaObject@QMediaControl@@2UQMetaObject@@B @ 408 NONAME ; struct QMetaObject const QMediaControl::staticMetaObject
+ ?isAvailable@QRadioTuner@@UBE_NXZ @ 409 NONAME ; bool QRadioTuner::isAvailable(void) const
+ ??G@YA?AVQMediaTimeRange@@ABV0@0@Z @ 410 NONAME ; class QMediaTimeRange operator-(class QMediaTimeRange const &, class QMediaTimeRange const &)
+ ?unmap@QVideoFrame@@QAEXXZ @ 411 NONAME ; void QVideoFrame::unmap(void)
+ ?qt_metacast@QImageEncoderControl@@UAEPAXPBD@Z @ 412 NONAME ; void * QImageEncoderControl::qt_metacast(char const *)
+ ??0QMediaServiceProviderHint@@QAE@XZ @ 413 NONAME ; QMediaServiceProviderHint::QMediaServiceProviderHint(void)
+ ??9QImageEncoderSettings@@QBE_NABV0@@Z @ 414 NONAME ; bool QImageEncoderSettings::operator!=(class QImageEncoderSettings const &) const
+ ?play@QMediaImageViewer@@QAEXXZ @ 415 NONAME ; void QMediaImageViewer::play(void)
+ ?setPosition@QMediaPlayer@@QAEX_J@Z @ 416 NONAME ; void QMediaPlayer::setPosition(long long)
+ ?setResolution@QMediaResource@@QAEXHH@Z @ 417 NONAME ; void QMediaResource::setResolution(int, int)
+ ??_EQVideoDeviceControl@@UAE@I@Z @ 418 NONAME ; QVideoDeviceControl::~QVideoDeviceControl(unsigned int)
+ ?addInterval@QMediaTimeRange@@QAEX_J0@Z @ 419 NONAME ; void QMediaTimeRange::addInterval(long long, long long)
+ ??0QMediaContent@@QAE@ABV0@@Z @ 420 NONAME ; QMediaContent::QMediaContent(class QMediaContent const &)
+ ?videoBitRate@QMediaResource@@QBEHXZ @ 421 NONAME ; int QMediaResource::videoBitRate(void) const
+ ?statusChanged@QAudioCaptureSource@@AAEXXZ @ 422 NONAME ; void QAudioCaptureSource::statusChanged(void)
+ ?trUtf8@QAudioOutput@@SA?AVQString@@PBD0H@Z @ 423 NONAME ; class QString QAudioOutput::trUtf8(char const *, char const *, int)
+ ?availabilityError@QMediaRecorder@@QBE?AW4AvailabilityError@QtMultimediaKit@@XZ @ 424 NONAME ; enum QtMultimediaKit::AvailabilityError QMediaRecorder::availabilityError(void) const
+ ?setMediaObject@QGraphicsVideoItem@@MAE_NPAVQMediaObject@@@Z @ 425 NONAME ; bool QGraphicsVideoItem::setMediaObject(class QMediaObject *)
+ ?isFormatSupported@QAbstractVideoSurface@@UBE_NABVQVideoSurfaceFormat@@@Z @ 426 NONAME ; bool QAbstractVideoSurface::isFormatSupported(class QVideoSurfaceFormat const &) const
+ ??0QMetaDataWriterControl@@IAE@PAVQObject@@@Z @ 427 NONAME ; QMetaDataWriterControl::QMetaDataWriterControl(class QObject *)
+ ?frequencyChanged@QRadioTuner@@IAEXH@Z @ 428 NONAME ; void QRadioTuner::frequencyChanged(int)
+ ?hideEvent@QVideoWidget@@MAEXPAVQHideEvent@@@Z @ 429 NONAME ; void QVideoWidget::hideEvent(class QHideEvent *)
+ ?supportedMimeTypes@QMediaServiceProvider@@UBE?AVQStringList@@ABVQByteArray@@H@Z @ 430 NONAME ; class QStringList QMediaServiceProvider::supportedMimeTypes(class QByteArray const &, int) const
+ ?qt_metacast@QMediaPlayer@@UAEPAXPBD@Z @ 431 NONAME ; void * QMediaPlayer::qt_metacast(char const *)
+ ?metaDataAvailableChanged@QMediaRecorder@@IAEX_N@Z @ 432 NONAME ; void QMediaRecorder::metaDataAvailableChanged(bool)
+ ?metaDataAvailableChanged@QMediaObject@@IAEX_N@Z @ 433 NONAME ; void QMediaObject::metaDataAvailableChanged(bool)
+ ?stop@QAudioInput@@QAEXXZ @ 434 NONAME ; void QAudioInput::stop(void)
+ ??0QVideoFrame@@QAE@ABVQImage@@@Z @ 435 NONAME ; QVideoFrame::QVideoFrame(class QImage const &)
+ ?realm@QAudioDeviceInfo@@ABE?AVQString@@XZ @ 436 NONAME ; class QString QAudioDeviceInfo::realm(void) const
+ ?trUtf8@QRadioTunerControl@@SA?AVQString@@PBD0@Z @ 437 NONAME ; class QString QRadioTunerControl::trUtf8(char const *, char const *)
+ ?notify@QAbstractAudioInput@@IAEXXZ @ 438 NONAME ; void QAbstractAudioInput::notify(void)
+ ?metaDataAvailableChanged@QMetaDataReaderControl@@IAEX_N@Z @ 439 NONAME ; void QMetaDataReaderControl::metaDataAvailableChanged(bool)
+ ?request@QMediaResource@@QBE?AVQNetworkRequest@@XZ @ 440 NONAME ; class QNetworkRequest QMediaResource::request(void) const
+ ?handle@QVideoFrame@@QBE?AVQVariant@@XZ @ 441 NONAME ; class QVariant QVideoFrame::handle(void) const
+ ?setEncodingMode@QVideoEncoderSettings@@QAEXW4EncodingMode@QtMultimediaKit@@@Z @ 442 NONAME ; void QVideoEncoderSettings::setEncodingMode(enum QtMultimediaKit::EncodingMode)
+ ??1QMediaService@@UAE@XZ @ 443 NONAME ; QMediaService::~QMediaService(void)
+ ?volume@QMediaPlayer@@QBEHXZ @ 444 NONAME ; int QMediaPlayer::volume(void) const
+ ?tr@QMetaDataReaderControl@@SA?AVQString@@PBD0@Z @ 445 NONAME ; class QString QMetaDataReaderControl::tr(char const *, char const *)
+ ?supportedContainers@QMediaRecorder@@QBE?AVQStringList@@XZ @ 446 NONAME ; class QStringList QMediaRecorder::supportedContainers(void) const
+ ??0QVideoFrame@@QAE@PAVQAbstractVideoBuffer@@ABVQSize@@W4PixelFormat@0@@Z @ 447 NONAME ; QVideoFrame::QVideoFrame(class QAbstractVideoBuffer *, class QSize const &, enum QVideoFrame::PixelFormat)
+ ?d_func@QVideoWidget@@ABEPBVQVideoWidgetPrivate@@XZ @ 448 NONAME ; class QVideoWidgetPrivate const * QVideoWidget::d_func(void) const
+ ?durationChanged@QMediaRecorder@@IAEX_J@Z @ 449 NONAME ; void QMediaRecorder::durationChanged(long long)
+ ?trUtf8@QVideoWidgetControl@@SA?AVQString@@PBD0H@Z @ 450 NONAME ; class QString QVideoWidgetControl::trUtf8(char const *, char const *, int)
+ ?errorString@QMediaRecorder@@QBE?AVQString@@XZ @ 451 NONAME ; class QString QMediaRecorder::errorString(void) const
+ ?getStaticMetaObject@QMediaPlayerControl@@SAABUQMetaObject@@XZ @ 452 NONAME ; struct QMetaObject const & QMediaPlayerControl::getStaticMetaObject(void)
+ ?propertyNames@QVideoSurfaceFormat@@QBE?AV?$QList@VQByteArray@@@@XZ @ 453 NONAME ; class QList<class QByteArray> QVideoSurfaceFormat::propertyNames(void) const
+ ?trUtf8@QMetaDataWriterControl@@SA?AVQString@@PBD0H@Z @ 454 NONAME ; class QString QMetaDataWriterControl::trUtf8(char const *, char const *, int)
+ ??0QImageVideoBuffer@@QAE@ABVQImage@@@Z @ 455 NONAME ; QImageVideoBuffer::QImageVideoBuffer(class QImage const &)
+ ?pixelFormatFromImageFormat@QVideoFrame@@SA?AW4PixelFormat@1@W4Format@QImage@@@Z @ 456 NONAME ; enum QVideoFrame::PixelFormat QVideoFrame::pixelFormatFromImageFormat(enum QImage::Format)
+ ?defaultServiceProvider@QMediaServiceProvider@@SAPAV1@XZ @ 457 NONAME ; class QMediaServiceProvider * QMediaServiceProvider::defaultServiceProvider(void)
+ ?tr@QAudioCaptureSource@@SA?AVQString@@PBD0H@Z @ 458 NONAME ; class QString QAudioCaptureSource::tr(char const *, char const *, int)
+ ?start@QMediaTimeInterval@@QBE_JXZ @ 459 NONAME ; long long QMediaTimeInterval::start(void) const
+ ?staticMetaObject@QMediaPlaylistProvider@@2UQMetaObject@@B @ 460 NONAME ; struct QMetaObject const QMediaPlaylistProvider::staticMetaObject
+ ?isEmpty@QMediaTimeRange@@QBE_NXZ @ 461 NONAME ; bool QMediaTimeRange::isEmpty(void) const
+ ?staticMetaObject@QMediaPlaylistNavigator@@2UQMetaObject@@B @ 462 NONAME ; struct QMetaObject const QMediaPlaylistNavigator::staticMetaObject
+ ?features@QMediaServiceProviderHint@@QBE?AV?$QFlags@W4Feature@QMediaServiceProviderHint@@@@XZ @ 463 NONAME ; class QFlags<enum QMediaServiceProviderHint::Feature> QMediaServiceProviderHint::features(void) const
+ ?isNull@QMediaResource@@QBE_NXZ @ 464 NONAME ; bool QMediaResource::isNull(void) const
+ ??8QMediaResource@@QBE_NABV0@@Z @ 465 NONAME ; bool QMediaResource::operator==(class QMediaResource const &) const
+ ?bufferStatusChanged@QMediaPlayer@@IAEXH@Z @ 466 NONAME ; void QMediaPlayer::bufferStatusChanged(int)
+ ?error@QAudioOutput@@QBE?AW4Error@QAudio@@XZ @ 467 NONAME ; enum QAudio::Error QAudioOutput::error(void) const
+ ?d_func@QRadioTuner@@ABEPBVQRadioTunerPrivate@@XZ @ 468 NONAME ; class QRadioTunerPrivate const * QRadioTuner::d_func(void) const
+ ?d_func@QMemoryVideoBuffer@@ABEPBVQMemoryVideoBufferPrivate@@XZ @ 469 NONAME ; class QMemoryVideoBufferPrivate const * QMemoryVideoBuffer::d_func(void) const
+ ?trUtf8@QAudioEncoderControl@@SA?AVQString@@PBD0H@Z @ 470 NONAME ; class QString QAudioEncoderControl::trUtf8(char const *, char const *, int)
+ ?trUtf8@QMediaPlayer@@SA?AVQString@@PBD0@Z @ 471 NONAME ; class QString QMediaPlayer::trUtf8(char const *, char const *)
+ ?elapsedUSecs@QAudioOutput@@QBE_JXZ @ 472 NONAME ; long long QAudioOutput::elapsedUSecs(void) const
+ ??8@YA_NABVQMediaTimeInterval@@0@Z @ 473 NONAME ; bool operator==(class QMediaTimeInterval const &, class QMediaTimeInterval const &)
+ ?containerDescription@QMediaRecorder@@QBE?AVQString@@ABV2@@Z @ 474 NONAME ; class QString QMediaRecorder::containerDescription(class QString const &) const
+ ?trUtf8@QVideoWindowControl@@SA?AVQString@@PBD0H@Z @ 475 NONAME ; class QString QVideoWindowControl::trUtf8(char const *, char const *, int)
+ ?isMuted@QSoundEffect@@QBE_NXZ @ 476 NONAME ; bool QSoundEffect::isMuted(void) const
+ ?volumeChanged@QMediaPlayer@@IAEXH@Z @ 477 NONAME ; void QMediaPlayer::volumeChanged(int)
+ ??1QVideoWidgetControl@@UAE@XZ @ 478 NONAME ; QVideoWidgetControl::~QVideoWidgetControl(void)
+ ??_EQMediaRecorderControl@@UAE@I@Z @ 479 NONAME ; QMediaRecorderControl::~QMediaRecorderControl(unsigned int)
+ ?volumeChanged@QRadioTunerControl@@IAEXH@Z @ 480 NONAME ; void QRadioTunerControl::volumeChanged(int)
+ ??_EQMediaContainerControl@@UAE@I@Z @ 481 NONAME ; QMediaContainerControl::~QMediaContainerControl(unsigned int)
+ ?tr@QAudioInput@@SA?AVQString@@PBD0H@Z @ 482 NONAME ; class QString QAudioInput::tr(char const *, char const *, int)
+ ??8QMediaContent@@QBE_NABV0@@Z @ 483 NONAME ; bool QMediaContent::operator==(class QMediaContent const &) const
+ ?getStaticMetaObject@QImageEncoderControl@@SAABUQMetaObject@@XZ @ 484 NONAME ; struct QMetaObject const & QImageEncoderControl::getStaticMetaObject(void)
+ ?durationChanged@QMediaRecorderControl@@IAEX_J@Z @ 485 NONAME ; void QMediaRecorderControl::durationChanged(long long)
+ ?getStaticMetaObject@QMetaDataReaderControl@@SAABUQMetaObject@@XZ @ 486 NONAME ; struct QMetaObject const & QMetaDataReaderControl::getStaticMetaObject(void)
+ ?hue@QVideoWidget@@QBEHXZ @ 487 NONAME ; int QVideoWidget::hue(void) const
+ ?handleType@QVideoSurfaceFormat@@QBE?AW4HandleType@QAbstractVideoBuffer@@XZ @ 488 NONAME ; enum QAbstractVideoBuffer::HandleType QVideoSurfaceFormat::handleType(void) const
+ ?setNotifyInterval@QAudioOutput@@QAEXH@Z @ 489 NONAME ; void QAudioOutput::setNotifyInterval(int)
+ ?start@QAbstractVideoSurface@@UAE_NABVQVideoSurfaceFormat@@@Z @ 490 NONAME ; bool QAbstractVideoSurface::start(class QVideoSurfaceFormat const &)
+ ?processedUSecs@QAudioInput@@QBE_JXZ @ 491 NONAME ; long long QAudioInput::processedUSecs(void) const
+ ?tr@QMediaObject@@SA?AVQString@@PBD0H@Z @ 492 NONAME ; class QString QMediaObject::tr(char const *, char const *, int)
+ ?fullScreenChanged@QVideoWindowControl@@IAEX_N@Z @ 493 NONAME ; void QVideoWindowControl::fullScreenChanged(bool)
+ ?play@QSoundEffect@@QAEXXZ @ 494 NONAME ; void QSoundEffect::play(void)
+ ?stop@QAbstractVideoSurface@@UAEXXZ @ 495 NONAME ; void QAbstractVideoSurface::stop(void)
+ ?contains@QMediaTimeRange@@QBE_N_J@Z @ 496 NONAME ; bool QMediaTimeRange::contains(long long) const
+ ?setMuted@QMediaPlayer@@QAEX_N@Z @ 497 NONAME ; void QMediaPlayer::setMuted(bool)
+ ?tr@QRadioTunerControl@@SA?AVQString@@PBD0@Z @ 498 NONAME ; class QString QRadioTunerControl::tr(char const *, char const *)
+ ?surfaceFormat@QAbstractVideoSurface@@QBE?AVQVideoSurfaceFormat@@XZ @ 499 NONAME ; class QVideoSurfaceFormat QAbstractVideoSurface::surfaceFormat(void) const
+ ?addPropertyWatch@QMediaObject@@IAEXABVQByteArray@@@Z @ 500 NONAME ; void QMediaObject::addPropertyWatch(class QByteArray const &)
+ ??_EQMediaPlaylistIOPlugin@@UAE@I@Z @ 501 NONAME ; QMediaPlaylistIOPlugin::~QMediaPlaylistIOPlugin(unsigned int)
+ ?trUtf8@QMediaPlayerControl@@SA?AVQString@@PBD0H@Z @ 502 NONAME ; class QString QMediaPlayerControl::trUtf8(char const *, char const *, int)
+ ?setVideoBitRate@QMediaResource@@QAEXH@Z @ 503 NONAME ; void QMediaResource::setVideoBitRate(int)
+ ?qt_metacall@QRadioTuner@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 504 NONAME ; int QRadioTuner::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?frequencyChanged@QRadioTunerControl@@IAEXH@Z @ 505 NONAME ; void QRadioTunerControl::frequencyChanged(int)
+ ?pause@QMediaRecorder@@QAEXXZ @ 506 NONAME ; void QMediaRecorder::pause(void)
+ ?fullScreenChanged@QVideoWidgetControl@@IAEX_N@Z @ 507 NONAME ; void QVideoWidgetControl::fullScreenChanged(bool)
+ ?intervals@QMediaTimeRange@@QBE?AV?$QList@VQMediaTimeInterval@@@@XZ @ 508 NONAME ; class QList<class QMediaTimeInterval> QMediaTimeRange::intervals(void) const
+ ?bytesReady@QAudioInput@@QBEHXZ @ 509 NONAME ; int QAudioInput::bytesReady(void) const
+ ?tr@QMediaServiceProviderPlugin@@SA?AVQString@@PBD0@Z @ 510 NONAME ; class QString QMediaServiceProviderPlugin::tr(char const *, char const *)
+ ?stateChanged@QMediaPlayerControl@@IAEXW4State@QMediaPlayer@@@Z @ 511 NONAME ; void QMediaPlayerControl::stateChanged(enum QMediaPlayer::State)
+ ?tr@QAbstractAudioOutput@@SA?AVQString@@PBD0H@Z @ 512 NONAME ; class QString QAbstractAudioOutput::tr(char const *, char const *, int)
+ ?previous@QMediaPlaylist@@QAEXXZ @ 513 NONAME ; void QMediaPlaylist::previous(void)
+ ?stereoMode@QRadioTuner@@QBE?AW4StereoMode@1@XZ @ 514 NONAME ; enum QRadioTuner::StereoMode QRadioTuner::stereoMode(void) const
+ ?metaObject@QMediaPlaylist@@UBEPBUQMetaObject@@XZ @ 515 NONAME ; struct QMetaObject const * QMediaPlaylist::metaObject(void) const
+ ?trUtf8@QVideoWindowControl@@SA?AVQString@@PBD0@Z @ 516 NONAME ; class QString QVideoWindowControl::trUtf8(char const *, char const *)
+ ?stop@QMediaRecorder@@QAEXXZ @ 517 NONAME ; void QMediaRecorder::stop(void)
+ ?setViewport@QVideoSurfaceFormat@@QAEXABVQRect@@@Z @ 518 NONAME ; void QVideoSurfaceFormat::setViewport(class QRect const &)
+ ?setPlaybackMode@QMediaPlaylistNavigator@@QAEXW4PlaybackMode@QMediaPlaylist@@@Z @ 519 NONAME ; void QMediaPlaylistNavigator::setPlaybackMode(enum QMediaPlaylist::PlaybackMode)
+ ?tr@QMediaPlaylist@@SA?AVQString@@PBD0@Z @ 520 NONAME ; class QString QMediaPlaylist::tr(char const *, char const *)
+ ?playbackRate@QMediaPlayer@@QBEMXZ @ 521 NONAME ; float QMediaPlayer::playbackRate(void) const
+ ?metaObject@QMediaStreamsControl@@UBEPBUQMetaObject@@XZ @ 522 NONAME ; struct QMetaObject const * QMediaStreamsControl::metaObject(void) const
+ ?metaObject@QMediaObject@@UBEPBUQMetaObject@@XZ @ 523 NONAME ; struct QMetaObject const * QMediaObject::metaObject(void) const
+ ?d_func@QMediaRecorder@@AAEPAVQMediaRecorderPrivate@@XZ @ 524 NONAME ; class QMediaRecorderPrivate * QMediaRecorder::d_func(void)
+ ?brightnessChanged@QVideoWindowControl@@IAEXH@Z @ 525 NONAME ; void QVideoWindowControl::brightnessChanged(int)
+ ?stereoStatusChanged@QRadioTuner@@IAEX_N@Z @ 526 NONAME ; void QRadioTuner::stereoStatusChanged(bool)
+ ?setQuality@QVideoEncoderSettings@@QAEXW4EncodingQuality@QtMultimediaKit@@@Z @ 527 NONAME ; void QVideoEncoderSettings::setQuality(enum QtMultimediaKit::EncodingQuality)
+ ?staticMetaObject@QMetaDataReaderControl@@2UQMetaObject@@B @ 528 NONAME ; struct QMetaObject const QMetaDataReaderControl::staticMetaObject
+ ?isNull@QAudioEncoderSettings@@QBE_NXZ @ 529 NONAME ; bool QAudioEncoderSettings::isNull(void) const
+ ?handleType@QVideoFrame@@QBE?AW4HandleType@QAbstractVideoBuffer@@XZ @ 530 NONAME ; enum QAbstractVideoBuffer::HandleType QVideoFrame::handleType(void) const
+ ?setAudioInput@QAudioCaptureSource@@QAEXABVQString@@@Z @ 531 NONAME ; void QAudioCaptureSource::setAudioInput(class QString const &)
+ ?mapMode@QImageVideoBuffer@@UBE?AW4MapMode@QAbstractVideoBuffer@@XZ @ 532 NONAME ; enum QAbstractVideoBuffer::MapMode QImageVideoBuffer::mapMode(void) const
+ ?mediaAboutToBeRemoved@QMediaPlaylist@@IAEXHH@Z @ 533 NONAME ; void QMediaPlaylist::mediaAboutToBeRemoved(int, int)
+ ??8QVideoEncoderSettings@@QBE_NABV0@@Z @ 534 NONAME ; bool QVideoEncoderSettings::operator==(class QVideoEncoderSettings const &) const
+ ??0QMediaResource@@QAE@XZ @ 535 NONAME ; QMediaResource::QMediaResource(void)
+ ?staticMetaObject@QAudioEncoderControl@@2UQMetaObject@@B @ 536 NONAME ; struct QMetaObject const QAudioEncoderControl::staticMetaObject
+ ?isAvailable@QMediaObject@@UBE_NXZ @ 537 NONAME ; bool QMediaObject::isAvailable(void) const
+ ?trUtf8@QVideoRendererControl@@SA?AVQString@@PBD0@Z @ 538 NONAME ; class QString QVideoRendererControl::trUtf8(char const *, char const *)
+ ??0QAudioEncoderControl@@IAE@PAVQObject@@@Z @ 539 NONAME ; QAudioEncoderControl::QAudioEncoderControl(class QObject *)
+ ?supportedCodecs@QAudioDeviceInfo@@QBE?AVQStringList@@XZ @ 540 NONAME ; class QStringList QAudioDeviceInfo::supportedCodecs(void) const
+ ?playlistProviderChanged@QMediaPlaylistControl@@IAEXXZ @ 541 NONAME ; void QMediaPlaylistControl::playlistProviderChanged(void)
+ ??4QMediaContent@@QAEAAV0@ABV0@@Z @ 542 NONAME ; class QMediaContent & QMediaContent::operator=(class QMediaContent const &)
+ ?getStaticMetaObject@QMediaStreamsControl@@SAABUQMetaObject@@XZ @ 543 NONAME ; struct QMetaObject const & QMediaStreamsControl::getStaticMetaObject(void)
+ ??1QAudioEncoderControl@@UAE@XZ @ 544 NONAME ; QAudioEncoderControl::~QAudioEncoderControl(void)
+ ?trUtf8@QLocalMediaPlaylistProvider@@SA?AVQString@@PBD0H@Z @ 545 NONAME ; class QString QLocalMediaPlaylistProvider::trUtf8(char const *, char const *, int)
+ ?availabilityError@QRadioTuner@@UBE?AW4AvailabilityError@QtMultimediaKit@@XZ @ 546 NONAME ; enum QtMultimediaKit::AvailabilityError QRadioTuner::availabilityError(void) const
+ ??0QVideoFrame@@QAE@HABVQSize@@HW4PixelFormat@0@@Z @ 547 NONAME ; QVideoFrame::QVideoFrame(int, class QSize const &, int, enum QVideoFrame::PixelFormat)
+ ?trUtf8@QMediaPlaylistSourceControl@@SA?AVQString@@PBD0H@Z @ 548 NONAME ; class QString QMediaPlaylistSourceControl::trUtf8(char const *, char const *, int)
+ ?handle@QAbstractVideoBuffer@@UBE?AVQVariant@@XZ @ 549 NONAME ; class QVariant QAbstractVideoBuffer::handle(void) const
+ ?setOutputLocation@QMediaRecorder@@QAE_NABVQUrl@@@Z @ 550 NONAME ; bool QMediaRecorder::setOutputLocation(class QUrl const &)
+ ?canonicalRequest@QMediaContent@@QBE?AVQNetworkRequest@@XZ @ 551 NONAME ; class QNetworkRequest QMediaContent::canonicalRequest(void) const
+ ?error@QRadioTuner@@QBE?AW4Error@1@XZ @ 552 NONAME ; enum QRadioTuner::Error QRadioTuner::error(void) const
+ ?codec@QVideoEncoderSettings@@QBE?AVQString@@XZ @ 553 NONAME ; class QString QVideoEncoderSettings::codec(void) const
+ ?qt_metacall@QAudioEncoderControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 554 NONAME ; int QAudioEncoderControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?trUtf8@QMediaService@@SA?AVQString@@PBD0H@Z @ 555 NONAME ; class QString QMediaService::trUtf8(char const *, char const *, int)
+ ?removeMedia@QMediaPlaylistProvider@@UAE_NHH@Z @ 556 NONAME ; bool QMediaPlaylistProvider::removeMedia(int, int)
+ ?saturationChanged@QVideoWindowControl@@IAEXH@Z @ 557 NONAME ; void QVideoWindowControl::saturationChanged(int)
+ ??0QMediaPlaylistControl@@IAE@PAVQObject@@@Z @ 558 NONAME ; QMediaPlaylistControl::QMediaPlaylistControl(class QObject *)
+ ?error@QMediaRecorder@@QBE?AW4Error@1@XZ @ 559 NONAME ; enum QMediaRecorder::Error QMediaRecorder::error(void) const
+ ?canonicalResource@QMediaContent@@QBE?AVQMediaResource@@XZ @ 560 NONAME ; class QMediaResource QMediaContent::canonicalResource(void) const
+ ?metaObject@QAbstractVideoSurface@@UBEPBUQMetaObject@@XZ @ 561 NONAME ; struct QMetaObject const * QAbstractVideoSurface::metaObject(void) const
+ ??0QMediaService@@IAE@AAVQMediaServicePrivate@@PAVQObject@@@Z @ 562 NONAME ; QMediaService::QMediaService(class QMediaServicePrivate &, class QObject *)
+ ?playlist@QMediaPlaylistNavigator@@QBEPAVQMediaPlaylistProvider@@XZ @ 563 NONAME ; class QMediaPlaylistProvider * QMediaPlaylistNavigator::playlist(void) const
+ ?metaObject@QAudioCaptureSource@@UBEPBUQMetaObject@@XZ @ 564 NONAME ; struct QMetaObject const * QAudioCaptureSource::metaObject(void) const
+ ?staticMetaObject@QMetaDataWriterControl@@2UQMetaObject@@B @ 565 NONAME ; struct QMetaObject const QMetaDataWriterControl::staticMetaObject
+ ?getStaticMetaObject@QAbstractAudioInput@@SAABUQMetaObject@@XZ @ 566 NONAME ; struct QMetaObject const & QAbstractAudioInput::getStaticMetaObject(void)
+ ?d_func@QAbstractVideoBuffer@@AAEPAVQAbstractVideoBufferPrivate@@XZ @ 567 NONAME ; class QAbstractVideoBufferPrivate * QAbstractVideoBuffer::d_func(void)
+ ?staticMetaObject@QMediaPlaylistControl@@2UQMetaObject@@B @ 568 NONAME ; struct QMetaObject const QMediaPlaylistControl::staticMetaObject
+ ?qt_metacast@QVideoDeviceControl@@UAEPAXPBD@Z @ 569 NONAME ; void * QVideoDeviceControl::qt_metacast(char const *)
+ ?metaObject@QVideoRendererControl@@UBEPBUQMetaObject@@XZ @ 570 NONAME ; struct QMetaObject const * QVideoRendererControl::metaObject(void) const
+ ??1QMediaPlaylistReader@@UAE@XZ @ 571 NONAME ; QMediaPlaylistReader::~QMediaPlaylistReader(void)
+ ?getStaticMetaObject@QAbstractAudioOutput@@SAABUQMetaObject@@XZ @ 572 NONAME ; struct QMetaObject const & QAbstractAudioOutput::getStaticMetaObject(void)
+ ?qt_metacast@QAbstractVideoSurface@@UAEPAXPBD@Z @ 573 NONAME ; void * QAbstractVideoSurface::qt_metacast(char const *)
+ ?qt_metacall@QMetaDataWriterControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 574 NONAME ; int QMetaDataWriterControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??0QAbstractVideoSurface@@IAE@AAVQAbstractVideoSurfacePrivate@@PAVQObject@@@Z @ 575 NONAME ; QAbstractVideoSurface::QAbstractVideoSurface(class QAbstractVideoSurfacePrivate &, class QObject *)
+ ?tr@QMediaPlaylist@@SA?AVQString@@PBD0H@Z @ 576 NONAME ; class QString QMediaPlaylist::tr(char const *, char const *, int)
+ ??1QMediaServiceFeaturesInterface@@UAE@XZ @ 577 NONAME ; QMediaServiceFeaturesInterface::~QMediaServiceFeaturesInterface(void)
+ ?frequency@QAudioFormat@@QBEHXZ @ 578 NONAME ; int QAudioFormat::frequency(void) const
+ ?errorString@QMediaPlayer@@QBE?AVQString@@XZ @ 579 NONAME ; class QString QMediaPlayer::errorString(void) const
+ ?map@QImageVideoBuffer@@UAEPAEW4MapMode@QAbstractVideoBuffer@@PAH1@Z @ 580 NONAME ; unsigned char * QImageVideoBuffer::map(enum QAbstractVideoBuffer::MapMode, int *, int *)
+ ?setBufferSize@QAudioInput@@QAEXH@Z @ 581 NONAME ; void QAudioInput::setBufferSize(int)
+ ?loadFailed@QMediaPlaylist@@IAEXXZ @ 582 NONAME ; void QMediaPlaylist::loadFailed(void)
+ ?elapsedTime@QMediaImageViewer@@QBEHXZ @ 583 NONAME ; int QMediaImageViewer::elapsedTime(void) const
+ ?loaded@QMediaPlaylist@@IAEXXZ @ 584 NONAME ; void QMediaPlaylist::loaded(void)
+ ?mediaObject@QVideoWidget@@UBEPAVQMediaObject@@XZ @ 585 NONAME ; class QMediaObject * QVideoWidget::mediaObject(void) const
+ ??8QImageEncoderSettings@@QBE_NABV0@@Z @ 586 NONAME ; bool QImageEncoderSettings::operator==(class QImageEncoderSettings const &) const
+ ??1QMediaPlaylistNavigator@@UAE@XZ @ 587 NONAME ; QMediaPlaylistNavigator::~QMediaPlaylistNavigator(void)
+ ??0QAudioDeviceInfo@@QAE@ABV0@@Z @ 588 NONAME ; QAudioDeviceInfo::QAudioDeviceInfo(class QAudioDeviceInfo const &)
+ ?tr@QVideoEncoderControl@@SA?AVQString@@PBD0@Z @ 589 NONAME ; class QString QVideoEncoderControl::tr(char const *, char const *)
+ ?qt_metacast@QMediaRecorderControl@@UAEPAXPBD@Z @ 590 NONAME ; void * QMediaRecorderControl::qt_metacast(char const *)
+ ?tr@QAudioInput@@SA?AVQString@@PBD0@Z @ 591 NONAME ; class QString QAudioInput::tr(char const *, char const *)
+ ?devices@QMediaServiceProvider@@UBE?AV?$QList@VQByteArray@@@@ABVQByteArray@@@Z @ 592 NONAME ; class QList<class QByteArray> QMediaServiceProvider::devices(class QByteArray const &) const
+ ?staticMetaObject@QMediaRecorderControl@@2UQMetaObject@@B @ 593 NONAME ; struct QMetaObject const QMediaRecorderControl::staticMetaObject
+ ?qt_metacall@QMediaPlaylist@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 594 NONAME ; int QMediaPlaylist::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?setBrightness@QVideoWidget@@QAEXH@Z @ 595 NONAME ; void QVideoWidget::setBrightness(int)
+ ??4QImageEncoderSettings@@QAEAAV0@ABV0@@Z @ 596 NONAME ; class QImageEncoderSettings & QImageEncoderSettings::operator=(class QImageEncoderSettings const &)
+ ?qt_metacall@QVideoWidgetControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 597 NONAME ; int QVideoWidgetControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??_EQAudioSystemFactoryInterface@@UAE@I@Z @ 598 NONAME ; QAudioSystemFactoryInterface::~QAudioSystemFactoryInterface(unsigned int)
+ ?isNull@QMediaContent@@QBE_NXZ @ 599 NONAME ; bool QMediaContent::isNull(void) const
+ ?qt_metacall@QAbstractVideoSurface@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 600 NONAME ; int QAbstractVideoSurface::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??1QVideoDeviceControl@@UAE@XZ @ 601 NONAME ; QVideoDeviceControl::~QVideoDeviceControl(void)
+ ?isValid@QVideoSurfaceFormat@@QBE_NXZ @ 602 NONAME ; bool QVideoSurfaceFormat::isValid(void) const
+ ?defaultInputDevice@QAudioDeviceInfo@@SA?AV1@XZ @ 603 NONAME ; class QAudioDeviceInfo QAudioDeviceInfo::defaultInputDevice(void)
+ ?tr@QVideoDeviceControl@@SA?AVQString@@PBD0H@Z @ 604 NONAME ; class QString QVideoDeviceControl::tr(char const *, char const *, int)
+ ?pause@QMediaImageViewer@@QAEXXZ @ 605 NONAME ; void QMediaImageViewer::pause(void)
+ ?qt_metacast@QAudioInput@@UAEPAXPBD@Z @ 606 NONAME ; void * QAudioInput::qt_metacast(char const *)
+ ?trUtf8@QMediaServiceProvider@@SA?AVQString@@PBD0@Z @ 607 NONAME ; class QString QMediaServiceProvider::trUtf8(char const *, char const *)
+ ?tr@QMediaPlaylistSourceControl@@SA?AVQString@@PBD0@Z @ 608 NONAME ; class QString QMediaPlaylistSourceControl::tr(char const *, char const *)
+ ?state@QMediaPlayer@@QBE?AW4State@1@XZ @ 609 NONAME ; enum QMediaPlayer::State QMediaPlayer::state(void) const
+ ?tr@QAudioEncoderControl@@SA?AVQString@@PBD0@Z @ 610 NONAME ; class QString QAudioEncoderControl::tr(char const *, char const *)
+ ??1QAudioFormat@@QAE@XZ @ 611 NONAME ; QAudioFormat::~QAudioFormat(void)
+ ?bind@QMediaObject@@UAE_NPAVQObject@@@Z @ 612 NONAME ; bool QMediaObject::bind(class QObject *)
+ ?metaDataChanged@QMetaDataReaderControl@@IAEXXZ @ 613 NONAME ; void QMetaDataReaderControl::metaDataChanged(void)
+ ?playlist@QMediaPlayer@@QBEPAVQMediaPlaylist@@XZ @ 614 NONAME ; class QMediaPlaylist * QMediaPlayer::playlist(void) const
+ ?trUtf8@QAudioInput@@SA?AVQString@@PBD0@Z @ 615 NONAME ; class QString QAudioInput::trUtf8(char const *, char const *)
+ ?metaObject@QAudioEncoderControl@@UBEPBUQMetaObject@@XZ @ 616 NONAME ; struct QMetaObject const * QAudioEncoderControl::metaObject(void) const
+ ?getStaticMetaObject@QAudioInput@@SAABUQMetaObject@@XZ @ 617 NONAME ; struct QMetaObject const & QAudioInput::getStaticMetaObject(void)
+ ?previousItem@QMediaPlaylistNavigator@@QBE?AVQMediaContent@@H@Z @ 618 NONAME ; class QMediaContent QMediaPlaylistNavigator::previousItem(int) const
+ ??0QMediaTimeInterval@@QAE@ABV0@@Z @ 619 NONAME ; QMediaTimeInterval::QMediaTimeInterval(class QMediaTimeInterval const &)
+ ?tr@QAudioEndpointSelector@@SA?AVQString@@PBD0@Z @ 620 NONAME ; class QString QAudioEndpointSelector::tr(char const *, char const *)
+ ?qt_metacall@QGraphicsVideoItem@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 621 NONAME ; int QGraphicsVideoItem::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?tr@QMetaDataReaderControl@@SA?AVQString@@PBD0H@Z @ 622 NONAME ; class QString QMetaDataReaderControl::tr(char const *, char const *, int)
+ ?mediaChanged@QMediaPlaylistProvider@@IAEXHH@Z @ 623 NONAME ; void QMediaPlaylistProvider::mediaChanged(int, int)
+ ?service@QMediaObject@@UBEPAVQMediaService@@XZ @ 624 NONAME ; class QMediaService * QMediaObject::service(void) const
+ ?mappedBytes@QVideoFrame@@QBEHXZ @ 625 NONAME ; int QVideoFrame::mappedBytes(void) const
+ ?tr@QMediaPlaylistIOPlugin@@SA?AVQString@@PBD0@Z @ 626 NONAME ; class QString QMediaPlaylistIOPlugin::tr(char const *, char const *)
+ ?removePropertyWatch@QMediaObject@@IAEXABVQByteArray@@@Z @ 627 NONAME ; void QMediaObject::removePropertyWatch(class QByteArray const &)
+ ?metaObject@QMediaControl@@UBEPBUQMetaObject@@XZ @ 628 NONAME ; struct QMetaObject const * QMediaControl::metaObject(void) const
+ ??1QMediaStreamsControl@@UAE@XZ @ 629 NONAME ; QMediaStreamsControl::~QMediaStreamsControl(void)
+ ?codec@QImageEncoderSettings@@QBE?AVQString@@XZ @ 630 NONAME ; class QString QImageEncoderSettings::codec(void) const
+ ?frequencyStep@QRadioTuner@@QBEHW4Band@1@@Z @ 631 NONAME ; int QRadioTuner::frequencyStep(enum QRadioTuner::Band) const
+ ??1QVideoRendererControl@@UAE@XZ @ 632 NONAME ; QVideoRendererControl::~QVideoRendererControl(void)
+ ?setNotifyInterval@QMediaObject@@QAEXH@Z @ 633 NONAME ; void QMediaObject::setNotifyInterval(int)
+ ?metaDataChanged@QMetaDataWriterControl@@IAEXXZ @ 634 NONAME ; void QMetaDataWriterControl::metaDataChanged(void)
+ ??_EQMetaDataReaderControl@@UAE@I@Z @ 635 NONAME ; QMetaDataReaderControl::~QMetaDataReaderControl(unsigned int)
+ ?surfaceFormatChanged@QAbstractVideoSurface@@IAEXABVQVideoSurfaceFormat@@@Z @ 636 NONAME ; void QAbstractVideoSurface::surfaceFormatChanged(class QVideoSurfaceFormat const &)
+ ?clear@QMediaTimeRange@@QAEXXZ @ 637 NONAME ; void QMediaTimeRange::clear(void)
+ ?setOffset@QGraphicsVideoItem@@QAEXABVQPointF@@@Z @ 638 NONAME ; void QGraphicsVideoItem::setOffset(class QPointF const &)
+ ??_EQAudioEncoderControl@@UAE@I@Z @ 639 NONAME ; QAudioEncoderControl::~QAudioEncoderControl(unsigned int)
+ ?qt_metacast@QLocalMediaPlaylistProvider@@UAEPAXPBD@Z @ 640 NONAME ; void * QLocalMediaPlaylistProvider::qt_metacast(char const *)
+ ?resizeEvent@QVideoWidget@@MAEXPAVQResizeEvent@@@Z @ 641 NONAME ; void QVideoWidget::resizeEvent(class QResizeEvent *)
+ ?isReadOnly@QLocalMediaPlaylistProvider@@UBE_NXZ @ 642 NONAME ; bool QLocalMediaPlaylistProvider::isReadOnly(void) const
+ ?d_func@QMediaPlayer@@AAEPAVQMediaPlayerPrivate@@XZ @ 643 NONAME ; class QMediaPlayerPrivate * QMediaPlayer::d_func(void)
+ ?elapsedTimeChanged@QMediaImageViewer@@IAEXH@Z @ 644 NONAME ; void QMediaImageViewer::elapsedTimeChanged(int)
+ ?isMapped@QVideoFrame@@QBE_NXZ @ 645 NONAME ; bool QVideoFrame::isMapped(void) const
+ ?tr@QAudioOutput@@SA?AVQString@@PBD0@Z @ 646 NONAME ; class QString QAudioOutput::tr(char const *, char const *)
+ ?metaDataWritableChanged@QMediaRecorder@@IAEX_N@Z @ 647 NONAME ; void QMediaRecorder::metaDataWritableChanged(bool)
+ ?loopsChanged@QSoundEffect@@IAEXXZ @ 648 NONAME ABSENT ; void QSoundEffect::loopsChanged(void)
+ ?trUtf8@QAbstractAudioInput@@SA?AVQString@@PBD0H@Z @ 649 NONAME ; class QString QAbstractAudioInput::trUtf8(char const *, char const *, int)
+ ?setDataSize@QMediaResource@@QAEX_J@Z @ 650 NONAME ; void QMediaResource::setDataSize(long long)
+ ?trUtf8@QAudioEndpointSelector@@SA?AVQString@@PBD0H@Z @ 651 NONAME ; class QString QAudioEndpointSelector::trUtf8(char const *, char const *, int)
+ ?setFieldType@QVideoFrame@@QAEXW4FieldType@1@@Z @ 652 NONAME ; void QVideoFrame::setFieldType(enum QVideoFrame::FieldType)
+ ?metaData@QMediaRecorder@@QBE?AVQVariant@@W4MetaData@QtMultimediaKit@@@Z @ 653 NONAME ; class QVariant QMediaRecorder::metaData(enum QtMultimediaKit::MetaData) const
+ ?audioDescription@QAudioCaptureSource@@QBE?AVQString@@ABV2@@Z @ 654 NONAME ; class QString QAudioCaptureSource::audioDescription(class QString const &) const
+ ?media@QLocalMediaPlaylistProvider@@UBE?AVQMediaContent@@H@Z @ 655 NONAME ; class QMediaContent QLocalMediaPlaylistProvider::media(int) const
+ ??0QVideoWidgetControl@@IAE@PAVQObject@@@Z @ 656 NONAME ; QVideoWidgetControl::QVideoWidgetControl(class QObject *)
+ ??1QImageEncoderSettings@@QAE@XZ @ 657 NONAME ; QImageEncoderSettings::~QImageEncoderSettings(void)
+ ?deviceName@QAudioDeviceInfo@@QBE?AVQString@@XZ @ 658 NONAME ; class QString QAudioDeviceInfo::deviceName(void) const
+ ?isAvailable@QAudioCaptureSource@@UBE_NXZ @ 659 NONAME ; bool QAudioCaptureSource::isAvailable(void) const
+ ?getStaticMetaObject@QAudioEndpointSelector@@SAABUQMetaObject@@XZ @ 660 NONAME ; struct QMetaObject const & QAudioEndpointSelector::getStaticMetaObject(void)
+ ??0QMediaObject@@IAE@PAVQObject@@PAVQMediaService@@@Z @ 661 NONAME ; QMediaObject::QMediaObject(class QObject *, class QMediaService *)
+ ?addTimeRange@QMediaTimeRange@@QAEXABV1@@Z @ 662 NONAME ; void QMediaTimeRange::addTimeRange(class QMediaTimeRange const &)
+ ?timerEvent@QMediaImageViewer@@MAEXPAVQTimerEvent@@@Z @ 663 NONAME ; void QMediaImageViewer::timerEvent(class QTimerEvent *)
+ ?getStaticMetaObject@QMediaPlaylistIOPlugin@@SAABUQMetaObject@@XZ @ 664 NONAME ; struct QMetaObject const & QMediaPlaylistIOPlugin::getStaticMetaObject(void)
+ ?metaObject@QLocalMediaPlaylistProvider@@UBEPBUQMetaObject@@XZ @ 665 NONAME ; struct QMetaObject const * QLocalMediaPlaylistProvider::metaObject(void) const
+ ?currentIndexChanged@QMediaPlaylist@@IAEXH@Z @ 666 NONAME ; void QMediaPlaylist::currentIndexChanged(int)
+ ?videoCodecDescription@QMediaRecorder@@QBE?AVQString@@ABV2@@Z @ 667 NONAME ; class QString QMediaRecorder::videoCodecDescription(class QString const &) const
+ ?trUtf8@QMediaImageViewer@@SA?AVQString@@PBD0H@Z @ 668 NONAME ; class QString QMediaImageViewer::trUtf8(char const *, char const *, int)
+ ?stop@QMediaImageViewer@@QAEXXZ @ 669 NONAME ; void QMediaImageViewer::stop(void)
+ ?metaObject@QMediaPlaylistSourceControl@@UBEPBUQMetaObject@@XZ @ 670 NONAME ; struct QMetaObject const * QMediaPlaylistSourceControl::metaObject(void) const
+ ?qt_metacall@QAudioInput@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 671 NONAME ; int QAudioInput::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?availableEndpointsChanged@QAudioEndpointSelector@@IAEXXZ @ 672 NONAME ; void QAudioEndpointSelector::availableEndpointsChanged(void)
+ ?isNull@QVideoEncoderSettings@@QBE_NXZ @ 673 NONAME ; bool QVideoEncoderSettings::isNull(void) const
+ ?qt_metacast@QMediaPlayerControl@@UAEPAXPBD@Z @ 674 NONAME ; void * QMediaPlayerControl::qt_metacast(char const *)
+ ?setMediaObject@QMediaPlaylist@@MAE_NPAVQMediaObject@@@Z @ 675 NONAME ; bool QMediaPlaylist::setMediaObject(class QMediaObject *)
+ ?supportedMimeTypes@QMediaPlayer@@SA?AVQStringList@@V?$QFlags@W4Flag@QMediaPlayer@@@@@Z @ 676 NONAME ; class QStringList QMediaPlayer::supportedMimeTypes(class QFlags<enum QMediaPlayer::Flag>)
+ ?source@QSoundEffect@@QBE?AVQUrl@@XZ @ 677 NONAME ; class QUrl QSoundEffect::source(void) const
+ ?addMedia@QMediaPlaylist@@QAE_NABVQMediaContent@@@Z @ 678 NONAME ; bool QMediaPlaylist::addMedia(class QMediaContent const &)
+ ?metaObject@QMediaPlaylistNavigator@@UBEPBUQMetaObject@@XZ @ 679 NONAME ; struct QMetaObject const * QMediaPlaylistNavigator::metaObject(void) const
+ ?size@QVideoFrame@@QBE?AVQSize@@XZ @ 680 NONAME ; class QSize QVideoFrame::size(void) const
+ ?tr@QMediaPlayer@@SA?AVQString@@PBD0H@Z @ 681 NONAME ; class QString QMediaPlayer::tr(char const *, char const *, int)
+ ?d_func@QAbstractVideoSurface@@AAEPAVQAbstractVideoSurfacePrivate@@XZ @ 682 NONAME ; class QAbstractVideoSurfacePrivate * QAbstractVideoSurface::d_func(void)
+ ?dataSize@QMediaResource@@QBE_JXZ @ 683 NONAME ; long long QMediaResource::dataSize(void) const
+ ?staticMetaObject@QRadioTunerControl@@2UQMetaObject@@B @ 684 NONAME ; struct QMetaObject const QRadioTunerControl::staticMetaObject
+ ?tr@QMediaPlaylistNavigator@@SA?AVQString@@PBD0@Z @ 685 NONAME ; class QString QMediaPlaylistNavigator::tr(char const *, char const *)
+ ?tr@QMediaService@@SA?AVQString@@PBD0H@Z @ 686 NONAME ; class QString QMediaService::tr(char const *, char const *, int)
+ ?resolution@QVideoEncoderSettings@@QBE?AVQSize@@XZ @ 687 NONAME ; class QSize QVideoEncoderSettings::resolution(void) const
+ ?setContrast@QVideoWidget@@QAEXH@Z @ 688 NONAME ; void QVideoWidget::setContrast(int)
+ ??1QMediaServiceSupportedFormatsInterface@@UAE@XZ @ 689 NONAME ; QMediaServiceSupportedFormatsInterface::~QMediaServiceSupportedFormatsInterface(void)
+ ?activeStreamsChanged@QMediaStreamsControl@@IAEXXZ @ 690 NONAME ; void QMediaStreamsControl::activeStreamsChanged(void)
+ ?aspectRatioMode@QVideoWidget@@QBE?AW4AspectRatioMode@Qt@@XZ @ 691 NONAME ; enum Qt::AspectRatioMode QVideoWidget::aspectRatioMode(void) const
+ ??1QMediaRecorder@@UAE@XZ @ 692 NONAME ; QMediaRecorder::~QMediaRecorder(void)
+ ?setSampleType@QAudioFormat@@QAEXW4SampleType@1@@Z @ 693 NONAME ; void QAudioFormat::setSampleType(enum QAudioFormat::SampleType)
+ ?next@QMediaPlaylistNavigator@@QAEXXZ @ 694 NONAME ; void QMediaPlaylistNavigator::next(void)
+ ?setMedia@QMediaPlayer@@QAEXABVQMediaContent@@PAVQIODevice@@@Z @ 695 NONAME ; void QMediaPlayer::setMedia(class QMediaContent const &, class QIODevice *)
+ ??_EQMediaPlaylistControl@@UAE@I@Z @ 696 NONAME ; QMediaPlaylistControl::~QMediaPlaylistControl(unsigned int)
+ ??1QMetaDataReaderControl@@UAE@XZ @ 697 NONAME ; QMetaDataReaderControl::~QMetaDataReaderControl(void)
+ ?qt_metacall@QVideoEncoderControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 698 NONAME ; int QVideoEncoderControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?hasSupport@QMediaServiceProvider@@UBE?AW4SupportEstimate@QtMultimediaKit@@ABVQByteArray@@ABVQString@@ABVQStringList@@H@Z @ 699 NONAME ; enum QtMultimediaKit::SupportEstimate QMediaServiceProvider::hasSupport(class QByteArray const &, class QString const &, class QStringList const &, int) const
+ ??_EQAudioOutput@@UAE@I@Z @ 700 NONAME ; QAudioOutput::~QAudioOutput(unsigned int)
+ ?mediaInserted@QMediaPlaylist@@IAEXHH@Z @ 701 NONAME ; void QMediaPlaylist::mediaInserted(int, int)
+ ?currentIndex@QMediaPlaylistNavigator@@QBEHXZ @ 702 NONAME ; int QMediaPlaylistNavigator::currentIndex(void) const
+ ?volumeChanged@QSoundEffect@@IAEXXZ @ 703 NONAME ; void QSoundEffect::volumeChanged(void)
+ ?duration@QMediaRecorder@@QBE_JXZ @ 704 NONAME ; long long QMediaRecorder::duration(void) const
+ ??0QMediaContent@@QAE@XZ @ 705 NONAME ; QMediaContent::QMediaContent(void)
+ ?mapMode@QMemoryVideoBuffer@@UBE?AW4MapMode@QAbstractVideoBuffer@@XZ @ 706 NONAME ; enum QAbstractVideoBuffer::MapMode QMemoryVideoBuffer::mapMode(void) const
+ ?setProperty@QVideoSurfaceFormat@@QAEXPBDABVQVariant@@@Z @ 707 NONAME ; void QVideoSurfaceFormat::setProperty(char const *, class QVariant const &)
+ ?metaObject@QMediaPlayer@@UBEPBUQMetaObject@@XZ @ 708 NONAME ; struct QMetaObject const * QMediaPlayer::metaObject(void) const
+ ?qt_metacall@QAudioOutput@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 709 NONAME ; int QAudioOutput::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?fieldType@QVideoFrame@@QBE?AW4FieldType@1@XZ @ 710 NONAME ; enum QVideoFrame::FieldType QVideoFrame::fieldType(void) const
+ ?language@QMediaResource@@QBE?AVQString@@XZ @ 711 NONAME ; class QString QMediaResource::language(void) const
+ ?trUtf8@QLocalMediaPlaylistProvider@@SA?AVQString@@PBD0@Z @ 712 NONAME ; class QString QLocalMediaPlaylistProvider::trUtf8(char const *, char const *)
+ ?isMetaDataAvailable@QMediaRecorder@@QBE_NXZ @ 713 NONAME ; bool QMediaRecorder::isMetaDataAvailable(void) const
+ ??1QGraphicsVideoItem@@UAE@XZ @ 714 NONAME ; QGraphicsVideoItem::~QGraphicsVideoItem(void)
+ ?setByteOrder@QAudioFormat@@QAEXW4Endian@1@@Z @ 715 NONAME ; void QAudioFormat::setByteOrder(enum QAudioFormat::Endian)
+ ?tr@QVideoDeviceControl@@SA?AVQString@@PBD0@Z @ 716 NONAME ; class QString QVideoDeviceControl::tr(char const *, char const *)
+ ??0QVideoDeviceControl@@IAE@PAVQObject@@@Z @ 717 NONAME ; QVideoDeviceControl::QVideoDeviceControl(class QObject *)
+ ?frequency@QRadioTuner@@QBEHXZ @ 718 NONAME ; int QRadioTuner::frequency(void) const
+ ?qt_metacast@QAbstractAudioDeviceInfo@@UAEPAXPBD@Z @ 719 NONAME ; void * QAbstractAudioDeviceInfo::qt_metacast(char const *)
+ ?trUtf8@QMediaContainerControl@@SA?AVQString@@PBD0@Z @ 720 NONAME ; class QString QMediaContainerControl::trUtf8(char const *, char const *)
+ ?tr@QMediaPlaylistProvider@@SA?AVQString@@PBD0@Z @ 721 NONAME ; class QString QMediaPlaylistProvider::tr(char const *, char const *)
+ ?metaObject@QMetaDataWriterControl@@UBEPBUQMetaObject@@XZ @ 722 NONAME ; struct QMetaObject const * QMetaDataWriterControl::metaObject(void) const
+ ?metaObject@QVideoDeviceControl@@UBEPBUQMetaObject@@XZ @ 723 NONAME ; struct QMetaObject const * QVideoDeviceControl::metaObject(void) const
+ ?removeMedia@QMediaPlaylist@@QAE_NH@Z @ 724 NONAME ; bool QMediaPlaylist::removeMedia(int)
+ ??1QMetaDataWriterControl@@UAE@XZ @ 725 NONAME ; QMetaDataWriterControl::~QMetaDataWriterControl(void)
+ ?trUtf8@QImageEncoderControl@@SA?AVQString@@PBD0@Z @ 726 NONAME ; class QString QImageEncoderControl::trUtf8(char const *, char const *)
+ ?d_func@QMediaObject@@AAEPAVQMediaObjectPrivate@@XZ @ 727 NONAME ; class QMediaObjectPrivate * QMediaObject::d_func(void)
+ ?getStaticMetaObject@QVideoWindowControl@@SAABUQMetaObject@@XZ @ 728 NONAME ; struct QMetaObject const & QVideoWindowControl::getStaticMetaObject(void)
+ ??0QAudioEndpointSelector@@IAE@PAVQObject@@@Z @ 729 NONAME ; QAudioEndpointSelector::QAudioEndpointSelector(class QObject *)
+ ?mediaStatus@QMediaImageViewer@@QBE?AW4MediaStatus@1@XZ @ 730 NONAME ; enum QMediaImageViewer::MediaStatus QMediaImageViewer::mediaStatus(void) const
+ ?tr@QVideoWidgetControl@@SA?AVQString@@PBD0@Z @ 731 NONAME ; class QString QVideoWidgetControl::tr(char const *, char const *)
+ ?trUtf8@QMediaRecorderControl@@SA?AVQString@@PBD0@Z @ 732 NONAME ; class QString QMediaRecorderControl::trUtf8(char const *, char const *)
+ ?getStaticMetaObject@QAudioOutput@@SAABUQMetaObject@@XZ @ 733 NONAME ; struct QMetaObject const & QAudioOutput::getStaticMetaObject(void)
+ ?qt_metacall@QMediaPlaylistNavigator@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 734 NONAME ; int QMediaPlaylistNavigator::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?metaObject@QMediaPlaylistControl@@UBEPBUQMetaObject@@XZ @ 735 NONAME ; struct QMetaObject const * QMediaPlaylistControl::metaObject(void) const
+ ?normalized@QMediaTimeInterval@@QBE?AV1@XZ @ 736 NONAME ; class QMediaTimeInterval QMediaTimeInterval::normalized(void) const
+ ?durationChanged@QMediaPlayerControl@@IAEX_J@Z @ 737 NONAME ; void QMediaPlayerControl::durationChanged(long long)
+ ?d_func@QImageVideoBuffer@@AAEPAVQImageVideoBufferPrivate@@XZ @ 738 NONAME ; class QImageVideoBufferPrivate * QImageVideoBuffer::d_func(void)
+ ?stateChanged@QAbstractAudioOutput@@IAEXW4State@QAudio@@@Z @ 739 NONAME ; void QAbstractAudioOutput::stateChanged(enum QAudio::State)
+ ?trUtf8@QMediaContainerControl@@SA?AVQString@@PBD0H@Z @ 740 NONAME ; class QString QMediaContainerControl::trUtf8(char const *, char const *, int)
+ ?byteOrder@QAudioFormat@@QBE?AW4Endian@1@XZ @ 741 NONAME ; enum QAudioFormat::Endian QAudioFormat::byteOrder(void) const
+ ?qt_metacast@QAbstractAudioInput@@UAEPAXPBD@Z @ 742 NONAME ; void * QAbstractAudioInput::qt_metacast(char const *)
+ ?mediaChanged@QMediaImageViewer@@IAEXABVQMediaContent@@@Z @ 743 NONAME ; void QMediaImageViewer::mediaChanged(class QMediaContent const &)
+ ?errorString@QRadioTuner@@QBE?AVQString@@XZ @ 744 NONAME ; class QString QRadioTuner::errorString(void) const
+ ?d_func@QMediaPlaylistNavigator@@ABEPBVQMediaPlaylistNavigatorPrivate@@XZ @ 745 NONAME ; class QMediaPlaylistNavigatorPrivate const * QMediaPlaylistNavigator::d_func(void) const
+ ?error@QAbstractVideoSurface@@QBE?AW4Error@1@XZ @ 746 NONAME ; enum QAbstractVideoSurface::Error QAbstractVideoSurface::error(void) const
+ ?contrastChanged@QVideoWidgetControl@@IAEXH@Z @ 747 NONAME ; void QVideoWidgetControl::contrastChanged(int)
+ ?d_func@QAbstractVideoBuffer@@ABEPBVQAbstractVideoBufferPrivate@@XZ @ 748 NONAME ; class QAbstractVideoBufferPrivate const * QAbstractVideoBuffer::d_func(void) const
+ ?setScanLineDirection@QVideoSurfaceFormat@@QAEXW4Direction@1@@Z @ 749 NONAME ; void QVideoSurfaceFormat::setScanLineDirection(enum QVideoSurfaceFormat::Direction)
+ ??0QVideoRendererControl@@IAE@PAVQObject@@@Z @ 750 NONAME ; QVideoRendererControl::QVideoRendererControl(class QObject *)
+ ?trUtf8@QMediaObject@@SA?AVQString@@PBD0@Z @ 751 NONAME ; class QString QMediaObject::trUtf8(char const *, char const *)
+ ?tr@QMediaImageViewer@@SA?AVQString@@PBD0H@Z @ 752 NONAME ; class QString QMediaImageViewer::tr(char const *, char const *, int)
+ ??1QAudioDeviceInfo@@QAE@XZ @ 753 NONAME ; QAudioDeviceInfo::~QAudioDeviceInfo(void)
+ ?videoSettings@QMediaRecorder@@QBE?AVQVideoEncoderSettings@@XZ @ 754 NONAME ; class QVideoEncoderSettings QMediaRecorder::videoSettings(void) const
+ ?nearestFormat@QAudioDeviceInfo@@QBE?AVQAudioFormat@@ABV2@@Z @ 755 NONAME ; class QAudioFormat QAudioDeviceInfo::nearestFormat(class QAudioFormat const &) const
+ ?playbackModeChanged@QMediaPlaylist@@IAEXW4PlaybackMode@1@@Z @ 756 NONAME ; void QMediaPlaylist::playbackModeChanged(enum QMediaPlaylist::PlaybackMode)
+ ?setMediaObject@QVideoWidget@@MAE_NPAVQMediaObject@@@Z @ 757 NONAME ; bool QVideoWidget::setMediaObject(class QMediaObject *)
+ ?isFormatSupported@QAudioDeviceInfo@@QBE_NABVQAudioFormat@@@Z @ 758 NONAME ; bool QAudioDeviceInfo::isFormatSupported(class QAudioFormat const &) const
+ ??1QMediaPlaylistProvider@@UAE@XZ @ 759 NONAME ; QMediaPlaylistProvider::~QMediaPlaylistProvider(void)
+ ?qt_metacall@QMediaImageViewer@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 760 NONAME ; int QMediaImageViewer::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?tr@QMediaPlaylistProvider@@SA?AVQString@@PBD0H@Z @ 761 NONAME ; class QString QMediaPlaylistProvider::tr(char const *, char const *, int)
+ ?tr@QMediaPlaylistNavigator@@SA?AVQString@@PBD0H@Z @ 762 NONAME ; class QString QMediaPlaylistNavigator::tr(char const *, char const *, int)
+ ?isNull@QAudioDeviceInfo@@QBE_NXZ @ 763 NONAME ; bool QAudioDeviceInfo::isNull(void) const
+ ?supportedByteOrders@QAudioDeviceInfo@@QBE?AV?$QList@W4Endian@QAudioFormat@@@@XZ @ 764 NONAME ; class QList<enum QAudioFormat::Endian> QAudioDeviceInfo::supportedByteOrders(void) const
+ ?showEvent@QVideoWidget@@MAEXPAVQShowEvent@@@Z @ 765 NONAME ; void QVideoWidget::showEvent(class QShowEvent *)
+ ?codecs@QMediaServiceProviderHint@@QBE?AVQStringList@@XZ @ 766 NONAME ; class QStringList QMediaServiceProviderHint::codecs(void) const
+ ?error@QMediaPlayer@@QBE?AW4Error@1@XZ @ 767 NONAME ; enum QMediaPlayer::Error QMediaPlayer::error(void) const
+ ?insertMedia@QLocalMediaPlaylistProvider@@UAE_NHABV?$QList@VQMediaContent@@@@@Z @ 768 NONAME ; bool QLocalMediaPlaylistProvider::insertMedia(int, class QList<class QMediaContent> const &)
+ ?mediaStream@QMediaPlayer@@QBEPBVQIODevice@@XZ @ 769 NONAME ; class QIODevice const * QMediaPlayer::mediaStream(void) const
+ ??0QMediaPlaylistProvider@@IAE@AAVQMediaPlaylistProviderPrivate@@PAVQObject@@@Z @ 770 NONAME ; QMediaPlaylistProvider::QMediaPlaylistProvider(class QMediaPlaylistProviderPrivate &, class QObject *)
+ ?audioInputs@QAudioCaptureSource@@QBE?AV?$QList@VQString@@@@XZ @ 771 NONAME ; class QList<class QString> QAudioCaptureSource::audioInputs(void) const
+ ?setResolution@QImageEncoderSettings@@QAEXABVQSize@@@Z @ 772 NONAME ; void QImageEncoderSettings::setResolution(class QSize const &)
+ ??0QImageEncoderSettings@@QAE@ABV0@@Z @ 773 NONAME ; QImageEncoderSettings::QImageEncoderSettings(class QImageEncoderSettings const &)
+ ?state@QMediaImageViewer@@QBE?AW4State@1@XZ @ 774 NONAME ; enum QMediaImageViewer::State QMediaImageViewer::state(void) const
+ ?encodingMode@QVideoEncoderSettings@@QBE?AW4EncodingMode@QtMultimediaKit@@XZ @ 775 NONAME ; enum QtMultimediaKit::EncodingMode QVideoEncoderSettings::encodingMode(void) const
+ ?errorChanged@QAbstractAudioOutput@@IAEXW4Error@QAudio@@@Z @ 776 NONAME ; void QAbstractAudioOutput::errorChanged(enum QAudio::Error)
+ ?nearestFormat@QAbstractVideoSurface@@UBE?AVQVideoSurfaceFormat@@ABV2@@Z @ 777 NONAME ; class QVideoSurfaceFormat QAbstractVideoSurface::nearestFormat(class QVideoSurfaceFormat const &) const
+ ?setPixelAspectRatio@QVideoSurfaceFormat@@QAEXHH@Z @ 778 NONAME ; void QVideoSurfaceFormat::setPixelAspectRatio(int, int)
+ ?getStaticMetaObject@QAbstractAudioDeviceInfo@@SAABUQMetaObject@@XZ @ 779 NONAME ; struct QMetaObject const & QAbstractAudioDeviceInfo::getStaticMetaObject(void)
+ ?clear@QMediaPlaylist@@QAE_NXZ @ 780 NONAME ; bool QMediaPlaylist::clear(void)
+ ?surroundingItemsChanged@QMediaPlaylistNavigator@@IAEXXZ @ 781 NONAME ; void QMediaPlaylistNavigator::surroundingItemsChanged(void)
+ ?availableDevices@QAudioDeviceInfo@@SA?AV?$QList@VQAudioDeviceInfo@@@@W4Mode@QAudio@@@Z @ 782 NONAME ; class QList<class QAudioDeviceInfo> QAudioDeviceInfo::availableDevices(enum QAudio::Mode)
+ ?d_func@QMediaService@@ABEPBVQMediaServicePrivate@@XZ @ 783 NONAME ; class QMediaServicePrivate const * QMediaService::d_func(void) const
+ ?getStaticMetaObject@QMediaPlaylistProvider@@SAABUQMetaObject@@XZ @ 784 NONAME ; struct QMetaObject const & QMediaPlaylistProvider::getStaticMetaObject(void)
+ ?availablePlaybackRangesChanged@QMediaPlayerControl@@IAEXABVQMediaTimeRange@@@Z @ 785 NONAME ; void QMediaPlayerControl::availablePlaybackRangesChanged(class QMediaTimeRange const &)
+ ??1QImageVideoBuffer@@UAE@XZ @ 786 NONAME ; QImageVideoBuffer::~QImageVideoBuffer(void)
+ ?notifyInterval@QAudioOutput@@QBEHXZ @ 787 NONAME ; int QAudioOutput::notifyInterval(void) const
+ ??1QAbstractAudioDeviceInfo@@UAE@XZ @ 788 NONAME ; QAbstractAudioDeviceInfo::~QAbstractAudioDeviceInfo(void)
+ ??1QVideoEncoderSettings@@QAE@XZ @ 789 NONAME ; QVideoEncoderSettings::~QVideoEncoderSettings(void)
+ ?clear@QLocalMediaPlaylistProvider@@UAE_NXZ @ 790 NONAME ; bool QLocalMediaPlaylistProvider::clear(void)
+ ?setSampleRate@QMediaResource@@QAEXH@Z @ 791 NONAME ; void QMediaResource::setSampleRate(int)
+ ?setBand@QRadioTuner@@QAEXW4Band@1@@Z @ 792 NONAME ; void QRadioTuner::setBand(enum QRadioTuner::Band)
+ ?mediaChanged@QMediaPlayerControl@@IAEXABVQMediaContent@@@Z @ 793 NONAME ; void QMediaPlayerControl::mediaChanged(class QMediaContent const &)
+ ?removeMedia@QMediaPlaylist@@QAE_NHH@Z @ 794 NONAME ; bool QMediaPlaylist::removeMedia(int, int)
+ ?setMetaData@QMediaRecorder@@QAEXW4MetaData@QtMultimediaKit@@ABVQVariant@@@Z @ 795 NONAME ; void QMediaRecorder::setMetaData(enum QtMultimediaKit::MetaData, class QVariant const &)
+ ?d_func@QGraphicsVideoItem@@ABEPBVQGraphicsVideoItemPrivate@@XZ @ 796 NONAME ; class QGraphicsVideoItemPrivate const * QGraphicsVideoItem::d_func(void) const
+ ?setPlaylist@QMediaImageViewer@@QAEXPAVQMediaPlaylist@@@Z @ 797 NONAME ; void QMediaImageViewer::setPlaylist(class QMediaPlaylist *)
+ ?itemChange@QGraphicsVideoItem@@MAE?AVQVariant@@W4GraphicsItemChange@QGraphicsItem@@ABV2@@Z @ 798 NONAME ; class QVariant QGraphicsVideoItem::itemChange(enum QGraphicsItem::GraphicsItemChange, class QVariant const &)
+ ?stateChanged@QRadioTuner@@IAEXW4State@1@@Z @ 799 NONAME ; void QRadioTuner::stateChanged(enum QRadioTuner::State)
+ ?getStaticMetaObject@QMediaControl@@SAABUQMetaObject@@XZ @ 800 NONAME ; struct QMetaObject const & QMediaControl::getStaticMetaObject(void)
+ ?qt_metacall@QMediaService@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 801 NONAME ; int QMediaService::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?bitRate@QAudioEncoderSettings@@QBEHXZ @ 802 NONAME ; int QAudioEncoderSettings::bitRate(void) const
+ ?mediaObject@QMediaRecorder@@UBEPAVQMediaObject@@XZ @ 803 NONAME ; class QMediaObject * QMediaRecorder::mediaObject(void) const
+ ?trUtf8@QMediaStreamsControl@@SA?AVQString@@PBD0@Z @ 804 NONAME ; class QString QMediaStreamsControl::trUtf8(char const *, char const *)
+ ??0QMediaResource@@QAE@ABV0@@Z @ 805 NONAME ; QMediaResource::QMediaResource(class QMediaResource const &)
+ ?d_func@QMediaPlaylistNavigator@@AAEPAVQMediaPlaylistNavigatorPrivate@@XZ @ 806 NONAME ; class QMediaPlaylistNavigatorPrivate * QMediaPlaylistNavigator::d_func(void)
+ ?save@QMediaPlaylistProvider@@UAE_NABVQUrl@@PBD@Z @ 807 NONAME ; bool QMediaPlaylistProvider::save(class QUrl const &, char const *)
+ ?frequencyRange@QRadioTuner@@QBE?AU?$QPair@HH@@W4Band@1@@Z @ 808 NONAME ; struct QPair<int, int> QRadioTuner::frequencyRange(enum QRadioTuner::Band) const
+ ?setResolution@QMediaResource@@QAEXABVQSize@@@Z @ 809 NONAME ; void QMediaResource::setResolution(class QSize const &)
+ ??1QAudioCaptureSource@@UAE@XZ @ 810 NONAME ; QAudioCaptureSource::~QAudioCaptureSource(void)
+ ?positionChanged@QMediaPlayer@@IAEX_J@Z @ 811 NONAME ; void QMediaPlayer::positionChanged(long long)
+ ?qt_metacall@QAbstractAudioOutput@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 812 NONAME ; int QAbstractAudioOutput::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??0QAudioOutput@@QAE@ABVQAudioDeviceInfo@@ABVQAudioFormat@@PAVQObject@@@Z @ 813 NONAME ; QAudioOutput::QAudioOutput(class QAudioDeviceInfo const &, class QAudioFormat const &, class QObject *)
+ ?staticMetaObject@QMediaRecorder@@2UQMetaObject@@B @ 814 NONAME ; struct QMetaObject const QMediaRecorder::staticMetaObject
+ ?setMuted@QRadioTuner@@QAEX_N@Z @ 815 NONAME ; void QRadioTuner::setMuted(bool)
+ ?getStaticMetaObject@QMediaRecorder@@SAABUQMetaObject@@XZ @ 816 NONAME ; struct QMetaObject const & QMediaRecorder::getStaticMetaObject(void)
+ ?streamsChanged@QMediaStreamsControl@@IAEXXZ @ 817 NONAME ; void QMediaStreamsControl::streamsChanged(void)
+ ??0QMediaServiceProviderHint@@QAE@V?$QFlags@W4Feature@QMediaServiceProviderHint@@@@@Z @ 818 NONAME ; QMediaServiceProviderHint::QMediaServiceProviderHint(class QFlags<enum QMediaServiceProviderHint::Feature>)
+ ?mediaStatusChanged@QMediaPlayer@@IAEXW4MediaStatus@1@@Z @ 819 NONAME ; void QMediaPlayer::mediaStatusChanged(enum QMediaPlayer::MediaStatus)
+ ?trUtf8@QMediaPlaylistIOPlugin@@SA?AVQString@@PBD0H@Z @ 820 NONAME ; class QString QMediaPlaylistIOPlugin::trUtf8(char const *, char const *, int)
+ ?tr@QVideoWidget@@SA?AVQString@@PBD0H@Z @ 821 NONAME ; class QString QVideoWidget::tr(char const *, char const *, int)
+ ?nextIndex@QMediaPlaylist@@QBEHH@Z @ 822 NONAME ; int QMediaPlaylist::nextIndex(int) const
+ ??0QMediaService@@IAE@PAVQObject@@@Z @ 823 NONAME ; QMediaService::QMediaService(class QObject *)
+ ?qt_metacall@QMediaPlayer@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 824 NONAME ; int QMediaPlayer::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??4QAudioEncoderSettings@@QAEAAV0@ABV0@@Z @ 825 NONAME ; class QAudioEncoderSettings & QAudioEncoderSettings::operator=(class QAudioEncoderSettings const &)
+ ?staticMetaObject@QAbstractVideoSurface@@2UQMetaObject@@B @ 826 NONAME ; struct QMetaObject const QAbstractVideoSurface::staticMetaObject
+ ?trUtf8@QAbstractVideoSurface@@SA?AVQString@@PBD0@Z @ 827 NONAME ; class QString QAbstractVideoSurface::trUtf8(char const *, char const *)
+ ??_EQMediaStreamsControl@@UAE@I@Z @ 828 NONAME ; QMediaStreamsControl::~QMediaStreamsControl(unsigned int)
+ ?playbackModeChanged@QMediaPlaylistNavigator@@IAEXW4PlaybackMode@QMediaPlaylist@@@Z @ 829 NONAME ; void QMediaPlaylistNavigator::playbackModeChanged(enum QMediaPlaylist::PlaybackMode)
+ ?staticMetaObject@QAudioCaptureSource@@2UQMetaObject@@B @ 830 NONAME ; struct QMetaObject const QAudioCaptureSource::staticMetaObject
+ ?staticMetaObject@QMediaContainerControl@@2UQMetaObject@@B @ 831 NONAME ; struct QMetaObject const QMediaContainerControl::staticMetaObject
+ ?trUtf8@QAbstractAudioOutput@@SA?AVQString@@PBD0@Z @ 832 NONAME ; class QString QAbstractAudioOutput::trUtf8(char const *, char const *)
+ ?sourceChanged@QSoundEffect@@IAEXXZ @ 833 NONAME ; void QSoundEffect::sourceChanged(void)
+ ??9@YA_NABVQMediaTimeRange@@0@Z @ 834 NONAME ; bool operator!=(class QMediaTimeRange const &, class QMediaTimeRange const &)
+ ?availableAudioInputsChanged@QAudioCaptureSource@@IAEXXZ @ 835 NONAME ; void QAudioCaptureSource::availableAudioInputsChanged(void)
+ ??_EQAbstractAudioDeviceInfo@@UAE@I@Z @ 836 NONAME ; QAbstractAudioDeviceInfo::~QAbstractAudioDeviceInfo(unsigned int)
+ ?load@QMediaPlaylist@@QAEXPAVQIODevice@@PBD@Z @ 837 NONAME ; void QMediaPlaylist::load(class QIODevice *, char const *)
+ ?currentMediaChanged@QMediaPlaylistControl@@IAEXABVQMediaContent@@@Z @ 838 NONAME ; void QMediaPlaylistControl::currentMediaChanged(class QMediaContent const &)
+ ?setSampleSize@QAudioFormat@@QAEXH@Z @ 839 NONAME ; void QAudioFormat::setSampleSize(int)
+ ?isReadOnly@QMediaPlaylist@@QBE_NXZ @ 840 NONAME ; bool QMediaPlaylist::isReadOnly(void) const
+ ?supportedFrameRates@QMediaRecorder@@QBE?AV?$QList@M@@ABVQVideoEncoderSettings@@PA_N@Z @ 841 NONAME ; class QList<float> QMediaRecorder::supportedFrameRates(class QVideoEncoderSettings const &, bool *) const
+ ?mediaObject@QMediaPlaylist@@UBEPAVQMediaObject@@XZ @ 842 NONAME ; class QMediaObject * QMediaPlaylist::mediaObject(void) const
+ ?start@QRadioTuner@@QAEXXZ @ 843 NONAME ; void QRadioTuner::start(void)
+ ?play@QMediaPlayer@@QAEXXZ @ 844 NONAME ; void QMediaPlayer::play(void)
+ ??1QAudioEndpointSelector@@UAE@XZ @ 845 NONAME ; QAudioEndpointSelector::~QAudioEndpointSelector(void)
+ ?mode@QAudioDeviceInfo@@ABE?AW4Mode@QAudio@@XZ @ 846 NONAME ; enum QAudio::Mode QAudioDeviceInfo::mode(void) const
+ ?trUtf8@QVideoWidget@@SA?AVQString@@PBD0@Z @ 847 NONAME ; class QString QVideoWidget::trUtf8(char const *, char const *)
+ ?trUtf8@QAbstractAudioDeviceInfo@@SA?AVQString@@PBD0H@Z @ 848 NONAME ; class QString QAbstractAudioDeviceInfo::trUtf8(char const *, char const *, int)
+ ?stereoStatusChanged@QRadioTunerControl@@IAEX_N@Z @ 849 NONAME ; void QRadioTunerControl::stereoStatusChanged(bool)
+ ??4QMediaResource@@QAEAAV0@ABV0@@Z @ 850 NONAME ; class QMediaResource & QMediaResource::operator=(class QMediaResource const &)
+ ?d_func@QImageVideoBuffer@@ABEPBVQImageVideoBufferPrivate@@XZ @ 851 NONAME ; class QImageVideoBufferPrivate const * QImageVideoBuffer::d_func(void) const
+ ?qt_metacast@QAudioCaptureSource@@UAEPAXPBD@Z @ 852 NONAME ; void * QAudioCaptureSource::qt_metacast(char const *)
+ ?metaObject@QVideoWidget@@UBEPBUQMetaObject@@XZ @ 853 NONAME ; struct QMetaObject const * QVideoWidget::metaObject(void) const
+ ?defaultAudioInput@QAudioCaptureSource@@QBE?AVQString@@XZ @ 854 NONAME ; class QString QAudioCaptureSource::defaultAudioInput(void) const
+ ??0QAbstractVideoSurface@@QAE@PAVQObject@@@Z @ 855 NONAME ; QAbstractVideoSurface::QAbstractVideoSurface(class QObject *)
+ ?trUtf8@QImageEncoderControl@@SA?AVQString@@PBD0H@Z @ 856 NONAME ; class QString QImageEncoderControl::trUtf8(char const *, char const *, int)
+ ??1QMediaPlaylistWriter@@UAE@XZ @ 857 NONAME ; QMediaPlaylistWriter::~QMediaPlaylistWriter(void)
+ ?position@QMediaPlayer@@QBE_JXZ @ 858 NONAME ; long long QMediaPlayer::position(void) const
+ ?staticMetaObject@QAudioSystemPlugin@@2UQMetaObject@@B @ 859 NONAME ; struct QMetaObject const QAudioSystemPlugin::staticMetaObject
+ ??_EQMediaPlaylistIOInterface@@UAE@I@Z @ 860 NONAME ; QMediaPlaylistIOInterface::~QMediaPlaylistIOInterface(unsigned int)
+ ??_EQVideoWidget@@UAE@I@Z @ 861 NONAME ; QVideoWidget::~QVideoWidget(unsigned int)
+ ?contains@QMediaTimeInterval@@QBE_N_J@Z @ 862 NONAME ; bool QMediaTimeInterval::contains(long long) const
+ ?errorChanged@QAbstractAudioInput@@IAEXW4Error@QAudio@@@Z @ 863 NONAME ; void QAbstractAudioInput::errorChanged(enum QAudio::Error)
+ ??_EQMediaServiceSupportedDevicesInterface@@UAE@I@Z @ 864 NONAME ; QMediaServiceSupportedDevicesInterface::~QMediaServiceSupportedDevicesInterface(unsigned int)
+ ?brightnessChanged@QVideoWidget@@IAEXH@Z @ 865 NONAME ; void QVideoWidget::brightnessChanged(int)
+ ??_EQMediaPlaylistProvider@@UAE@I@Z @ 866 NONAME ; QMediaPlaylistProvider::~QMediaPlaylistProvider(unsigned int)
+ ?setResolution@QVideoEncoderSettings@@QAEXHH@Z @ 867 NONAME ; void QVideoEncoderSettings::setResolution(int, int)
+ ?trUtf8@QMediaControl@@SA?AVQString@@PBD0@Z @ 868 NONAME ; class QString QMediaControl::trUtf8(char const *, char const *)
+ ?supportedSampleRates@QAudioDeviceInfo@@QBE?AV?$QList@H@@XZ @ 869 NONAME ; class QList<int> QAudioDeviceInfo::supportedSampleRates(void) const
+ ??_EQMediaObject@@UAE@I@Z @ 870 NONAME ; QMediaObject::~QMediaObject(unsigned int)
+ ?trUtf8@QSoundEffect@@SA?AVQString@@PBD0@Z @ 871 NONAME ; class QString QSoundEffect::trUtf8(char const *, char const *)
+ ?qt_metacast@QGraphicsVideoItem@@UAEPAXPBD@Z @ 872 NONAME ; void * QGraphicsVideoItem::qt_metacast(char const *)
+ ??0QVideoFrame@@QAE@ABV0@@Z @ 873 NONAME ; QVideoFrame::QVideoFrame(class QVideoFrame const &)
+ ?tr@QRadioTuner@@SA?AVQString@@PBD0H@Z @ 874 NONAME ; class QString QRadioTuner::tr(char const *, char const *, int)
+ ?notifyIntervalChanged@QMediaObject@@IAEXH@Z @ 875 NONAME ; void QMediaObject::notifyIntervalChanged(int)
+ ?setMedia@QMediaImageViewer@@QAEXABVQMediaContent@@@Z @ 876 NONAME ; void QMediaImageViewer::setMedia(class QMediaContent const &)
+ ?tr@QMediaStreamsControl@@SA?AVQString@@PBD0H@Z @ 877 NONAME ; class QString QMediaStreamsControl::tr(char const *, char const *, int)
+ ?tr@QAudioOutput@@SA?AVQString@@PBD0H@Z @ 878 NONAME ; class QString QAudioOutput::tr(char const *, char const *, int)
+ ??YQMediaTimeRange@@QAEAAV0@ABV0@@Z @ 879 NONAME ; class QMediaTimeRange & QMediaTimeRange::operator+=(class QMediaTimeRange const &)
+ ?hasSupport@QMediaPlayer@@SA?AW4SupportEstimate@QtMultimediaKit@@ABVQString@@ABVQStringList@@V?$QFlags@W4Flag@QMediaPlayer@@@@@Z @ 880 NONAME ; enum QtMultimediaKit::SupportEstimate QMediaPlayer::hasSupport(class QString const &, class QStringList const &, class QFlags<enum QMediaPlayer::Flag>)
+ ?qt_metacast@QAudioSystemPlugin@@UAEPAXPBD@Z @ 881 NONAME ; void * QAudioSystemPlugin::qt_metacast(char const *)
+ ?setVideoOutput@QMediaPlayer@@QAEXPAVQVideoWidget@@@Z @ 882 NONAME ; void QMediaPlayer::setVideoOutput(class QVideoWidget *)
+ ?mutedChanged@QMediaRecorderControl@@IAEX_N@Z @ 883 NONAME ; void QMediaRecorderControl::mutedChanged(bool)
+ ??1QMediaPlaylistIOInterface@@UAE@XZ @ 884 NONAME ; QMediaPlaylistIOInterface::~QMediaPlaylistIOInterface(void)
+ ?map@QVideoFrame@@QAE_NW4MapMode@QAbstractVideoBuffer@@@Z @ 885 NONAME ; bool QVideoFrame::map(enum QAbstractVideoBuffer::MapMode)
+ ?periodSize@QAudioInput@@QBEHXZ @ 886 NONAME ; int QAudioInput::periodSize(void) const
+ ?handle@QAudioDeviceInfo@@ABE?AVQByteArray@@XZ @ 887 NONAME ; class QByteArray QAudioDeviceInfo::handle(void) const
+ ?isMetaDataWritable@QMediaRecorder@@QBE_NXZ @ 888 NONAME ; bool QMediaRecorder::isMetaDataWritable(void) const
+ ?qt_metacall@QMediaPlaylistSourceControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 889 NONAME ; int QMediaPlaylistSourceControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??0QMediaPlayer@@QAE@PAVQObject@@V?$QFlags@W4Flag@QMediaPlayer@@@@PAVQMediaServiceProvider@@@Z @ 890 NONAME ; QMediaPlayer::QMediaPlayer(class QObject *, class QFlags<enum QMediaPlayer::Flag>, class QMediaServiceProvider *)
+ ?mediaRemoved@QMediaPlaylistProvider@@IAEXHH@Z @ 891 NONAME ; void QMediaPlaylistProvider::mediaRemoved(int, int)
+ ?quality@QAudioEncoderSettings@@QBE?AW4EncodingQuality@QtMultimediaKit@@XZ @ 892 NONAME ; enum QtMultimediaKit::EncodingQuality QAudioEncoderSettings::quality(void) const
+ ?handleType@QAbstractVideoBuffer@@QBE?AW4HandleType@1@XZ @ 893 NONAME ; enum QAbstractVideoBuffer::HandleType QAbstractVideoBuffer::handleType(void) const
+ ?audioBitRate@QMediaResource@@QBEHXZ @ 894 NONAME ; int QMediaResource::audioBitRate(void) const
+ ?qt_metacast@QMetaDataWriterControl@@UAEPAXPBD@Z @ 895 NONAME ; void * QMetaDataWriterControl::qt_metacast(char const *)
+ ?trUtf8@QMediaRecorder@@SA?AVQString@@PBD0H@Z @ 896 NONAME ; class QString QMediaRecorder::trUtf8(char const *, char const *, int)
+ ??0QSoundEffect@@QAE@PAVQObject@@@Z @ 897 NONAME ; QSoundEffect::QSoundEffect(class QObject *)
+ ?bufferStatus@QMediaPlayer@@QBEHXZ @ 898 NONAME ; int QMediaPlayer::bufferStatus(void) const
+ ??0QAudioDeviceInfo@@AAE@ABVQString@@ABVQByteArray@@W4Mode@QAudio@@@Z @ 899 NONAME ; QAudioDeviceInfo::QAudioDeviceInfo(class QString const &, class QByteArray const &, enum QAudio::Mode)
+ ?metaObject@QAudioOutput@@UBEPBUQMetaObject@@XZ @ 900 NONAME ; struct QMetaObject const * QAudioOutput::metaObject(void) const
+ ??0QMediaTimeRange@@QAE@_J0@Z @ 901 NONAME ; QMediaTimeRange::QMediaTimeRange(long long, long long)
+ ?mediaAboutToBeInserted@QMediaPlaylistProvider@@IAEXHH@Z @ 902 NONAME ; void QMediaPlaylistProvider::mediaAboutToBeInserted(int, int)
+ ?setAspectRatioMode@QVideoWidget@@QAEXW4AspectRatioMode@Qt@@@Z @ 903 NONAME ; void QVideoWidget::setAspectRatioMode(enum Qt::AspectRatioMode)
+ ?qt_metacall@QVideoWindowControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 904 NONAME ; int QVideoWindowControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?codec@QAudioFormat@@QBE?AVQString@@XZ @ 905 NONAME ; class QString QAudioFormat::codec(void) const
+ ??0QMemoryVideoBuffer@@QAE@ABVQByteArray@@H@Z @ 906 NONAME ; QMemoryVideoBuffer::QMemoryVideoBuffer(class QByteArray const &, int)
+ ?currentIndexChanged@QMediaPlaylistNavigator@@IAEXH@Z @ 907 NONAME ; void QMediaPlaylistNavigator::currentIndexChanged(int)
+ ?qt_metacall@QVideoRendererControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 908 NONAME ; int QVideoRendererControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?setResolution@QVideoEncoderSettings@@QAEXABVQSize@@@Z @ 909 NONAME ; void QVideoEncoderSettings::setResolution(class QSize const &)
+ ??0QImageEncoderSettings@@QAE@XZ @ 910 NONAME ; QImageEncoderSettings::QImageEncoderSettings(void)
+ ?d_func@QMediaPlaylistProvider@@ABEPBVQMediaPlaylistProviderPrivate@@XZ @ 911 NONAME ; class QMediaPlaylistProviderPrivate const * QMediaPlaylistProvider::d_func(void) const
+ ??0QMediaTimeRange@@QAE@XZ @ 912 NONAME ; QMediaTimeRange::QMediaTimeRange(void)
+ ?shuffle@QMediaPlaylistProvider@@UAEXXZ @ 913 NONAME ; void QMediaPlaylistProvider::shuffle(void)
+ ?reset@QAudioInput@@QAEXXZ @ 914 NONAME ; void QAudioInput::reset(void)
+ ?trUtf8@QMetaDataWriterControl@@SA?AVQString@@PBD0@Z @ 915 NONAME ; class QString QMetaDataWriterControl::trUtf8(char const *, char const *)
+ ??_EQImageVideoBuffer@@UAE@I@Z @ 916 NONAME ; QImageVideoBuffer::~QImageVideoBuffer(unsigned int)
+ ?staticMetaObject@QAudioEndpointSelector@@2UQMetaObject@@B @ 917 NONAME ; struct QMetaObject const QAudioEndpointSelector::staticMetaObject
+ ??1QMediaPlayerControl@@UAE@XZ @ 918 NONAME ; QMediaPlayerControl::~QMediaPlayerControl(void)
+ ?d_func@QMediaControl@@AAEPAVQMediaControlPrivate@@XZ @ 919 NONAME ; class QMediaControlPrivate * QMediaControl::d_func(void)
+ ?metaDataAvailableChanged@QMetaDataWriterControl@@IAEX_N@Z @ 920 NONAME ; void QMetaDataWriterControl::metaDataAvailableChanged(bool)
+ ?notify@QAudioOutput@@IAEXXZ @ 921 NONAME ; void QAudioOutput::notify(void)
+ ?tr@QLocalMediaPlaylistProvider@@SA?AVQString@@PBD0H@Z @ 922 NONAME ; class QString QLocalMediaPlaylistProvider::tr(char const *, char const *, int)
+ ?removeMedia@QLocalMediaPlaylistProvider@@UAE_NHH@Z @ 923 NONAME ; bool QLocalMediaPlaylistProvider::removeMedia(int, int)
+ ?trUtf8@QMediaServiceProvider@@SA?AVQString@@PBD0H@Z @ 924 NONAME ; class QString QMediaServiceProvider::trUtf8(char const *, char const *, int)
+ ?isMuted@QMediaPlayer@@QBE_NXZ @ 925 NONAME ; bool QMediaPlayer::isMuted(void) const
+ ?tr@QMediaPlaylistSourceControl@@SA?AVQString@@PBD0H@Z @ 926 NONAME ; class QString QMediaPlaylistSourceControl::tr(char const *, char const *, int)
+ ?metaObject@QAudioEndpointSelector@@UBEPBUQMetaObject@@XZ @ 927 NONAME ; struct QMetaObject const * QAudioEndpointSelector::metaObject(void) const
+ ??0QAudioInput@@QAE@ABVQAudioFormat@@PAVQObject@@@Z @ 928 NONAME ; QAudioInput::QAudioInput(class QAudioFormat const &, class QObject *)
+ ??9QMediaResource@@QBE_NABV0@@Z @ 929 NONAME ; bool QMediaResource::operator!=(class QMediaResource const &) const
+ ??0QMediaStreamsControl@@IAE@PAVQObject@@@Z @ 930 NONAME ; QMediaStreamsControl::QMediaStreamsControl(class QObject *)
+ ?url@QMediaResource@@QBE?AVQUrl@@XZ @ 931 NONAME ; class QUrl QMediaResource::url(void) const
+ ??ZQMediaTimeRange@@QAEAAV0@ABVQMediaTimeInterval@@@Z @ 932 NONAME ; class QMediaTimeRange & QMediaTimeRange::operator-=(class QMediaTimeInterval const &)
+ ?canonicalUrl@QMediaContent@@QBE?AVQUrl@@XZ @ 933 NONAME ; class QUrl QMediaContent::canonicalUrl(void) const
+ ?tr@QVideoWidgetControl@@SA?AVQString@@PBD0H@Z @ 934 NONAME ; class QString QVideoWidgetControl::tr(char const *, char const *, int)
+ ?d_func@QLocalMediaPlaylistProvider@@ABEPBVQLocalMediaPlaylistProviderPrivate@@XZ @ 935 NONAME ; class QLocalMediaPlaylistProviderPrivate const * QLocalMediaPlaylistProvider::d_func(void) const
+ ?quality@QImageEncoderSettings@@QBE?AW4EncodingQuality@QtMultimediaKit@@XZ @ 936 NONAME ; enum QtMultimediaKit::EncodingQuality QImageEncoderSettings::quality(void) const
+ ?timeout@QMediaImageViewer@@QBEHXZ @ 937 NONAME ; int QMediaImageViewer::timeout(void) const
+ ?trUtf8@QMediaPlaylistControl@@SA?AVQString@@PBD0@Z @ 938 NONAME ; class QString QMediaPlaylistControl::trUtf8(char const *, char const *)
+ ?d_func@QVideoWidget@@AAEPAVQVideoWidgetPrivate@@XZ @ 939 NONAME ; class QVideoWidgetPrivate * QVideoWidget::d_func(void)
+ ?playbackMode@QMediaPlaylistNavigator@@QBE?AW4PlaybackMode@QMediaPlaylist@@XZ @ 940 NONAME ; enum QMediaPlaylist::PlaybackMode QMediaPlaylistNavigator::playbackMode(void) const
+ ?qt_metacast@QMediaPlaylist@@UAEPAXPBD@Z @ 941 NONAME ; void * QMediaPlaylist::qt_metacast(char const *)
+ ?elapsedUSecs@QAudioInput@@QBE_JXZ @ 942 NONAME ; long long QAudioInput::elapsedUSecs(void) const
+ ?frameWidth@QVideoSurfaceFormat@@QBEHXZ @ 943 NONAME ; int QVideoSurfaceFormat::frameWidth(void) const
+ ?resume@QAudioOutput@@QAEXXZ @ 944 NONAME ; void QAudioOutput::resume(void)
+ ?d_func@QMediaImageViewer@@AAEPAVQMediaImageViewerPrivate@@XZ @ 945 NONAME ; class QMediaImageViewerPrivate * QMediaImageViewer::d_func(void)
+ ??_EQVideoWindowControl@@UAE@I@Z @ 946 NONAME ; QVideoWindowControl::~QVideoWindowControl(unsigned int)
+ ?error@QRadioTuner@@IAEXW4Error@1@@Z @ 947 NONAME ; void QRadioTuner::error(enum QRadioTuner::Error)
+ ??_EQAudioEndpointSelector@@UAE@I@Z @ 948 NONAME ; QAudioEndpointSelector::~QAudioEndpointSelector(unsigned int)
+ ?isAvailable@QMediaRecorder@@QBE_NXZ @ 949 NONAME ; bool QMediaRecorder::isAvailable(void) const
+ ?staticMetaObject@QMediaService@@2UQMetaObject@@B @ 950 NONAME ; struct QMetaObject const QMediaService::staticMetaObject
+ ?d_func@QAbstractVideoSurface@@ABEPBVQAbstractVideoSurfacePrivate@@XZ @ 951 NONAME ; class QAbstractVideoSurfacePrivate const * QAbstractVideoSurface::d_func(void) const
+ ?d_func@QAudioCaptureSource@@AAEPAVQAudioCaptureSourcePrivate@@XZ @ 952 NONAME ; class QAudioCaptureSourcePrivate * QAudioCaptureSource::d_func(void)
+ ?tr@QAudioEncoderControl@@SA?AVQString@@PBD0H@Z @ 953 NONAME ; class QString QAudioEncoderControl::tr(char const *, char const *, int)
+ ?addInterval@QMediaTimeRange@@QAEXABVQMediaTimeInterval@@@Z @ 954 NONAME ; void QMediaTimeRange::addInterval(class QMediaTimeInterval const &)
+ ??_EQMediaPlaylistSourceControl@@UAE@I@Z @ 955 NONAME ; QMediaPlaylistSourceControl::~QMediaPlaylistSourceControl(unsigned int)
+ ??4QVideoFrame@@QAEAAV0@ABV0@@Z @ 956 NONAME ; class QVideoFrame & QVideoFrame::operator=(class QVideoFrame const &)
+ ?trUtf8@QMediaRecorderControl@@SA?AVQString@@PBD0H@Z @ 957 NONAME ; class QString QMediaRecorderControl::trUtf8(char const *, char const *, int)
+ ?nextItem@QMediaPlaylistNavigator@@QBE?AVQMediaContent@@H@Z @ 958 NONAME ; class QMediaContent QMediaPlaylistNavigator::nextItem(int) const
+ ?clear@QMediaPlaylistProvider@@UAE_NXZ @ 959 NONAME ; bool QMediaPlaylistProvider::clear(void)
+ ?isNull@QImageEncoderSettings@@QBE_NXZ @ 960 NONAME ; bool QImageEncoderSettings::isNull(void) const
+ ?saturationChanged@QVideoWidget@@IAEXH@Z @ 961 NONAME ; void QVideoWidget::saturationChanged(int)
+ ??4QMediaTimeRange@@QAEAAV0@ABVQMediaTimeInterval@@@Z @ 962 NONAME ; class QMediaTimeRange & QMediaTimeRange::operator=(class QMediaTimeInterval const &)
+ ?qt_metacast@QVideoWindowControl@@UAEPAXPBD@Z @ 963 NONAME ; void * QVideoWindowControl::qt_metacast(char const *)
+ ?metaObject@QAudioInput@@UBEPBUQMetaObject@@XZ @ 964 NONAME ; struct QMetaObject const * QAudioInput::metaObject(void) const
+ ?nativeSizeChanged@QVideoWindowControl@@IAEXXZ @ 965 NONAME ; void QVideoWindowControl::nativeSizeChanged(void)
+ ?sampleRate@QAudioEncoderSettings@@QBEHXZ @ 966 NONAME ; int QAudioEncoderSettings::sampleRate(void) const
+ ?stateChanged@QAudioInput@@IAEXW4State@QAudio@@@Z @ 967 NONAME ; void QAudioInput::stateChanged(enum QAudio::State)
+ ?tr@QVideoWindowControl@@SA?AVQString@@PBD0H@Z @ 968 NONAME ; class QString QVideoWindowControl::tr(char const *, char const *, int)
+ ??1QAbstractAudioOutput@@UAE@XZ @ 969 NONAME ; QAbstractAudioOutput::~QAbstractAudioOutput(void)
+ ?signalStrengthChanged@QRadioTunerControl@@IAEXH@Z @ 970 NONAME ; void QRadioTunerControl::signalStrengthChanged(int)
+ ?jump@QMediaPlaylistNavigator@@QAEXH@Z @ 971 NONAME ; void QMediaPlaylistNavigator::jump(int)
+ ?preferredFormat@QAudioDeviceInfo@@QBE?AVQAudioFormat@@XZ @ 972 NONAME ; class QAudioFormat QAudioDeviceInfo::preferredFormat(void) const
+ ?format@QAudioInput@@QBE?AVQAudioFormat@@XZ @ 973 NONAME ; class QAudioFormat QAudioInput::format(void) const
+ ??8QMediaServiceProviderHint@@QBE_NABV0@@Z @ 974 NONAME ; bool QMediaServiceProviderHint::operator==(class QMediaServiceProviderHint const &) const
+ ?qt_metacall@QMediaPlaylistIOPlugin@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 975 NONAME ; int QMediaPlaylistIOPlugin::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??9QAudioFormat@@QBE_NABV0@@Z @ 976 NONAME ; bool QAudioFormat::operator!=(class QAudioFormat const &) const
+ ?qt_metacast@QAudioEndpointSelector@@UAEPAXPBD@Z @ 977 NONAME ; void * QAudioEndpointSelector::qt_metacast(char const *)
+ ??0QMediaContent@@QAE@ABVQNetworkRequest@@@Z @ 978 NONAME ; QMediaContent::QMediaContent(class QNetworkRequest const &)
+ ?availabilityError@QAudioCaptureSource@@UBE?AW4AvailabilityError@QtMultimediaKit@@XZ @ 979 NONAME ; enum QtMultimediaKit::AvailabilityError QAudioCaptureSource::availabilityError(void) const
+ ?staticMetaObject@QAudioInput@@2UQMetaObject@@B @ 980 NONAME ; struct QMetaObject const QAudioInput::staticMetaObject
+ ??8QAudioFormat@@QBE_NABV0@@Z @ 981 NONAME ; bool QAudioFormat::operator==(class QAudioFormat const &) const
+ ?width@QVideoFrame@@QBEHXZ @ 982 NONAME ; int QVideoFrame::width(void) const
+ ?durationChanged@QMediaPlayer@@IAEX_J@Z @ 983 NONAME ; void QMediaPlayer::durationChanged(long long)
+ ?qt_metacall@QSoundEffect@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 984 NONAME ; int QSoundEffect::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?setVolume@QSoundEffect@@QAEXM@Z @ 985 NONAME ; void QSoundEffect::setVolume(float)
+ ?setCurrentIndex@QMediaPlaylist@@QAEXH@Z @ 986 NONAME ; void QMediaPlaylist::setCurrentIndex(int)
+ ?size@QGraphicsVideoItem@@QBE?AVQSizeF@@XZ @ 987 NONAME ; class QSizeF QGraphicsVideoItem::size(void) const
+ ??4QAudioDeviceInfo@@QAEAAV0@ABV0@@Z @ 988 NONAME ; class QAudioDeviceInfo & QAudioDeviceInfo::operator=(class QAudioDeviceInfo const &)
+ ?signalStrengthChanged@QRadioTuner@@IAEXH@Z @ 989 NONAME ; void QRadioTuner::signalStrengthChanged(int)
+ ?selectedDeviceChanged@QVideoDeviceControl@@IAEXH@Z @ 990 NONAME ; void QVideoDeviceControl::selectedDeviceChanged(int)
+ ?metaObject@QImageEncoderControl@@UBEPBUQMetaObject@@XZ @ 991 NONAME ; struct QMetaObject const * QImageEncoderControl::metaObject(void) const
+ ?state@QAudioOutput@@QBE?AW4State@QAudio@@XZ @ 992 NONAME ; enum QAudio::State QAudioOutput::state(void) const
+ ?extendedMetaData@QMediaRecorder@@QBE?AVQVariant@@ABVQString@@@Z @ 993 NONAME ; class QVariant QMediaRecorder::extendedMetaData(class QString const &) const
+ ?mutedChanged@QRadioTunerControl@@IAEX_N@Z @ 994 NONAME ; void QRadioTunerControl::mutedChanged(bool)
+ ?staticMetaObject@QMediaImageViewer@@2UQMetaObject@@B @ 995 NONAME ; struct QMetaObject const QMediaImageViewer::staticMetaObject
+ ?paint@QGraphicsVideoItem@@UAEXPAVQPainter@@PBVQStyleOptionGraphicsItem@@PAVQWidget@@@Z @ 996 NONAME ; void QGraphicsVideoItem::paint(class QPainter *, class QStyleOptionGraphicsItem const *, class QWidget *)
+ ??6@YA?AVQDebug@@V0@ABVQVideoSurfaceFormat@@@Z @ 997 NONAME ; class QDebug operator<<(class QDebug, class QVideoSurfaceFormat const &)
+ ?start@QAudioOutput@@QAEXPAVQIODevice@@@Z @ 998 NONAME ; void QAudioOutput::start(class QIODevice *)
+ ?tr@QMediaPlayerControl@@SA?AVQString@@PBD0H@Z @ 999 NONAME ; class QString QMediaPlayerControl::tr(char const *, char const *, int)
+ ??_EQAbstractVideoSurface@@UAE@I@Z @ 1000 NONAME ; QAbstractVideoSurface::~QAbstractVideoSurface(unsigned int)
+ ?mediaStatusChanged@QMediaImageViewer@@IAEXW4MediaStatus@1@@Z @ 1001 NONAME ; void QMediaImageViewer::mediaStatusChanged(enum QMediaImageViewer::MediaStatus)
+ ?setVideoCodec@QMediaResource@@QAEXABVQString@@@Z @ 1002 NONAME ; void QMediaResource::setVideoCodec(class QString const &)
+ ?brightnessChanged@QVideoWidgetControl@@IAEXH@Z @ 1003 NONAME ; void QVideoWidgetControl::brightnessChanged(int)
+ ?staticMetaObject@QVideoRendererControl@@2UQMetaObject@@B @ 1004 NONAME ; struct QMetaObject const QVideoRendererControl::staticMetaObject
+ ??0QMediaPlaylist@@QAE@PAVQObject@@@Z @ 1005 NONAME ; QMediaPlaylist::QMediaPlaylist(class QObject *)
+ ??4QVideoSurfaceFormat@@QAEAAV0@ABV0@@Z @ 1006 NONAME ; class QVideoSurfaceFormat & QVideoSurfaceFormat::operator=(class QVideoSurfaceFormat const &)
+ ?qt_metacall@QLocalMediaPlaylistProvider@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1007 NONAME ; int QLocalMediaPlaylistProvider::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?getStaticMetaObject@QVideoRendererControl@@SAABUQMetaObject@@XZ @ 1008 NONAME ; struct QMetaObject const & QVideoRendererControl::getStaticMetaObject(void)
+ ?metaObject@QMediaContainerControl@@UBEPBUQMetaObject@@XZ @ 1009 NONAME ; struct QMetaObject const * QMediaContainerControl::metaObject(void) const
+ ??9QVideoSurfaceFormat@@QBE_NABV0@@Z @ 1010 NONAME ; bool QVideoSurfaceFormat::operator!=(class QVideoSurfaceFormat const &) const
+ ??_EQSoundEffect@@UAE@I@Z @ 1011 NONAME ; QSoundEffect::~QSoundEffect(unsigned int)
+ ??_EQMemoryVideoBuffer@@UAE@I@Z @ 1012 NONAME ; QMemoryVideoBuffer::~QMemoryVideoBuffer(unsigned int)
+ ??1QMediaPlaylistIOPlugin@@UAE@XZ @ 1013 NONAME ; QMediaPlaylistIOPlugin::~QMediaPlaylistIOPlugin(void)
+ ?quality@QVideoEncoderSettings@@QBE?AW4EncodingQuality@QtMultimediaKit@@XZ @ 1014 NONAME ; enum QtMultimediaKit::EncodingQuality QVideoEncoderSettings::quality(void) const
+ ?playbackRateChanged@QMediaPlayerControl@@IAEXM@Z @ 1015 NONAME ; void QMediaPlayerControl::playbackRateChanged(float)
+ ??0QVideoEncoderSettings@@QAE@XZ @ 1016 NONAME ; QVideoEncoderSettings::QVideoEncoderSettings(void)
+ ?staticMetaObject@QMediaPlayerControl@@2UQMetaObject@@B @ 1017 NONAME ; struct QMetaObject const QMediaPlayerControl::staticMetaObject
+ ?trUtf8@QVideoDeviceControl@@SA?AVQString@@PBD0@Z @ 1018 NONAME ; class QString QVideoDeviceControl::trUtf8(char const *, char const *)
+ ??0QMediaControl@@IAE@PAVQObject@@@Z @ 1019 NONAME ; QMediaControl::QMediaControl(class QObject *)
+ ?currentItem@QMediaPlaylistNavigator@@QBE?AVQMediaContent@@XZ @ 1020 NONAME ; class QMediaContent QMediaPlaylistNavigator::currentItem(void) const
+ ?mediaAboutToBeRemoved@QMediaPlaylistProvider@@IAEXHH@Z @ 1021 NONAME ; void QMediaPlaylistProvider::mediaAboutToBeRemoved(int, int)
+ ?tr@QVideoRendererControl@@SA?AVQString@@PBD0@Z @ 1022 NONAME ; class QString QVideoRendererControl::tr(char const *, char const *)
+ ?boundingRect@QGraphicsVideoItem@@UBE?AVQRectF@@XZ @ 1023 NONAME ; class QRectF QGraphicsVideoItem::boundingRect(void) const
+ ?qt_metacast@QAudioEncoderControl@@UAEPAXPBD@Z @ 1024 NONAME ; void * QAudioEncoderControl::qt_metacast(char const *)
+ ?property@QVideoSurfaceFormat@@QBE?AVQVariant@@PBD@Z @ 1025 NONAME ; class QVariant QVideoSurfaceFormat::property(char const *) const
+ ?qt_metacast@QMediaContainerControl@@UAEPAXPBD@Z @ 1026 NONAME ; void * QMediaContainerControl::qt_metacast(char const *)
+ ?trUtf8@QVideoWidgetControl@@SA?AVQString@@PBD0@Z @ 1027 NONAME ; class QString QVideoWidgetControl::trUtf8(char const *, char const *)
+ ?qt_metacast@QAudioOutput@@UAEPAXPBD@Z @ 1028 NONAME ; void * QAudioOutput::qt_metacast(char const *)
+ ??1QMediaServiceSupportedDevicesInterface@@UAE@XZ @ 1029 NONAME ; QMediaServiceSupportedDevicesInterface::~QMediaServiceSupportedDevicesInterface(void)
+ ?qt_metacall@QAbstractAudioInput@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1030 NONAME ; int QAbstractAudioInput::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??1QAudioSystemFactoryInterface@@UAE@XZ @ 1031 NONAME ; QAudioSystemFactoryInterface::~QAudioSystemFactoryInterface(void)
+ ?qt_metacast@QRadioTunerControl@@UAEPAXPBD@Z @ 1032 NONAME ; void * QRadioTunerControl::qt_metacast(char const *)
+ ?d_func@QMemoryVideoBuffer@@AAEPAVQMemoryVideoBufferPrivate@@XZ @ 1033 NONAME ; class QMemoryVideoBufferPrivate * QMemoryVideoBuffer::d_func(void)
+ ?qt_metacall@QMediaContainerControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1034 NONAME ; int QMediaContainerControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?qt_metacast@QMediaPlaylistSourceControl@@UAEPAXPBD@Z @ 1035 NONAME ; void * QMediaPlaylistSourceControl::qt_metacast(char const *)
+ ?qt_metacast@QMediaServiceProvider@@UAEPAXPBD@Z @ 1036 NONAME ; void * QMediaServiceProvider::qt_metacast(char const *)
+ ??1QMediaRecorderControl@@UAE@XZ @ 1037 NONAME ; QMediaRecorderControl::~QMediaRecorderControl(void)
+ ?isMetaDataAvailable@QMediaObject@@QBE_NXZ @ 1038 NONAME ; bool QMediaObject::isMetaDataAvailable(void) const
+ ?saturationChanged@QVideoWidgetControl@@IAEXH@Z @ 1039 NONAME ; void QVideoWidgetControl::saturationChanged(int)
+ ?channelCount@QAudioEncoderSettings@@QBEHXZ @ 1040 NONAME ; int QAudioEncoderSettings::channelCount(void) const
+ ?d_func@QMediaImageViewer@@ABEPBVQMediaImageViewerPrivate@@XZ @ 1041 NONAME ; class QMediaImageViewerPrivate const * QMediaImageViewer::d_func(void) const
+ ?getStaticMetaObject@QAudioSystemPlugin@@SAABUQMetaObject@@XZ @ 1042 NONAME ; struct QMetaObject const & QAudioSystemPlugin::getStaticMetaObject(void)
+ ??1QLocalMediaPlaylistProvider@@UAE@XZ @ 1043 NONAME ; QLocalMediaPlaylistProvider::~QLocalMediaPlaylistProvider(void)
+ ??_EQAudioInput@@UAE@I@Z @ 1044 NONAME ; QAudioInput::~QAudioInput(unsigned int)
+ ?state@QRadioTuner@@QBE?AW4State@1@XZ @ 1045 NONAME ; enum QRadioTuner::State QRadioTuner::state(void) const
+ ?metaObject@QVideoWidgetControl@@UBEPBUQMetaObject@@XZ @ 1046 NONAME ; struct QMetaObject const * QVideoWidgetControl::metaObject(void) const
+ ??0QMetaDataReaderControl@@IAE@PAVQObject@@@Z @ 1047 NONAME ; QMetaDataReaderControl::QMetaDataReaderControl(class QObject *)
+ ?qt_metacall@QMediaControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1048 NONAME ; int QMediaControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?frameRate@QVideoEncoderSettings@@QBEMXZ @ 1049 NONAME ; float QVideoEncoderSettings::frameRate(void) const
+ ?tr@QMediaContainerControl@@SA?AVQString@@PBD0@Z @ 1050 NONAME ; class QString QMediaContainerControl::tr(char const *, char const *)
+ ??4QMediaTimeRange@@QAEAAV0@ABV0@@Z @ 1051 NONAME ; class QMediaTimeRange & QMediaTimeRange::operator=(class QMediaTimeRange const &)
+ ?qt_metacast@QVideoWidgetControl@@UAEPAXPBD@Z @ 1052 NONAME ; void * QVideoWidgetControl::qt_metacast(char const *)
+ ?unbind@QMediaImageViewer@@UAEXPAVQObject@@@Z @ 1053 NONAME ; void QMediaImageViewer::unbind(class QObject *)
+ ?signalStrength@QRadioTuner@@QBEHXZ @ 1054 NONAME ; int QRadioTuner::signalStrength(void) const
+ ?videoCodec@QMediaResource@@QBE?AVQString@@XZ @ 1055 NONAME ; class QString QMediaResource::videoCodec(void) const
+ ?band@QRadioTuner@@QBE?AW4Band@1@XZ @ 1056 NONAME ; enum QRadioTuner::Band QRadioTuner::band(void) const
+ ?staticMetaObject@QMediaServiceProviderPlugin@@2UQMetaObject@@B @ 1057 NONAME ; struct QMetaObject const QMediaServiceProviderPlugin::staticMetaObject
+ ?insertMedia@QMediaPlaylistProvider@@UAE_NHABVQMediaContent@@@Z @ 1058 NONAME ; bool QMediaPlaylistProvider::insertMedia(int, class QMediaContent const &)
+ ??1QMemoryVideoBuffer@@UAE@XZ @ 1059 NONAME ; QMemoryVideoBuffer::~QMemoryVideoBuffer(void)
+ ??1QRadioTuner@@UAE@XZ @ 1060 NONAME ; QRadioTuner::~QRadioTuner(void)
+ ?error@QMediaPlayer@@IAEXW4Error@1@@Z @ 1061 NONAME ; void QMediaPlayer::error(enum QMediaPlayer::Error)
+ ?tr@QGraphicsVideoItem@@SA?AVQString@@PBD0H@Z @ 1062 NONAME ; class QString QGraphicsVideoItem::tr(char const *, char const *, int)
+ ?getStaticMetaObject@QMediaServiceProvider@@SAABUQMetaObject@@XZ @ 1063 NONAME ; struct QMetaObject const & QMediaServiceProvider::getStaticMetaObject(void)
+ ?setBitRate@QAudioEncoderSettings@@QAEXH@Z @ 1064 NONAME ; void QAudioEncoderSettings::setBitRate(int)
+ ?isSeekable@QMediaPlayer@@QBE_NXZ @ 1065 NONAME ; bool QMediaPlayer::isSeekable(void) const
+ ?metaObject@QMediaPlaylistIOPlugin@@UBEPBUQMetaObject@@XZ @ 1066 NONAME ; struct QMetaObject const * QMediaPlaylistIOPlugin::metaObject(void) const
+ ?tr@QMediaPlayer@@SA?AVQString@@PBD0@Z @ 1067 NONAME ; class QString QMediaPlayer::tr(char const *, char const *)
+ ?setCodec@QAudioEncoderSettings@@QAEXABVQString@@@Z @ 1068 NONAME ; void QAudioEncoderSettings::setCodec(class QString const &)
+ ?isActive@QAbstractVideoSurface@@QBE_NXZ @ 1069 NONAME ; bool QAbstractVideoSurface::isActive(void) const
+ ??_EQMediaBindableInterface@@UAE@I@Z @ 1070 NONAME ; QMediaBindableInterface::~QMediaBindableInterface(unsigned int)
+ ?setYCbCrColorSpace@QVideoSurfaceFormat@@QAEXW4YCbCrColorSpace@1@@Z @ 1071 NONAME ; void QVideoSurfaceFormat::setYCbCrColorSpace(enum QVideoSurfaceFormat::YCbCrColorSpace)
+ ?setPlaybackMode@QMediaPlaylist@@QAEXW4PlaybackMode@1@@Z @ 1072 NONAME ; void QMediaPlaylist::setPlaybackMode(enum QMediaPlaylist::PlaybackMode)
+ ?volumeChanged@QRadioTuner@@IAEXH@Z @ 1073 NONAME ; void QRadioTuner::volumeChanged(int)
+ ?metaObject@QVideoWindowControl@@UBEPBUQMetaObject@@XZ @ 1074 NONAME ; struct QMetaObject const * QVideoWindowControl::metaObject(void) const
+ ?setFrequency@QAudioFormat@@QAEXH@Z @ 1075 NONAME ; void QAudioFormat::setFrequency(int)
+ ?trUtf8@QMediaControl@@SA?AVQString@@PBD0H@Z @ 1076 NONAME ; class QString QMediaControl::trUtf8(char const *, char const *, int)
+ ?selectedDeviceChanged@QVideoDeviceControl@@IAEXABVQString@@@Z @ 1077 NONAME ; void QVideoDeviceControl::selectedDeviceChanged(class QString const &)
+ ?setFrameRate@QVideoEncoderSettings@@QAEXM@Z @ 1078 NONAME ; void QVideoEncoderSettings::setFrameRate(float)
+ ?notify@QAbstractAudioOutput@@IAEXXZ @ 1079 NONAME ; void QAbstractAudioOutput::notify(void)
+ ?getStaticMetaObject@QMediaImageViewer@@SAABUQMetaObject@@XZ @ 1080 NONAME ; struct QMetaObject const & QMediaImageViewer::getStaticMetaObject(void)
+ ??_EQMediaImageViewer@@UAE@I@Z @ 1081 NONAME ; QMediaImageViewer::~QMediaImageViewer(unsigned int)
+ ??0QMediaPlaylistProvider@@QAE@PAVQObject@@@Z @ 1082 NONAME ; QMediaPlaylistProvider::QMediaPlaylistProvider(class QObject *)
+ ?trUtf8@QMediaServiceProviderPlugin@@SA?AVQString@@PBD0@Z @ 1083 NONAME ; class QString QMediaServiceProviderPlugin::trUtf8(char const *, char const *)
+ ?tr@QMediaServiceProvider@@SA?AVQString@@PBD0@Z @ 1084 NONAME ; class QString QMediaServiceProvider::tr(char const *, char const *)
+ ?loaded@QMediaPlaylistProvider@@IAEXXZ @ 1085 NONAME ; void QMediaPlaylistProvider::loaded(void)
+ ?staticMetaObject@QMediaPlayer@@2UQMetaObject@@B @ 1086 NONAME ; struct QMetaObject const QMediaPlayer::staticMetaObject
+ ??1QMediaPlaylist@@UAE@XZ @ 1087 NONAME ; QMediaPlaylist::~QMediaPlaylist(void)
+ ?error@QRadioTunerControl@@IAEXW4Error@QRadioTuner@@@Z @ 1088 NONAME ; void QRadioTunerControl::error(enum QRadioTuner::Error)
+ ?playbackRateChanged@QMediaPlayer@@IAEXM@Z @ 1089 NONAME ; void QMediaPlayer::playbackRateChanged(float)
+ ?setFrameSize@QVideoSurfaceFormat@@QAEXHH@Z @ 1090 NONAME ; void QVideoSurfaceFormat::setFrameSize(int, int)
+ ?getStaticMetaObject@QMediaContainerControl@@SAABUQMetaObject@@XZ @ 1091 NONAME ; struct QMetaObject const & QMediaContainerControl::getStaticMetaObject(void)
+ ?metaData@QMediaObject@@QBE?AVQVariant@@W4MetaData@QtMultimediaKit@@@Z @ 1092 NONAME ; class QVariant QMediaObject::metaData(enum QtMultimediaKit::MetaData) const
+ ?mimeType@QMediaServiceProviderHint@@QBE?AVQString@@XZ @ 1093 NONAME ; class QString QMediaServiceProviderHint::mimeType(void) const
+ ?outputLocation@QMediaRecorder@@QBE?AVQUrl@@XZ @ 1094 NONAME ; class QUrl QMediaRecorder::outputLocation(void) const
+ ?load@QMediaPlaylistProvider@@UAE_NPAVQIODevice@@PBD@Z @ 1095 NONAME ; bool QMediaPlaylistProvider::load(class QIODevice *, char const *)
+ ?error@QMediaRecorder@@IAEXW4Error@1@@Z @ 1096 NONAME ; void QMediaRecorder::error(enum QMediaRecorder::Error)
+ ?metaObject@QMediaPlayerControl@@UBEPBUQMetaObject@@XZ @ 1097 NONAME ; struct QMetaObject const * QMediaPlayerControl::metaObject(void) const
+ ??_EQMediaServiceFeaturesInterface@@UAE@I@Z @ 1098 NONAME ; QMediaServiceFeaturesInterface::~QMediaServiceFeaturesInterface(unsigned int)
+ ??_EQAbstractAudioInput@@UAE@I@Z @ 1099 NONAME ; QAbstractAudioInput::~QAbstractAudioInput(unsigned int)
+ ?moveEvent@QVideoWidget@@MAEXPAVQMoveEvent@@@Z @ 1100 NONAME ; void QVideoWidget::moveEvent(class QMoveEvent *)
+ ?audioCodec@QMediaResource@@QBE?AVQString@@XZ @ 1101 NONAME ; class QString QMediaResource::audioCodec(void) const
+ ??_EQGraphicsVideoItem@@UAE@I@Z @ 1102 NONAME ; QGraphicsVideoItem::~QGraphicsVideoItem(unsigned int)
+ ?staticMetaObject@QVideoEncoderControl@@2UQMetaObject@@B @ 1103 NONAME ; struct QMetaObject const QVideoEncoderControl::staticMetaObject
+ ?start@QAudioInput@@QAEPAVQIODevice@@XZ @ 1104 NONAME ; class QIODevice * QAudioInput::start(void)
+ ?pixelAspectRatio@QVideoSurfaceFormat@@QBE?AVQSize@@XZ @ 1105 NONAME ; class QSize QVideoSurfaceFormat::pixelAspectRatio(void) const
+ ??_EQLocalMediaPlaylistProvider@@UAE@I@Z @ 1106 NONAME ; QLocalMediaPlaylistProvider::~QLocalMediaPlaylistProvider(unsigned int)
+ ?trUtf8@QSoundEffect@@SA?AVQString@@PBD0H@Z @ 1107 NONAME ; class QString QSoundEffect::trUtf8(char const *, char const *, int)
+ ?getStaticMetaObject@QMediaService@@SAABUQMetaObject@@XZ @ 1108 NONAME ; struct QMetaObject const & QMediaService::getStaticMetaObject(void)
+ ??4QAudioFormat@@QAEAAV0@ABV0@@Z @ 1109 NONAME ; class QAudioFormat & QAudioFormat::operator=(class QAudioFormat const &)
+ ?isReadable@QVideoFrame@@QBE_NXZ @ 1110 NONAME ; bool QVideoFrame::isReadable(void) const
+ ?trUtf8@QMediaRecorder@@SA?AVQString@@PBD0@Z @ 1111 NONAME ; class QString QMediaRecorder::trUtf8(char const *, char const *)
+ ?setResolution@QImageEncoderSettings@@QAEXHH@Z @ 1112 NONAME ; void QImageEncoderSettings::setResolution(int, int)
+ ??_EQRadioTuner@@UAE@I@Z @ 1113 NONAME ; QRadioTuner::~QRadioTuner(unsigned int)
+ ?setVideoOutput@QMediaPlayer@@QAEXPAVQGraphicsVideoItem@@@Z @ 1114 NONAME ; void QMediaPlayer::setVideoOutput(class QGraphicsVideoItem *)
+ ??0QAudioInput@@QAE@ABVQAudioDeviceInfo@@ABVQAudioFormat@@PAVQObject@@@Z @ 1115 NONAME ; QAudioInput::QAudioInput(class QAudioDeviceInfo const &, class QAudioFormat const &, class QObject *)
+ ?setSize@QGraphicsVideoItem@@QAEXABVQSizeF@@@Z @ 1116 NONAME ; void QGraphicsVideoItem::setSize(class QSizeF const &)
+ ?codec@QAudioEncoderSettings@@QBE?AVQString@@XZ @ 1117 NONAME ; class QString QAudioEncoderSettings::codec(void) const
+ ?periodSize@QAudioOutput@@QBEHXZ @ 1118 NONAME ; int QAudioOutput::periodSize(void) const
+ ?trUtf8@QMediaPlaylistNavigator@@SA?AVQString@@PBD0H@Z @ 1119 NONAME ; class QString QMediaPlaylistNavigator::trUtf8(char const *, char const *, int)
+ ??1QMediaImageViewer@@UAE@XZ @ 1120 NONAME ; QMediaImageViewer::~QMediaImageViewer(void)
+ ??0QAudioDeviceInfo@@QAE@XZ @ 1121 NONAME ; QAudioDeviceInfo::QAudioDeviceInfo(void)
+ ?setCodec@QAudioFormat@@QAEXABVQString@@@Z @ 1122 NONAME ; void QAudioFormat::setCodec(class QString const &)
+ ?getStaticMetaObject@QLocalMediaPlaylistProvider@@SAABUQMetaObject@@XZ @ 1123 NONAME ; struct QMetaObject const & QLocalMediaPlaylistProvider::getStaticMetaObject(void)
+ ??1QMediaResource@@QAE@XZ @ 1124 NONAME ; QMediaResource::~QMediaResource(void)
+ ?tr@QAbstractAudioInput@@SA?AVQString@@PBD0H@Z @ 1125 NONAME ; class QString QAbstractAudioInput::tr(char const *, char const *, int)
+ ?save@QMediaPlaylistProvider@@UAE_NPAVQIODevice@@PBD@Z @ 1126 NONAME ; bool QMediaPlaylistProvider::save(class QIODevice *, char const *)
+ ?removeTimeRange@QMediaTimeRange@@QAEXABV1@@Z @ 1127 NONAME ; void QMediaTimeRange::removeTimeRange(class QMediaTimeRange const &)
+ ?setStartTime@QVideoFrame@@QAEX_J@Z @ 1128 NONAME ; void QVideoFrame::setStartTime(long long)
+ ?d_func@QLocalMediaPlaylistProvider@@AAEPAVQLocalMediaPlaylistProviderPrivate@@XZ @ 1129 NONAME ; class QLocalMediaPlaylistProviderPrivate * QLocalMediaPlaylistProvider::d_func(void)
+ ?metaObject@QMediaRecorder@@UBEPBUQMetaObject@@XZ @ 1130 NONAME ; struct QMetaObject const * QMediaRecorder::metaObject(void) const
+ ?unmap@QMemoryVideoBuffer@@UAEXXZ @ 1131 NONAME ; void QMemoryVideoBuffer::unmap(void)
+ ?d_func@QMediaPlaylistProvider@@AAEPAVQMediaPlaylistProviderPrivate@@XZ @ 1132 NONAME ; class QMediaPlaylistProviderPrivate * QMediaPlaylistProvider::d_func(void)
+ ??0QMediaObject@@IAE@AAVQMediaObjectPrivate@@PAVQObject@@PAVQMediaService@@@Z @ 1133 NONAME ; QMediaObject::QMediaObject(class QMediaObjectPrivate &, class QObject *, class QMediaService *)
+ ?tr@QMetaDataWriterControl@@SA?AVQString@@PBD0H@Z @ 1134 NONAME ; class QString QMetaDataWriterControl::tr(char const *, char const *, int)
+ ?isAudioAvailable@QMediaPlayer@@QBE_NXZ @ 1135 NONAME ; bool QMediaPlayer::isAudioAvailable(void) const
+ ?mediaAboutToBeInserted@QMediaPlaylist@@IAEXHH@Z @ 1136 NONAME ; void QMediaPlaylist::mediaAboutToBeInserted(int, int)
+ ??0QAudioFormat@@QAE@ABV0@@Z @ 1137 NONAME ; QAudioFormat::QAudioFormat(class QAudioFormat const &)
+ ?qt_metacall@QMediaObject@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1138 NONAME ; int QMediaObject::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?getStaticMetaObject@QMediaPlayer@@SAABUQMetaObject@@XZ @ 1139 NONAME ; struct QMetaObject const & QMediaPlayer::getStaticMetaObject(void)
+ ?bufferSize@QAudioInput@@QBEHXZ @ 1140 NONAME ; int QAudioInput::bufferSize(void) const
+ ?staticMetaObject@QMediaServiceProvider@@2UQMetaObject@@B @ 1141 NONAME ; struct QMetaObject const QMediaServiceProvider::staticMetaObject
+ ?error@QAudioInput@@QBE?AW4Error@QAudio@@XZ @ 1142 NONAME ; enum QAudio::Error QAudioInput::error(void) const
+ ?getStaticMetaObject@QVideoEncoderControl@@SAABUQMetaObject@@XZ @ 1143 NONAME ; struct QMetaObject const & QVideoEncoderControl::getStaticMetaObject(void)
+ ?qt_metacall@QMediaPlaylistControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1144 NONAME ; int QMediaPlaylistControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??0QLocalMediaPlaylistProvider@@QAE@PAVQObject@@@Z @ 1145 NONAME ; QLocalMediaPlaylistProvider::QLocalMediaPlaylistProvider(class QObject *)
+ ?notifyInterval@QMediaObject@@QBEHXZ @ 1146 NONAME ; int QMediaObject::notifyInterval(void) const
+ ??0QMediaContent@@QAE@ABVQMediaResource@@@Z @ 1147 NONAME ; QMediaContent::QMediaContent(class QMediaResource const &)
+ ?qt_metacall@QVideoDeviceControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1148 NONAME ; int QVideoDeviceControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?tr@QAbstractAudioDeviceInfo@@SA?AVQString@@PBD0H@Z @ 1149 NONAME ; class QString QAbstractAudioDeviceInfo::tr(char const *, char const *, int)
+ ??_EQMediaPlaylistWriter@@UAE@I@Z @ 1150 NONAME ; QMediaPlaylistWriter::~QMediaPlaylistWriter(unsigned int)
+ ?trUtf8@QAudioInput@@SA?AVQString@@PBD0H@Z @ 1151 NONAME ; class QString QAudioInput::trUtf8(char const *, char const *, int)
+ ?trUtf8@QAudioSystemPlugin@@SA?AVQString@@PBD0@Z @ 1152 NONAME ; class QString QAudioSystemPlugin::trUtf8(char const *, char const *)
+ ?getStaticMetaObject@QAudioEncoderControl@@SAABUQMetaObject@@XZ @ 1153 NONAME ; struct QMetaObject const & QAudioEncoderControl::getStaticMetaObject(void)
+ ?resources@QMediaContent@@QBE?AV?$QList@VQMediaResource@@@@XZ @ 1154 NONAME ; class QList<class QMediaResource> QMediaContent::resources(void) const
+ ?trUtf8@QAbstractVideoSurface@@SA?AVQString@@PBD0H@Z @ 1155 NONAME ; class QString QAbstractVideoSurface::trUtf8(char const *, char const *, int)
+ ?shuffle@QLocalMediaPlaylistProvider@@UAEXXZ @ 1156 NONAME ; void QLocalMediaPlaylistProvider::shuffle(void)
+ ?nativeSize@QGraphicsVideoItem@@QBE?AVQSizeF@@XZ @ 1157 NONAME ; class QSizeF QGraphicsVideoItem::nativeSize(void) const
+ ?setEncodingSettings@QMediaRecorder@@QAEXABVQAudioEncoderSettings@@ABVQVideoEncoderSettings@@ABVQString@@@Z @ 1158 NONAME ; void QMediaRecorder::setEncodingSettings(class QAudioEncoderSettings const &, class QVideoEncoderSettings const &, class QString const &)
+ ?event@QVideoWidget@@MAE_NPAVQEvent@@@Z @ 1159 NONAME ; bool QVideoWidget::event(class QEvent *)
+ ?processedUSecs@QAudioOutput@@QBE_JXZ @ 1160 NONAME ; long long QAudioOutput::processedUSecs(void) const
+ ?setChannels@QAudioFormat@@QAEXH@Z @ 1161 NONAME ; void QAudioFormat::setChannels(int)
+ ?tr@QAudioCaptureSource@@SA?AVQString@@PBD0@Z @ 1162 NONAME ; class QString QAudioCaptureSource::tr(char const *, char const *)
+ ?volumeChanged@QMediaPlayerControl@@IAEXH@Z @ 1163 NONAME ; void QMediaPlayerControl::volumeChanged(int)
+ ?trUtf8@QVideoRendererControl@@SA?AVQString@@PBD0H@Z @ 1164 NONAME ; class QString QVideoRendererControl::trUtf8(char const *, char const *, int)
+ ?trUtf8@QMediaPlaylistSourceControl@@SA?AVQString@@PBD0@Z @ 1165 NONAME ; class QString QMediaPlaylistSourceControl::trUtf8(char const *, char const *)
+ ?isMuted@QMediaRecorder@@QBE_NXZ @ 1166 NONAME ; bool QMediaRecorder::isMuted(void) const
+ ?trUtf8@QMediaService@@SA?AVQString@@PBD0@Z @ 1167 NONAME ; class QString QMediaService::trUtf8(char const *, char const *)
+ ?getStaticMetaObject@QMediaRecorderControl@@SAABUQMetaObject@@XZ @ 1168 NONAME ; struct QMetaObject const & QMediaRecorderControl::getStaticMetaObject(void)
+ ??0QAudioSystemPlugin@@QAE@PAVQObject@@@Z @ 1169 NONAME ; QAudioSystemPlugin::QAudioSystemPlugin(class QObject *)
+ ?resolution@QImageEncoderSettings@@QBE?AVQSize@@XZ @ 1170 NONAME ; class QSize QImageEncoderSettings::resolution(void) const
+ ?setPlaybackRate@QMediaPlayer@@QAEXM@Z @ 1171 NONAME ; void QMediaPlayer::setPlaybackRate(float)
+ ?availableExtendedMetaData@QMediaObject@@QBE?AVQStringList@@XZ @ 1172 NONAME ; class QStringList QMediaObject::availableExtendedMetaData(void) const
+ ??ZQMediaTimeRange@@QAEAAV0@ABV0@@Z @ 1173 NONAME ; class QMediaTimeRange & QMediaTimeRange::operator-=(class QMediaTimeRange const &)
+ ?brightness@QVideoWidget@@QBEHXZ @ 1174 NONAME ; int QVideoWidget::brightness(void) const
+ ??0QMediaTimeRange@@QAE@ABV0@@Z @ 1175 NONAME ; QMediaTimeRange::QMediaTimeRange(class QMediaTimeRange const &)
+ ?state@QMediaRecorder@@QBE?AW4State@1@XZ @ 1176 NONAME ; enum QMediaRecorder::State QMediaRecorder::state(void) const
+ ?tr@QMediaRecorder@@SA?AVQString@@PBD0H@Z @ 1177 NONAME ; class QString QMediaRecorder::tr(char const *, char const *, int)
+ ?trUtf8@QVideoEncoderControl@@SA?AVQString@@PBD0H@Z @ 1178 NONAME ; class QString QVideoEncoderControl::trUtf8(char const *, char const *, int)
+ ?hueChanged@QVideoWindowControl@@IAEXH@Z @ 1179 NONAME ; void QVideoWindowControl::hueChanged(int)
+ ?qt_metacast@QMediaService@@UAEPAXPBD@Z @ 1180 NONAME ; void * QMediaService::qt_metacast(char const *)
+ ?endTime@QVideoFrame@@QBE_JXZ @ 1181 NONAME ; long long QVideoFrame::endTime(void) const
+ ??0QAbstractVideoBuffer@@QAE@W4HandleType@0@@Z @ 1182 NONAME ; QAbstractVideoBuffer::QAbstractVideoBuffer(enum QAbstractVideoBuffer::HandleType)
+ ?defaultOutputDevice@QAudioDeviceInfo@@SA?AV1@XZ @ 1183 NONAME ; class QAudioDeviceInfo QAudioDeviceInfo::defaultOutputDevice(void)
+ ?tr@QMediaRecorderControl@@SA?AVQString@@PBD0@Z @ 1184 NONAME ; class QString QMediaRecorderControl::tr(char const *, char const *)
+ ?suspend@QAudioOutput@@QAEXXZ @ 1185 NONAME ; void QAudioOutput::suspend(void)
+ ??1QAbstractVideoSurface@@UAE@XZ @ 1186 NONAME ; QAbstractVideoSurface::~QAbstractVideoSurface(void)
+ ?previousIndex@QMediaPlaylist@@QBEHH@Z @ 1187 NONAME ; int QMediaPlaylist::previousIndex(int) const
+ ?tr@QMediaControl@@SA?AVQString@@PBD0H@Z @ 1188 NONAME ; class QString QMediaControl::tr(char const *, char const *, int)
+ ?tr@QImageEncoderControl@@SA?AVQString@@PBD0@Z @ 1189 NONAME ; class QString QImageEncoderControl::tr(char const *, char const *)
+ ?nativeSizeChanged@QGraphicsVideoItem@@IAEXABVQSizeF@@@Z @ 1190 NONAME ; void QGraphicsVideoItem::nativeSizeChanged(class QSizeF const &)
+ ??1QSoundEffect@@UAE@XZ @ 1191 NONAME ; QSoundEffect::~QSoundEffect(void)
+ ?stateChanged@QAbstractAudioInput@@IAEXW4State@QAudio@@@Z @ 1192 NONAME ; void QAbstractAudioInput::stateChanged(enum QAudio::State)
+ ?media@QMediaPlayer@@QBE?AVQMediaContent@@XZ @ 1193 NONAME ; class QMediaContent QMediaPlayer::media(void) const
+ ?bind@QMediaImageViewer@@UAE_NPAVQObject@@@Z @ 1194 NONAME ; bool QMediaImageViewer::bind(class QObject *)
+ ?resolution@QMediaResource@@QBE?AVQSize@@XZ @ 1195 NONAME ; class QSize QMediaResource::resolution(void) const
+ ?setBitRate@QVideoEncoderSettings@@QAEXH@Z @ 1196 NONAME ; void QVideoEncoderSettings::setBitRate(int)
+ ?qt_metacast@QMediaControl@@UAEPAXPBD@Z @ 1197 NONAME ; void * QMediaControl::qt_metacast(char const *)
+ ?sizeHint@QVideoWidget@@UBE?AVQSize@@XZ @ 1198 NONAME ; class QSize QVideoWidget::sizeHint(void) const
+ ?bandChanged@QRadioTunerControl@@IAEXW4Band@QRadioTuner@@@Z @ 1199 NONAME ; void QRadioTunerControl::bandChanged(enum QRadioTuner::Band)
+ ?trUtf8@QMetaDataReaderControl@@SA?AVQString@@PBD0H@Z @ 1200 NONAME ; class QString QMetaDataReaderControl::trUtf8(char const *, char const *, int)
+ ?getStaticMetaObject@QVideoDeviceControl@@SAABUQMetaObject@@XZ @ 1201 NONAME ; struct QMetaObject const & QVideoDeviceControl::getStaticMetaObject(void)
+ ?stateChanged@QMediaPlayer@@IAEXW4State@1@@Z @ 1202 NONAME ; void QMediaPlayer::stateChanged(enum QMediaPlayer::State)
+ ??0QMediaPlayerControl@@IAE@PAVQObject@@@Z @ 1203 NONAME ; QMediaPlayerControl::QMediaPlayerControl(class QObject *)
+ ?availabilityError@QMediaObject@@UBE?AW4AvailabilityError@QtMultimediaKit@@XZ @ 1204 NONAME ; enum QtMultimediaKit::AvailabilityError QMediaObject::availabilityError(void) const
+ ?tr@QRadioTunerControl@@SA?AVQString@@PBD0H@Z @ 1205 NONAME ; class QString QRadioTunerControl::tr(char const *, char const *, int)
+ ?getStaticMetaObject@QVideoWidgetControl@@SAABUQMetaObject@@XZ @ 1206 NONAME ; struct QMetaObject const & QVideoWidgetControl::getStaticMetaObject(void)
+ ??9QMediaServiceProviderHint@@QBE_NABV0@@Z @ 1207 NONAME ; bool QMediaServiceProviderHint::operator!=(class QMediaServiceProviderHint const &) const
+ ?tr@QRadioTuner@@SA?AVQString@@PBD0@Z @ 1208 NONAME ; class QString QRadioTuner::tr(char const *, char const *)
+ ?tr@QAudioSystemPlugin@@SA?AVQString@@PBD0H@Z @ 1209 NONAME ; class QString QAudioSystemPlugin::tr(char const *, char const *, int)
+ ?stateChanged@QMediaImageViewer@@IAEXW4State@1@@Z @ 1210 NONAME ; void QMediaImageViewer::stateChanged(enum QMediaImageViewer::State)
+ ?next@QMediaPlaylist@@QAEXXZ @ 1211 NONAME ; void QMediaPlaylist::next(void)
+ ?tr@QMediaPlayerControl@@SA?AVQString@@PBD0@Z @ 1212 NONAME ; class QString QMediaPlayerControl::tr(char const *, char const *)
+ ??1QMediaPlaylistControl@@UAE@XZ @ 1213 NONAME ; QMediaPlaylistControl::~QMediaPlaylistControl(void)
+ ??1QAudioOutput@@UAE@XZ @ 1214 NONAME ; QAudioOutput::~QAudioOutput(void)
+ ?setupMetaData@QMediaObject@@AAEXXZ @ 1215 NONAME ; void QMediaObject::setupMetaData(void)
+ ??_EQImageEncoderControl@@UAE@I@Z @ 1216 NONAME ; QImageEncoderControl::~QImageEncoderControl(unsigned int)
+ ??_EQMediaRecorder@@UAE@I@Z @ 1217 NONAME ; QMediaRecorder::~QMediaRecorder(unsigned int)
+ ?tr@QMetaDataWriterControl@@SA?AVQString@@PBD0@Z @ 1218 NONAME ; class QString QMetaDataWriterControl::tr(char const *, char const *)
+ ?tr@QAbstractAudioDeviceInfo@@SA?AVQString@@PBD0@Z @ 1219 NONAME ; class QString QAbstractAudioDeviceInfo::tr(char const *, char const *)
+ ?tr@QMediaRecorder@@SA?AVQString@@PBD0@Z @ 1220 NONAME ; class QString QMediaRecorder::tr(char const *, char const *)
+ ??1QVideoWidget@@UAE@XZ @ 1221 NONAME ; QVideoWidget::~QVideoWidget(void)
+ ?tr@QAudioSystemPlugin@@SA?AVQString@@PBD0@Z @ 1222 NONAME ; class QString QAudioSystemPlugin::tr(char const *, char const *)
+ ?setEncodingMode@QAudioEncoderSettings@@QAEXW4EncodingMode@QtMultimediaKit@@@Z @ 1223 NONAME ; void QAudioEncoderSettings::setEncodingMode(enum QtMultimediaKit::EncodingMode)
+ ??1QVideoWindowControl@@UAE@XZ @ 1224 NONAME ; QVideoWindowControl::~QVideoWindowControl(void)
+ ?trUtf8@QMediaServiceProviderPlugin@@SA?AVQString@@PBD0H@Z @ 1225 NONAME ; class QString QMediaServiceProviderPlugin::trUtf8(char const *, char const *, int)
+ ?currentIndexChanged@QMediaPlaylistControl@@IAEXH@Z @ 1226 NONAME ; void QMediaPlaylistControl::currentIndexChanged(int)
+ ?suspend@QAudioInput@@QAEXXZ @ 1227 NONAME ; void QAudioInput::suspend(void)
+ ?mutedChanged@QMediaPlayer@@IAEX_N@Z @ 1228 NONAME ; void QMediaPlayer::mutedChanged(bool)
+ ?metaObject@QAbstractAudioInput@@UBEPBUQMetaObject@@XZ @ 1229 NONAME ; struct QMetaObject const * QAbstractAudioInput::metaObject(void) const
+ ?mediaChanged@QMediaPlayer@@IAEXABVQMediaContent@@@Z @ 1230 NONAME ; void QMediaPlayer::mediaChanged(class QMediaContent const &)
+ ?mediaChanged@QMediaPlaylist@@IAEXHH@Z @ 1231 NONAME ; void QMediaPlaylist::mediaChanged(int, int)
+ ?tr@QMediaServiceProvider@@SA?AVQString@@PBD0H@Z @ 1232 NONAME ; class QString QMediaServiceProvider::tr(char const *, char const *, int)
+ ?mutedChanged@QSoundEffect@@IAEXXZ @ 1233 NONAME ; void QSoundEffect::mutedChanged(void)
+ ?trUtf8@QRadioTuner@@SA?AVQString@@PBD0@Z @ 1234 NONAME ; class QString QRadioTuner::trUtf8(char const *, char const *)
+ ?getStaticMetaObject@QRadioTuner@@SAABUQMetaObject@@XZ @ 1235 NONAME ; struct QMetaObject const & QRadioTuner::getStaticMetaObject(void)
+ ?frameRate@QVideoSurfaceFormat@@QBEMXZ @ 1236 NONAME ; float QVideoSurfaceFormat::frameRate(void) const
+ ?offset@QGraphicsVideoItem@@QBE?AVQPointF@@XZ @ 1237 NONAME ; class QPointF QGraphicsVideoItem::offset(void) const
+ ?trUtf8@QAudioCaptureSource@@SA?AVQString@@PBD0H@Z @ 1238 NONAME ; class QString QAudioCaptureSource::trUtf8(char const *, char const *, int)
+ ?removeMedia@QMediaPlaylistProvider@@UAE_NH@Z @ 1239 NONAME ; bool QMediaPlaylistProvider::removeMedia(int)
+ ??0QVideoEncoderControl@@IAE@PAVQObject@@@Z @ 1240 NONAME ; QVideoEncoderControl::QVideoEncoderControl(class QObject *)
+ ?setQuality@QImageEncoderSettings@@QAEXW4EncodingQuality@QtMultimediaKit@@@Z @ 1241 NONAME ; void QImageEncoderSettings::setQuality(enum QtMultimediaKit::EncodingQuality)
+ ?contrastChanged@QVideoWidget@@IAEXH@Z @ 1242 NONAME ; void QVideoWidget::contrastChanged(int)
+ ?unbind@QMediaObject@@UAEXPAVQObject@@@Z @ 1243 NONAME ; void QMediaObject::unbind(class QObject *)
+ ?metaObject@QMediaImageViewer@@UBEPBUQMetaObject@@XZ @ 1244 NONAME ; struct QMetaObject const * QMediaImageViewer::metaObject(void) const
+ ?scanLineDirection@QVideoSurfaceFormat@@QBE?AW4Direction@1@XZ @ 1245 NONAME ; enum QVideoSurfaceFormat::Direction QVideoSurfaceFormat::scanLineDirection(void) const
+ ?tr@QMediaStreamsControl@@SA?AVQString@@PBD0@Z @ 1246 NONAME ; class QString QMediaStreamsControl::tr(char const *, char const *)
+ ?getStaticMetaObject@QAbstractVideoSurface@@SAABUQMetaObject@@XZ @ 1247 NONAME ; struct QMetaObject const & QAbstractVideoSurface::getStaticMetaObject(void)
+ ??0QGraphicsVideoItem@@QAE@PAVQGraphicsItem@@@Z @ 1248 NONAME ; QGraphicsVideoItem::QGraphicsVideoItem(class QGraphicsItem *)
+ ??1QVideoEncoderControl@@UAE@XZ @ 1249 NONAME ; QVideoEncoderControl::~QVideoEncoderControl(void)
+ ?removeInterval@QMediaTimeRange@@QAEXABVQMediaTimeInterval@@@Z @ 1250 NONAME ; void QMediaTimeRange::removeInterval(class QMediaTimeInterval const &)
+ ?insertMedia@QLocalMediaPlaylistProvider@@UAE_NHABVQMediaContent@@@Z @ 1251 NONAME ; bool QLocalMediaPlaylistProvider::insertMedia(int, class QMediaContent const &)
+ ?currentMedia@QMediaPlaylist@@QBE?AVQMediaContent@@XZ @ 1252 NONAME ; class QMediaContent QMediaPlaylist::currentMedia(void) const
+ ?setAudioCodec@QMediaResource@@QAEXABVQString@@@Z @ 1253 NONAME ; void QMediaResource::setAudioCodec(class QString const &)
+ ?activated@QMediaPlaylistNavigator@@IAEXABVQMediaContent@@@Z @ 1254 NONAME ; void QMediaPlaylistNavigator::activated(class QMediaContent const &)
+ ?trUtf8@QMediaPlaylistNavigator@@SA?AVQString@@PBD0@Z @ 1255 NONAME ; class QString QMediaPlaylistNavigator::trUtf8(char const *, char const *)
+ ?tr@QMediaControl@@SA?AVQString@@PBD0@Z @ 1256 NONAME ; class QString QMediaControl::tr(char const *, char const *)
+ ?getStaticMetaObject@QMetaDataWriterControl@@SAABUQMetaObject@@XZ @ 1257 NONAME ; struct QMetaObject const & QMetaDataWriterControl::getStaticMetaObject(void)
+ ??8QVideoSurfaceFormat@@QBE_NABV0@@Z @ 1258 NONAME ; bool QVideoSurfaceFormat::operator==(class QVideoSurfaceFormat const &) const
+ ?removeInterval@QMediaTimeRange@@QAEX_J0@Z @ 1259 NONAME ; void QMediaTimeRange::removeInterval(long long, long long)
+ ?qt_metacast@QAbstractAudioOutput@@UAEPAXPBD@Z @ 1260 NONAME ; void * QAbstractAudioOutput::qt_metacast(char const *)
+ ??1QVideoSurfaceFormat@@QAE@XZ @ 1261 NONAME ; QVideoSurfaceFormat::~QVideoSurfaceFormat(void)
+ ?nativeResolutionChanged@QAbstractVideoSurface@@IAEXABVQSize@@@Z @ 1262 NONAME ; void QAbstractVideoSurface::nativeResolutionChanged(class QSize const &)
+ ??1QCameraControl@@UAE@XZ @ 1263 NONAME ; QCameraControl::~QCameraControl(void)
+ ?opticalZoomChanged@QCameraFocusControl@@IAEXM@Z @ 1264 NONAME ; void QCameraFocusControl::opticalZoomChanged(float)
+ ?trUtf8@QCameraFocusControl@@SA?AVQString@@PBD0@Z @ 1265 NONAME ; class QString QCameraFocusControl::trUtf8(char const *, char const *)
+ ?qt_metacast@QCamera@@UAEPAXPBD@Z @ 1266 NONAME ; void * QCamera::qt_metacast(char const *)
+ ??4QCameraFocusZone@@QAEAAV0@ABV0@@Z @ 1267 NONAME ; class QCameraFocusZone & QCameraFocusZone::operator=(class QCameraFocusZone const &)
+ ?errorString@QCameraImageCapture@@QBE?AVQString@@XZ @ 1268 NONAME ; class QString QCameraImageCapture::errorString(void) const
+ ?readyForCaptureChanged@QCameraImageCaptureControl@@IAEX_N@Z @ 1269 NONAME ; void QCameraImageCaptureControl::readyForCaptureChanged(bool)
+ ??1QCameraImageCaptureControl@@UAE@XZ @ 1270 NONAME ; QCameraImageCaptureControl::~QCameraImageCaptureControl(void)
+ ?metaObject@QCameraViewfinder@@UBEPBUQMetaObject@@XZ @ 1271 NONAME ; struct QMetaObject const * QCameraViewfinder::metaObject(void) const
+ ?saturation@QCameraImageProcessing@@QBEHXZ @ 1272 NONAME ; int QCameraImageProcessing::saturation(void) const
+ ?trUtf8@QCameraExposure@@SA?AVQString@@PBD0@Z @ 1273 NONAME ; class QString QCameraExposure::trUtf8(char const *, char const *)
+ ?availableDevices@QCamera@@SA?AV?$QList@VQByteArray@@@@XZ @ 1274 NONAME ; class QList<class QByteArray> QCamera::availableDevices(void)
+ ?tr@QCameraImageCaptureControl@@SA?AVQString@@PBD0H@Z @ 1275 NONAME ; class QString QCameraImageCaptureControl::tr(char const *, char const *, int)
+ ?exposure@QCamera@@QBEPAVQCameraExposure@@XZ @ 1276 NONAME ; class QCameraExposure * QCamera::exposure(void) const
+ ??_EQCameraViewfinder@@UAE@I@Z @ 1277 NONAME ; QCameraViewfinder::~QCameraViewfinder(unsigned int)
+ ?setViewfinder@QCamera@@QAEXPAVQGraphicsVideoItem@@@Z @ 1278 NONAME ; void QCamera::setViewfinder(class QGraphicsVideoItem *)
+ ?exposureCompensationChanged@QCameraExposure@@IAEXM@Z @ 1279 NONAME ; void QCameraExposure::exposureCompensationChanged(float)
+ ?imageSaved@QCameraImageCaptureControl@@IAEXHABVQString@@@Z @ 1280 NONAME ; void QCameraImageCaptureControl::imageSaved(int, class QString const &)
+ ?isFocusPointModeSupported@QCameraFocus@@QBE_NW4FocusPointMode@1@@Z @ 1281 NONAME ; bool QCameraFocus::isFocusPointModeSupported(enum QCameraFocus::FocusPointMode) const
+ ?error@QCamera@@QBE?AW4Error@1@XZ @ 1282 NONAME ; enum QCamera::Error QCamera::error(void) const
+ ?getStaticMetaObject@QCameraLocksControl@@SAABUQMetaObject@@XZ @ 1283 NONAME ; struct QMetaObject const & QCameraLocksControl::getStaticMetaObject(void)
+ ?metaObject@QCameraImageCaptureControl@@UBEPBUQMetaObject@@XZ @ 1284 NONAME ; struct QMetaObject const * QCameraImageCaptureControl::metaObject(void) const
+ ?unlock@QCamera@@QAEXV?$QFlags@W4LockType@QCamera@@@@@Z @ 1285 NONAME ; void QCamera::unlock(class QFlags<enum QCamera::LockType>)
+ ?qt_metacall@QCameraExposure@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1286 NONAME ; int QCameraExposure::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?staticMetaObject@QCameraLocksControl@@2UQMetaObject@@B @ 1287 NONAME ; struct QMetaObject const QCameraLocksControl::staticMetaObject
+ ?focus@QCamera@@QBEPAVQCameraFocus@@XZ @ 1288 NONAME ; class QCameraFocus * QCamera::focus(void) const
+ ?staticMetaObject@QCameraFocus@@2UQMetaObject@@B @ 1289 NONAME ; struct QMetaObject const QCameraFocus::staticMetaObject
+ ?qt_metacall@QCameraImageProcessing@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1290 NONAME ; int QCameraImageProcessing::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??0QCameraFocus@@AAE@PAVQCamera@@@Z @ 1291 NONAME ; QCameraFocus::QCameraFocus(class QCamera *)
+ ?error@QCameraImageCaptureControl@@IAEXHHABVQString@@@Z @ 1292 NONAME ; void QCameraImageCaptureControl::error(int, int, class QString const &)
+ ?staticMetaObject@QCameraControl@@2UQMetaObject@@B @ 1293 NONAME ; struct QMetaObject const QCameraControl::staticMetaObject
+ ?isReadyForCapture@QCameraImageCapture@@QBE_NXZ @ 1294 NONAME ; bool QCameraImageCapture::isReadyForCapture(void) const
+ ?exposureCompensation@QCameraExposure@@QBEMXZ @ 1295 NONAME ; float QCameraExposure::exposureCompensation(void) const
+ ?getStaticMetaObject@QCameraImageCapture@@SAABUQMetaObject@@XZ @ 1296 NONAME ; struct QMetaObject const & QCameraImageCapture::getStaticMetaObject(void)
+ ?getStaticMetaObject@QCameraImageCaptureControl@@SAABUQMetaObject@@XZ @ 1297 NONAME ; struct QMetaObject const & QCameraImageCaptureControl::getStaticMetaObject(void)
+ ?isAvailable@QCameraImageProcessing@@QBE_NXZ @ 1298 NONAME ; bool QCameraImageProcessing::isAvailable(void) const
+ ?lockStatusChanged@QCamera@@IAEXW4LockType@1@W4LockStatus@1@W4LockChangeReason@1@@Z @ 1299 NONAME ; void QCamera::lockStatusChanged(enum QCamera::LockType, enum QCamera::LockStatus, enum QCamera::LockChangeReason)
+ ?qt_metacall@QCameraControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1300 NONAME ; int QCameraControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?qt_metacast@QCameraFlashControl@@UAEPAXPBD@Z @ 1301 NONAME ; void * QCameraFlashControl::qt_metacast(char const *)
+ ??1QCamera@@UAE@XZ @ 1302 NONAME ; QCamera::~QCamera(void)
+ ??0QCameraViewfinder@@QAE@PAVQWidget@@@Z @ 1303 NONAME ; QCameraViewfinder::QCameraViewfinder(class QWidget *)
+ ??1QCameraExposureControl@@UAE@XZ @ 1304 NONAME ; QCameraExposureControl::~QCameraExposureControl(void)
+ ?exposureParameterChanged@QCameraExposureControl@@IAEXH@Z @ 1305 NONAME ; void QCameraExposureControl::exposureParameterChanged(int)
+ ?tr@QCameraExposureControl@@SA?AVQString@@PBD0@Z @ 1306 NONAME ; class QString QCameraExposureControl::tr(char const *, char const *)
+ ?d_func@QCameraImageCapture@@ABEPBVQCameraImageCapturePrivate@@XZ @ 1307 NONAME ; class QCameraImageCapturePrivate const * QCameraImageCapture::d_func(void) const
+ ??9QCameraFocusZone@@QBE_NABV0@@Z @ 1308 NONAME ; bool QCameraFocusZone::operator!=(class QCameraFocusZone const &) const
+ ??1QCameraFocusControl@@UAE@XZ @ 1309 NONAME ; QCameraFocusControl::~QCameraFocusControl(void)
+ ?setContrast@QCameraImageProcessing@@QAEXH@Z @ 1310 NONAME ; void QCameraImageProcessing::setContrast(int)
+ ?error@QCameraImageCapture@@IAEXHW4Error@1@ABVQString@@@Z @ 1311 NONAME ; void QCameraImageCapture::error(int, enum QCameraImageCapture::Error, class QString const &)
+ ?encodingSettings@QCameraImageCapture@@QBE?AVQImageEncoderSettings@@XZ @ 1312 NONAME ; class QImageEncoderSettings QCameraImageCapture::encodingSettings(void) const
+ ?opticalZoom@QCameraFocus@@QBEMXZ @ 1313 NONAME ; float QCameraFocus::opticalZoom(void) const
+ ?setCaptureMode@QCamera@@QAEXW4CaptureMode@1@@Z @ 1314 NONAME ; void QCamera::setCaptureMode(enum QCamera::CaptureMode)
+ ?d_func@QCameraFocus@@AAEPAVQCameraFocusPrivate@@XZ @ 1315 NONAME ; class QCameraFocusPrivate * QCameraFocus::d_func(void)
+ ?metaObject@QCameraExposureControl@@UBEPBUQMetaObject@@XZ @ 1316 NONAME ; struct QMetaObject const * QCameraExposureControl::metaObject(void) const
+ ?trUtf8@QCameraFocusControl@@SA?AVQString@@PBD0H@Z @ 1317 NONAME ; class QString QCameraFocusControl::trUtf8(char const *, char const *, int)
+ ??_EQCameraLocksControl@@UAE@I@Z @ 1318 NONAME ; QCameraLocksControl::~QCameraLocksControl(unsigned int)
+ ?trUtf8@QCameraFlashControl@@SA?AVQString@@PBD0H@Z @ 1319 NONAME ; class QString QCameraFlashControl::trUtf8(char const *, char const *, int)
+ ?tr@QCameraImageCapture@@SA?AVQString@@PBD0H@Z @ 1320 NONAME ; class QString QCameraImageCapture::tr(char const *, char const *, int)
+ ?tr@QCameraImageProcessing@@SA?AVQString@@PBD0@Z @ 1321 NONAME ; class QString QCameraImageProcessing::tr(char const *, char const *)
+ ?trUtf8@QCameraImageProcessingControl@@SA?AVQString@@PBD0H@Z @ 1322 NONAME ; class QString QCameraImageProcessingControl::trUtf8(char const *, char const *, int)
+ ?getStaticMetaObject@QCameraFocusControl@@SAABUQMetaObject@@XZ @ 1323 NONAME ; struct QMetaObject const & QCameraFocusControl::getStaticMetaObject(void)
+ ?getStaticMetaObject@QCameraImageProcessingControl@@SAABUQMetaObject@@XZ @ 1324 NONAME ; struct QMetaObject const & QCameraImageProcessingControl::getStaticMetaObject(void)
+ ?trUtf8@QCameraImageCaptureControl@@SA?AVQString@@PBD0@Z @ 1325 NONAME ; class QString QCameraImageCaptureControl::trUtf8(char const *, char const *)
+ ?searchAndLock@QCamera@@QAEXXZ @ 1326 NONAME ; void QCamera::searchAndLock(void)
+ ?getStaticMetaObject@QCameraExposureControl@@SAABUQMetaObject@@XZ @ 1327 NONAME ; struct QMetaObject const & QCameraExposureControl::getStaticMetaObject(void)
+ ?contrast@QCameraImageProcessing@@QBEHXZ @ 1328 NONAME ; int QCameraImageProcessing::contrast(void) const
+ ??_EQCameraImageProcessingControl@@UAE@I@Z @ 1329 NONAME ; QCameraImageProcessingControl::~QCameraImageProcessingControl(unsigned int)
+ ??_EQCameraControl@@UAE@I@Z @ 1330 NONAME ; QCameraControl::~QCameraControl(unsigned int)
+ ?staticMetaObject@QCameraFocusControl@@2UQMetaObject@@B @ 1331 NONAME ; struct QMetaObject const QCameraFocusControl::staticMetaObject
+ ??0QCameraFocusControl@@IAE@PAVQObject@@@Z @ 1332 NONAME ; QCameraFocusControl::QCameraFocusControl(class QObject *)
+ ?setAutoIsoSensitivity@QCameraExposure@@QAEXXZ @ 1333 NONAME ; void QCameraExposure::setAutoIsoSensitivity(void)
+ ?qt_metacall@QCameraLocksControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1334 NONAME ; int QCameraLocksControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?trUtf8@QCameraFlashControl@@SA?AVQString@@PBD0@Z @ 1335 NONAME ; class QString QCameraFlashControl::trUtf8(char const *, char const *)
+ ?getStaticMetaObject@QCameraImageProcessing@@SAABUQMetaObject@@XZ @ 1336 NONAME ; struct QMetaObject const & QCameraImageProcessing::getStaticMetaObject(void)
+ ??0QCameraLocksControl@@IAE@PAVQObject@@@Z @ 1337 NONAME ; QCameraLocksControl::QCameraLocksControl(class QObject *)
+ ?stop@QCamera@@QAEXXZ @ 1338 NONAME ; void QCamera::stop(void)
+ ?supportedShutterSpeeds@QCameraExposure@@QBE?AV?$QList@M@@PA_N@Z @ 1339 NONAME ; class QList<float> QCameraExposure::supportedShutterSpeeds(bool *) const
+ ?flashReady@QCameraExposure@@IAEX_N@Z @ 1340 NONAME ; void QCameraExposure::flashReady(bool)
+ ?tr@QCameraViewfinder@@SA?AVQString@@PBD0@Z @ 1341 NONAME ; class QString QCameraViewfinder::tr(char const *, char const *)
+ ?whiteBalanceMode@QCameraImageProcessing@@QBE?AW4WhiteBalanceMode@1@XZ @ 1342 NONAME ; enum QCameraImageProcessing::WhiteBalanceMode QCameraImageProcessing::whiteBalanceMode(void) const
+ ?qt_metacast@QCameraExposure@@UAEPAXPBD@Z @ 1343 NONAME ; void * QCameraExposure::qt_metacast(char const *)
+ ?flashMode@QCameraExposure@@QBE?AV?$QFlags@W4FlashMode@QCameraExposure@@@@XZ @ 1344 NONAME ; class QFlags<enum QCameraExposure::FlashMode> QCameraExposure::flashMode(void) const
+ ??1QCameraViewfinder@@UAE@XZ @ 1345 NONAME ; QCameraViewfinder::~QCameraViewfinder(void)
+ ?manualWhiteBalance@QCameraImageProcessing@@QBEHXZ @ 1346 NONAME ; int QCameraImageProcessing::manualWhiteBalance(void) const
+ ?isAvailable@QCameraFocus@@QBE_NXZ @ 1347 NONAME ; bool QCameraFocus::isAvailable(void) const
+ ?readyForCaptureChanged@QCameraImageCapture@@IAEX_N@Z @ 1348 NONAME ; void QCameraImageCapture::readyForCaptureChanged(bool)
+ ?metaObject@QCameraExposure@@UBEPBUQMetaObject@@XZ @ 1349 NONAME ; struct QMetaObject const * QCameraExposure::metaObject(void) const
+ ?d_func@QCamera@@ABEPBVQCameraPrivate@@XZ @ 1350 NONAME ; class QCameraPrivate const * QCamera::d_func(void) const
+ ?opticalZoomChanged@QCameraFocus@@IAEXM@Z @ 1351 NONAME ; void QCameraFocus::opticalZoomChanged(float)
+ ?isValid@QCameraFocusZone@@QBE_NXZ @ 1352 NONAME ; bool QCameraFocusZone::isValid(void) const
+ ?tr@QCameraFocus@@SA?AVQString@@PBD0@Z @ 1353 NONAME ; class QString QCameraFocus::tr(char const *, char const *)
+ ?staticMetaObject@QCameraExposure@@2UQMetaObject@@B @ 1354 NONAME ; struct QMetaObject const QCameraExposure::staticMetaObject
+ ?setEncodingSettings@QCameraImageCapture@@QAEXABVQImageEncoderSettings@@@Z @ 1355 NONAME ; void QCameraImageCapture::setEncodingSettings(class QImageEncoderSettings const &)
+ ?metaObject@QCameraImageCapture@@UBEPBUQMetaObject@@XZ @ 1356 NONAME ; struct QMetaObject const * QCameraImageCapture::metaObject(void) const
+ ?load@QCamera@@QAEXXZ @ 1357 NONAME ; void QCamera::load(void)
+ ??0QVideoWidget@@IAE@AAVQVideoWidgetPrivate@@PAVQWidget@@@Z @ 1358 NONAME ; QVideoWidget::QVideoWidget(class QVideoWidgetPrivate &, class QWidget *)
+ ?setFocusPointMode@QCameraFocus@@QAEXW4FocusPointMode@1@@Z @ 1359 NONAME ; void QCameraFocus::setFocusPointMode(enum QCameraFocus::FocusPointMode)
+ ?tr@QCameraImageProcessing@@SA?AVQString@@PBD0H@Z @ 1360 NONAME ; class QString QCameraImageProcessing::tr(char const *, char const *, int)
+ ?staticMetaObject@QCameraFlashControl@@2UQMetaObject@@B @ 1361 NONAME ; struct QMetaObject const QCameraFlashControl::staticMetaObject
+ ?setManualShutterSpeed@QCameraExposure@@QAEXM@Z @ 1362 NONAME ; void QCameraExposure::setManualShutterSpeed(float)
+ ?mediaObject@QCameraViewfinder@@UBEPAVQMediaObject@@XZ @ 1363 NONAME ; class QMediaObject * QCameraViewfinder::mediaObject(void) const
+ ?setAutoAperture@QCameraExposure@@QAEXXZ @ 1364 NONAME ; void QCameraExposure::setAutoAperture(void)
+ ?tr@QCameraExposure@@SA?AVQString@@PBD0@Z @ 1365 NONAME ; class QString QCameraExposure::tr(char const *, char const *)
+ ?flashReady@QCameraExposureControl@@IAEX_N@Z @ 1366 NONAME ; void QCameraExposureControl::flashReady(bool)
+ ??1QCameraImageProcessingControl@@UAE@XZ @ 1367 NONAME ; QCameraImageProcessingControl::~QCameraImageProcessingControl(void)
+ ??1QCameraFocus@@EAE@XZ @ 1368 NONAME ; QCameraFocus::~QCameraFocus(void)
+ ?statusChanged@QCamera@@IAEXW4Status@1@@Z @ 1369 NONAME ; void QCamera::statusChanged(enum QCamera::Status)
+ ?apertureRangeChanged@QCameraExposure@@IAEXXZ @ 1370 NONAME ; void QCameraExposure::apertureRangeChanged(void)
+ ?getStaticMetaObject@QCameraFocus@@SAABUQMetaObject@@XZ @ 1371 NONAME ; struct QMetaObject const & QCameraFocus::getStaticMetaObject(void)
+ ??0QCameraImageProcessingControl@@IAE@PAVQObject@@@Z @ 1372 NONAME ; QCameraImageProcessingControl::QCameraImageProcessingControl(class QObject *)
+ ?setWhiteBalanceMode@QCameraImageProcessing@@QAEXW4WhiteBalanceMode@1@@Z @ 1373 NONAME ; void QCameraImageProcessing::setWhiteBalanceMode(enum QCameraImageProcessing::WhiteBalanceMode)
+ ??0QCamera@@QAE@ABVQByteArray@@PAVQObject@@@Z @ 1374 NONAME ; QCamera::QCamera(class QByteArray const &, class QObject *)
+ ?focusZonesChanged@QCameraFocusControl@@IAEXXZ @ 1375 NONAME ; void QCameraFocusControl::focusZonesChanged(void)
+ ?qt_metacall@QCameraImageCapture@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1376 NONAME ; int QCameraImageCapture::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?setStatus@QCameraFocusZone@@QAEXW4FocusZoneStatus@1@@Z @ 1377 NONAME ; void QCameraFocusZone::setStatus(enum QCameraFocusZone::FocusZoneStatus)
+ ?qt_metacall@QCameraFocusControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1378 NONAME ; int QCameraFocusControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?isFlashModeSupported@QCameraExposure@@QBE_NV?$QFlags@W4FlashMode@QCameraExposure@@@@@Z @ 1379 NONAME ; bool QCameraExposure::isFlashModeSupported(class QFlags<enum QCameraExposure::FlashMode>) const
+ ?imageSaved@QCameraImageCapture@@IAEXHABVQString@@@Z @ 1380 NONAME ; void QCameraImageCapture::imageSaved(int, class QString const &)
+ ?captureModeChanged@QCamera@@IAEXW4CaptureMode@1@@Z @ 1381 NONAME ; void QCamera::captureModeChanged(enum QCamera::CaptureMode)
+ ?getStaticMetaObject@QCameraFlashControl@@SAABUQMetaObject@@XZ @ 1382 NONAME ; struct QMetaObject const & QCameraFlashControl::getStaticMetaObject(void)
+ ?focusPointMode@QCameraFocus@@QBE?AW4FocusPointMode@1@XZ @ 1383 NONAME ; enum QCameraFocus::FocusPointMode QCameraFocus::focusPointMode(void) const
+ ?digitalZoom@QCameraFocus@@QBEMXZ @ 1384 NONAME ; float QCameraFocus::digitalZoom(void) const
+ ??8QCameraFocusZone@@QBE_NABV0@@Z @ 1385 NONAME ; bool QCameraFocusZone::operator==(class QCameraFocusZone const &) const
+ ?sharpeningLevel@QCameraImageProcessing@@QBEHXZ @ 1386 NONAME ; int QCameraImageProcessing::sharpeningLevel(void) const
+ ?tr@QCamera@@SA?AVQString@@PBD0H@Z @ 1387 NONAME ; class QString QCamera::tr(char const *, char const *, int)
+ ?setManualIsoSensitivity@QCameraExposure@@QAEXH@Z @ 1388 NONAME ; void QCameraExposure::setManualIsoSensitivity(int)
+ ?setManualWhiteBalance@QCameraImageProcessing@@QAEXH@Z @ 1389 NONAME ; void QCameraImageProcessing::setManualWhiteBalance(int)
+ ?isCaptureModeSupported@QCamera@@QBE_NW4CaptureMode@1@@Z @ 1390 NONAME ; bool QCamera::isCaptureModeSupported(enum QCamera::CaptureMode) const
+ ??0QCameraFlashControl@@IAE@PAVQObject@@@Z @ 1391 NONAME ; QCameraFlashControl::QCameraFlashControl(class QObject *)
+ ?focusZones@QCameraFocus@@QBE?AV?$QList@VQCameraFocusZone@@@@XZ @ 1392 NONAME ; class QList<class QCameraFocusZone> QCameraFocus::focusZones(void) const
+ ?shutterSpeed@QCameraExposure@@QBEMXZ @ 1393 NONAME ; float QCameraExposure::shutterSpeed(void) const
+ ?setManualAperture@QCameraExposure@@QAEXM@Z @ 1394 NONAME ; void QCameraExposure::setManualAperture(float)
+ ?setVideoOutput@QMediaImageViewer@@QAEXPAVQVideoWidget@@@Z @ 1395 NONAME ; void QMediaImageViewer::setVideoOutput(class QVideoWidget *)
+ ?trUtf8@QCameraLocksControl@@SA?AVQString@@PBD0H@Z @ 1396 NONAME ; class QString QCameraLocksControl::trUtf8(char const *, char const *, int)
+ ??1QCameraImageCapture@@UAE@XZ @ 1397 NONAME ; QCameraImageCapture::~QCameraImageCapture(void)
+ ?focusMode@QCameraFocus@@QBE?AW4FocusMode@1@XZ @ 1398 NONAME ; enum QCameraFocus::FocusMode QCameraFocus::focusMode(void) const
+ ??1QCameraImageProcessing@@EAE@XZ @ 1399 NONAME ; QCameraImageProcessing::~QCameraImageProcessing(void)
+ ?setFlashMode@QCameraExposure@@QAEXV?$QFlags@W4FlashMode@QCameraExposure@@@@@Z @ 1400 NONAME ; void QCameraExposure::setFlashMode(class QFlags<enum QCameraExposure::FlashMode>)
+ ?trUtf8@QCameraImageProcessingControl@@SA?AVQString@@PBD0@Z @ 1401 NONAME ; class QString QCameraImageProcessingControl::trUtf8(char const *, char const *)
+ ?lockStatusChanged@QCameraLocksControl@@IAEXW4LockType@QCamera@@W4LockStatus@3@W4LockChangeReason@3@@Z @ 1402 NONAME ; void QCameraLocksControl::lockStatusChanged(enum QCamera::LockType, enum QCamera::LockStatus, enum QCamera::LockChangeReason)
+ ??_EQCameraFocusControl@@UAE@I@Z @ 1403 NONAME ; QCameraFocusControl::~QCameraFocusControl(unsigned int)
+ ?lockStatus@QCamera@@QBE?AW4LockStatus@1@XZ @ 1404 NONAME ; enum QCamera::LockStatus QCamera::lockStatus(void) const
+ ?imageCaptured@QCameraImageCaptureControl@@IAEXHABVQImage@@@Z @ 1405 NONAME ; void QCameraImageCaptureControl::imageCaptured(int, class QImage const &)
+ ?aperture@QCameraExposure@@QBEMXZ @ 1406 NONAME ; float QCameraExposure::aperture(void) const
+ ?staticMetaObject@QCameraImageCaptureControl@@2UQMetaObject@@B @ 1407 NONAME ; struct QMetaObject const QCameraImageCaptureControl::staticMetaObject
+ ?isWhiteBalanceModeSupported@QCameraImageProcessing@@QBE_NW4WhiteBalanceMode@1@@Z @ 1408 NONAME ; bool QCameraImageProcessing::isWhiteBalanceModeSupported(enum QCameraImageProcessing::WhiteBalanceMode) const
+ ?maximumOpticalZoom@QCameraFocus@@QBEMXZ @ 1409 NONAME ; float QCameraFocus::maximumOpticalZoom(void) const
+ ?qt_metacast@QCameraFocus@@UAEPAXPBD@Z @ 1410 NONAME ; void * QCameraFocus::qt_metacast(char const *)
+ ?imageProcessing@QCamera@@QBEPAVQCameraImageProcessing@@XZ @ 1411 NONAME ; class QCameraImageProcessing * QCamera::imageProcessing(void) const
+ ?digitalZoomChanged@QCameraFocusControl@@IAEXM@Z @ 1412 NONAME ; void QCameraFocusControl::digitalZoomChanged(float)
+ ??0QCameraExposureControl@@IAE@PAVQObject@@@Z @ 1413 NONAME ; QCameraExposureControl::QCameraExposureControl(class QObject *)
+ ?setMediaObject@QCameraImageCapture@@MAE_NPAVQMediaObject@@@Z @ 1414 NONAME ; bool QCameraImageCapture::setMediaObject(class QMediaObject *)
+ ?getStaticMetaObject@QCameraControl@@SAABUQMetaObject@@XZ @ 1415 NONAME ; struct QMetaObject const & QCameraControl::getStaticMetaObject(void)
+ ?setFocusMode@QCameraFocus@@QAEXW4FocusMode@1@@Z @ 1416 NONAME ; void QCameraFocus::setFocusMode(enum QCameraFocus::FocusMode)
+ ?isoSensitivityChanged@QCameraExposure@@IAEXH@Z @ 1417 NONAME ; void QCameraExposure::isoSensitivityChanged(int)
+ ?supportedImageCodecs@QCameraImageCapture@@QBE?AVQStringList@@XZ @ 1418 NONAME ; class QStringList QCameraImageCapture::supportedImageCodecs(void) const
+ ?imageCaptured@QCameraImageCapture@@IAEXHABVQImage@@@Z @ 1419 NONAME ; void QCameraImageCapture::imageCaptured(int, class QImage const &)
+ ?qt_metacast@QCameraLocksControl@@UAEPAXPBD@Z @ 1420 NONAME ; void * QCameraLocksControl::qt_metacast(char const *)
+ ?qt_metacast@QCameraFocusControl@@UAEPAXPBD@Z @ 1421 NONAME ; void * QCameraFocusControl::qt_metacast(char const *)
+ ?trUtf8@QCameraImageCaptureControl@@SA?AVQString@@PBD0H@Z @ 1422 NONAME ; class QString QCameraImageCaptureControl::trUtf8(char const *, char const *, int)
+ ?trUtf8@QCameraViewfinder@@SA?AVQString@@PBD0@Z @ 1423 NONAME ; class QString QCameraViewfinder::trUtf8(char const *, char const *)
+ ?getStaticMetaObject@QCameraExposure@@SAABUQMetaObject@@XZ @ 1424 NONAME ; struct QMetaObject const & QCameraExposure::getStaticMetaObject(void)
+ ?trUtf8@QCamera@@SA?AVQString@@PBD0H@Z @ 1425 NONAME ; class QString QCamera::trUtf8(char const *, char const *, int)
+ ?tr@QCameraExposureControl@@SA?AVQString@@PBD0H@Z @ 1426 NONAME ; class QString QCameraExposureControl::tr(char const *, char const *, int)
+ ?trUtf8@QCameraFocus@@SA?AVQString@@PBD0H@Z @ 1427 NONAME ; class QString QCameraFocus::trUtf8(char const *, char const *, int)
+ ?playlist@QMediaImageViewer@@QBEPAVQMediaPlaylist@@XZ @ 1428 NONAME ; class QMediaPlaylist * QMediaImageViewer::playlist(void) const
+ ?qt_metacall@QCameraViewfinder@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1429 NONAME ; int QCameraViewfinder::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?unlock@QCamera@@QAEXXZ @ 1430 NONAME ; void QCamera::unlock(void)
+ ?supportedIsoSensitivities@QCameraExposure@@QBE?AV?$QList@H@@PA_N@Z @ 1431 NONAME ; class QList<int> QCameraExposure::supportedIsoSensitivities(bool *) const
+ ?staticMetaObject@QCameraImageProcessing@@2UQMetaObject@@B @ 1432 NONAME ; struct QMetaObject const QCameraImageProcessing::staticMetaObject
+ ?staticMetaObject@QCameraViewfinder@@2UQMetaObject@@B @ 1433 NONAME ; struct QMetaObject const QCameraViewfinder::staticMetaObject
+ ?d_func@QCameraImageProcessing@@ABEPBVQCameraImageProcessingPrivate@@XZ @ 1434 NONAME ; class QCameraImageProcessingPrivate const * QCameraImageProcessing::d_func(void) const
+ ?isAvailable@QCameraImageCapture@@QBE_NXZ @ 1435 NONAME ; bool QCameraImageCapture::isAvailable(void) const
+ ?setExposureCompensation@QCameraExposure@@QAEXM@Z @ 1436 NONAME ; void QCameraExposure::setExposureCompensation(float)
+ ??1QCameraExposure@@EAE@XZ @ 1437 NONAME ; QCameraExposure::~QCameraExposure(void)
+ ?isAvailable@QCameraExposure@@QBE_NXZ @ 1438 NONAME ; bool QCameraExposure::isAvailable(void) const
+ ?qt_metacall@QCameraImageProcessingControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1439 NONAME ; int QCameraImageProcessingControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?setDenoisingLevel@QCameraImageProcessing@@QAEXH@Z @ 1440 NONAME ; void QCameraImageProcessing::setDenoisingLevel(int)
+ ?tr@QCameraFocusControl@@SA?AVQString@@PBD0H@Z @ 1441 NONAME ; class QString QCameraFocusControl::tr(char const *, char const *, int)
+ ?tr@QCameraFlashControl@@SA?AVQString@@PBD0H@Z @ 1442 NONAME ; class QString QCameraFlashControl::tr(char const *, char const *, int)
+ ?area@QCameraFocusZone@@QBE?AVQRectF@@XZ @ 1443 NONAME ; class QRectF QCameraFocusZone::area(void) const
+ ??_EQCameraImageCapture@@UAE@I@Z @ 1444 NONAME ; QCameraImageCapture::~QCameraImageCapture(unsigned int)
+ ?status@QCamera@@QBE?AW4Status@1@XZ @ 1445 NONAME ; enum QCamera::Status QCamera::status(void) const
+ ?isSharpeningSupported@QCameraImageProcessing@@QBE_NXZ @ 1446 NONAME ; bool QCameraImageProcessing::isSharpeningSupported(void) const
+ ?mediaObject@QCameraImageCapture@@UBEPAVQMediaObject@@XZ @ 1447 NONAME ; class QMediaObject * QCameraImageCapture::mediaObject(void) const
+ ?trUtf8@QCameraViewfinder@@SA?AVQString@@PBD0H@Z @ 1448 NONAME ; class QString QCameraViewfinder::trUtf8(char const *, char const *, int)
+ ?d_func@QCameraImageCapture@@AAEPAVQCameraImageCapturePrivate@@XZ @ 1449 NONAME ; class QCameraImageCapturePrivate * QCameraImageCapture::d_func(void)
+ ?status@QCameraFocusZone@@QBE?AW4FocusZoneStatus@1@XZ @ 1450 NONAME ; enum QCameraFocusZone::FocusZoneStatus QCameraFocusZone::status(void) const
+ ?error@QCameraControl@@IAEXHABVQString@@@Z @ 1451 NONAME ; void QCameraControl::error(int, class QString const &)
+ ?metaObject@QCameraImageProcessingControl@@UBEPBUQMetaObject@@XZ @ 1452 NONAME ; struct QMetaObject const * QCameraImageProcessingControl::metaObject(void) const
+ ?qt_metacall@QCameraFocus@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1453 NONAME ; int QCameraFocus::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ??0QCameraFocusZone@@QAE@ABV0@@Z @ 1454 NONAME ; QCameraFocusZone::QCameraFocusZone(class QCameraFocusZone const &)
+ ?setSharpeningLevel@QCameraImageProcessing@@QAEXH@Z @ 1455 NONAME ; void QCameraImageProcessing::setSharpeningLevel(int)
+ ?qt_metacast@QCameraImageCapture@@UAEPAXPBD@Z @ 1456 NONAME ; void * QCameraImageCapture::qt_metacast(char const *)
+ ?tr@QCameraImageProcessingControl@@SA?AVQString@@PBD0H@Z @ 1457 NONAME ; class QString QCameraImageProcessingControl::tr(char const *, char const *, int)
+ ?captureMode@QCamera@@QBE?AW4CaptureMode@1@XZ @ 1458 NONAME ; enum QCamera::CaptureMode QCamera::captureMode(void) const
+ ?isDenoisingSupported@QCameraImageProcessing@@QBE_NXZ @ 1459 NONAME ; bool QCameraImageProcessing::isDenoisingSupported(void) const
+ ?shutterSpeedRangeChanged@QCameraExposure@@IAEXXZ @ 1460 NONAME ; void QCameraExposure::shutterSpeedRangeChanged(void)
+ ??0QCameraFocusZone@@QAE@ABVQRectF@@W4FocusZoneStatus@0@@Z @ 1461 NONAME ; QCameraFocusZone::QCameraFocusZone(class QRectF const &, enum QCameraFocusZone::FocusZoneStatus)
+ ?qt_metacast@QCameraControl@@UAEPAXPBD@Z @ 1462 NONAME ; void * QCameraControl::qt_metacast(char const *)
+ ?statusChanged@QCameraControl@@IAEXW4Status@QCamera@@@Z @ 1463 NONAME ; void QCameraControl::statusChanged(enum QCamera::Status)
+ ?zoomTo@QCameraFocus@@QAEXMM@Z @ 1464 NONAME ; void QCameraFocus::zoomTo(float, float)
+ ??1QCameraFocusZone@@QAE@XZ @ 1465 NONAME ; QCameraFocusZone::~QCameraFocusZone(void)
+ ?d_func@QCameraExposure@@ABEPBVQCameraExposurePrivate@@XZ @ 1466 NONAME ; class QCameraExposurePrivate const * QCameraExposure::d_func(void) const
+ ?tr@QCameraViewfinder@@SA?AVQString@@PBD0H@Z @ 1467 NONAME ; class QString QCameraViewfinder::tr(char const *, char const *, int)
+ ?qt_metacall@QCamera@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1468 NONAME ; int QCamera::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?availabilityError@QCameraImageCapture@@QBE?AW4AvailabilityError@QtMultimediaKit@@XZ @ 1469 NONAME ; enum QtMultimediaKit::AvailabilityError QCameraImageCapture::availabilityError(void) const
+ ??_EQCamera@@UAE@I@Z @ 1470 NONAME ; QCamera::~QCamera(unsigned int)
+ ?trUtf8@QCameraControl@@SA?AVQString@@PBD0H@Z @ 1471 NONAME ; class QString QCameraControl::trUtf8(char const *, char const *, int)
+ ?metaObject@QCameraFocusControl@@UBEPBUQMetaObject@@XZ @ 1472 NONAME ; struct QMetaObject const * QCameraFocusControl::metaObject(void) const
+ ?metaObject@QCameraFlashControl@@UBEPBUQMetaObject@@XZ @ 1473 NONAME ; struct QMetaObject const * QCameraFlashControl::metaObject(void) const
+ ?maximumDigitalZoom@QCameraFocus@@QBEMXZ @ 1474 NONAME ; float QCameraFocus::maximumDigitalZoom(void) const
+ ?error@QCamera@@IAEXW4Error@1@@Z @ 1475 NONAME ; void QCamera::error(enum QCamera::Error)
+ ?isFocusModeSupported@QCameraFocus@@QBE_NW4FocusMode@1@@Z @ 1476 NONAME ; bool QCameraFocus::isFocusModeSupported(enum QCameraFocus::FocusMode) const
+ ?locked@QCamera@@IAEXXZ @ 1477 NONAME ; void QCamera::locked(void)
+ ?supportedResolutions@QCameraImageCapture@@QBE?AV?$QList@VQSize@@@@ABVQImageEncoderSettings@@PA_N@Z @ 1478 NONAME ; class QList<class QSize> QCameraImageCapture::supportedResolutions(class QImageEncoderSettings const &, bool *) const
+ ?qt_metacall@QCameraImageCaptureControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1479 NONAME ; int QCameraImageCaptureControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?tr@QCameraLocksControl@@SA?AVQString@@PBD0@Z @ 1480 NONAME ; class QString QCameraLocksControl::tr(char const *, char const *)
+ ?stateChanged@QCamera@@IAEXW4State@1@@Z @ 1481 NONAME ; void QCamera::stateChanged(enum QCamera::State)
+ ?lockStatus@QCamera@@QBE?AW4LockStatus@1@W4LockType@1@@Z @ 1482 NONAME ; enum QCamera::LockStatus QCamera::lockStatus(enum QCamera::LockType) const
+ ?exposureMode@QCameraExposure@@QBE?AW4ExposureMode@1@XZ @ 1483 NONAME ; enum QCameraExposure::ExposureMode QCameraExposure::exposureMode(void) const
+ ??1QCameraLocksControl@@UAE@XZ @ 1484 NONAME ; QCameraLocksControl::~QCameraLocksControl(void)
+ ?requestedLocks@QCamera@@QBE?AV?$QFlags@W4LockType@QCamera@@@@XZ @ 1485 NONAME ; class QFlags<enum QCamera::LockType> QCamera::requestedLocks(void) const
+ ?trUtf8@QCameraControl@@SA?AVQString@@PBD0@Z @ 1486 NONAME ; class QString QCameraControl::trUtf8(char const *, char const *)
+ ?supportedLocks@QCamera@@QBE?AV?$QFlags@W4LockType@QCamera@@@@XZ @ 1487 NONAME ; class QFlags<enum QCamera::LockType> QCamera::supportedLocks(void) const
+ ??0QCameraImageCapture@@QAE@PAVQMediaObject@@PAVQObject@@@Z @ 1488 NONAME ; QCameraImageCapture::QCameraImageCapture(class QMediaObject *, class QObject *)
+ ?d_func@QCameraImageProcessing@@AAEPAVQCameraImageProcessingPrivate@@XZ @ 1489 NONAME ; class QCameraImageProcessingPrivate * QCameraImageProcessing::d_func(void)
+ ?isMeteringModeSupported@QCameraExposure@@QBE_NW4MeteringMode@1@@Z @ 1490 NONAME ; bool QCameraExposure::isMeteringModeSupported(enum QCameraExposure::MeteringMode) const
+ ?start@QCamera@@QAEXXZ @ 1491 NONAME ; void QCamera::start(void)
+ ?staticMetaObject@QCamera@@2UQMetaObject@@B @ 1492 NONAME ; struct QMetaObject const QCamera::staticMetaObject
+ ??0QCamera@@QAE@PAVQObject@@PAVQMediaServiceProvider@@@Z @ 1493 NONAME ; QCamera::QCamera(class QObject *, class QMediaServiceProvider *)
+ ?tr@QCameraImageCapture@@SA?AVQString@@PBD0@Z @ 1494 NONAME ; class QString QCameraImageCapture::tr(char const *, char const *)
+ ?trUtf8@QCameraExposure@@SA?AVQString@@PBD0H@Z @ 1495 NONAME ; class QString QCameraExposure::trUtf8(char const *, char const *, int)
+ ?staticMetaObject@QCameraImageProcessingControl@@2UQMetaObject@@B @ 1496 NONAME ; struct QMetaObject const QCameraImageProcessingControl::staticMetaObject
+ ?lockStatusChanged@QCamera@@IAEXW4LockStatus@1@W4LockChangeReason@1@@Z @ 1497 NONAME ; void QCamera::lockStatusChanged(enum QCamera::LockStatus, enum QCamera::LockChangeReason)
+ ?setAutoShutterSpeed@QCameraExposure@@QAEXXZ @ 1498 NONAME ; void QCameraExposure::setAutoShutterSpeed(void)
+ ?captureModeChanged@QCameraControl@@IAEXW4CaptureMode@QCamera@@@Z @ 1499 NONAME ; void QCameraControl::captureModeChanged(enum QCamera::CaptureMode)
+ ?trUtf8@QCameraImageProcessing@@SA?AVQString@@PBD0H@Z @ 1500 NONAME ; class QString QCameraImageProcessing::trUtf8(char const *, char const *, int)
+ ??_EQCameraExposure@@UAE@I@Z @ 1501 NONAME ; QCameraExposure::~QCameraExposure(unsigned int)
+ ?flashReady@QCameraFlashControl@@IAEX_N@Z @ 1502 NONAME ; void QCameraFlashControl::flashReady(bool)
+ ??_EQCameraImageProcessing@@UAE@I@Z @ 1503 NONAME ; QCameraImageProcessing::~QCameraImageProcessing(unsigned int)
+ ?imageExposed@QCameraImageCapture@@IAEXH@Z @ 1504 NONAME ; void QCameraImageCapture::imageExposed(int)
+ ?deviceDescription@QCamera@@SA?AVQString@@ABVQByteArray@@@Z @ 1505 NONAME ; class QString QCamera::deviceDescription(class QByteArray const &)
+ ?staticMetaObject@QCameraImageCapture@@2UQMetaObject@@B @ 1506 NONAME ; struct QMetaObject const QCameraImageCapture::staticMetaObject
+ ?qt_metacast@QCameraExposureControl@@UAEPAXPBD@Z @ 1507 NONAME ; void * QCameraExposureControl::qt_metacast(char const *)
+ ??0QCameraImageProcessing@@AAE@PAVQCamera@@@Z @ 1508 NONAME ; QCameraImageProcessing::QCameraImageProcessing(class QCamera *)
+ ?tr@QCameraLocksControl@@SA?AVQString@@PBD0H@Z @ 1509 NONAME ; class QString QCameraLocksControl::tr(char const *, char const *, int)
+ ?unload@QCamera@@QAEXXZ @ 1510 NONAME ; void QCamera::unload(void)
+ ?setVideoOutput@QMediaImageViewer@@QAEXPAVQGraphicsVideoItem@@@Z @ 1511 NONAME ; void QMediaImageViewer::setVideoOutput(class QGraphicsVideoItem *)
+ ?setCustomFocusPoint@QCameraFocus@@QAEXABVQPointF@@@Z @ 1512 NONAME ; void QCameraFocus::setCustomFocusPoint(class QPointF const &)
+ ?trUtf8@QCameraFocus@@SA?AVQString@@PBD0@Z @ 1513 NONAME ; class QString QCameraFocus::trUtf8(char const *, char const *)
+ ?qt_metacall@QCameraFlashControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1514 NONAME ; int QCameraFlashControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?tr@QCameraFocusControl@@SA?AVQString@@PBD0@Z @ 1515 NONAME ; class QString QCameraFocusControl::tr(char const *, char const *)
+ ?d_func@QCameraFocus@@ABEPBVQCameraFocusPrivate@@XZ @ 1516 NONAME ; class QCameraFocusPrivate const * QCameraFocus::d_func(void) const
+ ?getStaticMetaObject@QCamera@@SAABUQMetaObject@@XZ @ 1517 NONAME ; struct QMetaObject const & QCamera::getStaticMetaObject(void)
+ ?qt_metacast@QCameraViewfinder@@UAEPAXPBD@Z @ 1518 NONAME ; void * QCameraViewfinder::qt_metacast(char const *)
+ ?trUtf8@QCameraImageCapture@@SA?AVQString@@PBD0H@Z @ 1519 NONAME ; class QString QCameraImageCapture::trUtf8(char const *, char const *, int)
+ ?tr@QCameraControl@@SA?AVQString@@PBD0@Z @ 1520 NONAME ; class QString QCameraControl::tr(char const *, char const *)
+ ?apertureChanged@QCameraExposure@@IAEXM@Z @ 1521 NONAME ; void QCameraExposure::apertureChanged(float)
+ ?d_func@QCamera@@AAEPAVQCameraPrivate@@XZ @ 1522 NONAME ; class QCameraPrivate * QCamera::d_func(void)
+ ??_EQCameraFocus@@UAE@I@Z @ 1523 NONAME ; QCameraFocus::~QCameraFocus(unsigned int)
+ ??_EQCameraImageCaptureControl@@UAE@I@Z @ 1524 NONAME ; QCameraImageCaptureControl::~QCameraImageCaptureControl(unsigned int)
+ ?imageCodecDescription@QCameraImageCapture@@QBE?AVQString@@ABV2@@Z @ 1525 NONAME ; class QString QCameraImageCapture::imageCodecDescription(class QString const &) const
+ ??_EQCameraExposureControl@@UAE@I@Z @ 1526 NONAME ; QCameraExposureControl::~QCameraExposureControl(unsigned int)
+ ?setSaturation@QCameraImageProcessing@@QAEXH@Z @ 1527 NONAME ; void QCameraImageProcessing::setSaturation(int)
+ ?tr@QCameraImageProcessingControl@@SA?AVQString@@PBD0@Z @ 1528 NONAME ; class QString QCameraImageProcessingControl::tr(char const *, char const *)
+ ?setMeteringMode@QCameraExposure@@QAEXW4MeteringMode@1@@Z @ 1529 NONAME ; void QCameraExposure::setMeteringMode(enum QCameraExposure::MeteringMode)
+ ?isFlashReady@QCameraExposure@@QBE_NXZ @ 1530 NONAME ; bool QCameraExposure::isFlashReady(void) const
+ ?denoisingLevel@QCameraImageProcessing@@QBEHXZ @ 1531 NONAME ; int QCameraImageProcessing::denoisingLevel(void) const
+ ?qt_metacast@QCameraImageProcessing@@UAEPAXPBD@Z @ 1532 NONAME ; void * QCameraImageProcessing::qt_metacast(char const *)
+ ??1QCameraFlashControl@@UAE@XZ @ 1533 NONAME ; QCameraFlashControl::~QCameraFlashControl(void)
+ ?tr@QCameraFocus@@SA?AVQString@@PBD0H@Z @ 1534 NONAME ; class QString QCameraFocus::tr(char const *, char const *, int)
+ ?metaObject@QCameraControl@@UBEPBUQMetaObject@@XZ @ 1535 NONAME ; struct QMetaObject const * QCameraControl::metaObject(void) const
+ ?setNativeResolution@QAbstractVideoSurface@@IAEXABVQSize@@@Z @ 1536 NONAME ; void QAbstractVideoSurface::setNativeResolution(class QSize const &)
+ ?searchAndLock@QCamera@@QAEXV?$QFlags@W4LockType@QCamera@@@@@Z @ 1537 NONAME ; void QCamera::searchAndLock(class QFlags<enum QCamera::LockType>)
+ ?meteringMode@QCameraExposure@@QBE?AW4MeteringMode@1@XZ @ 1538 NONAME ; enum QCameraExposure::MeteringMode QCameraExposure::meteringMode(void) const
+ ??_EQCameraFlashControl@@UAE@I@Z @ 1539 NONAME ; QCameraFlashControl::~QCameraFlashControl(unsigned int)
+ ?d_func@QCameraViewfinder@@AAEPAVQCameraViewfinderPrivate@@XZ @ 1540 NONAME ; class QCameraViewfinderPrivate * QCameraViewfinder::d_func(void)
+ ?metaObject@QCameraFocus@@UBEPBUQMetaObject@@XZ @ 1541 NONAME ; struct QMetaObject const * QCameraFocus::metaObject(void) const
+ ?metaObject@QCameraLocksControl@@UBEPBUQMetaObject@@XZ @ 1542 NONAME ; struct QMetaObject const * QCameraLocksControl::metaObject(void) const
+ ?errorString@QCamera@@QBE?AVQString@@XZ @ 1543 NONAME ; class QString QCamera::errorString(void) const
+ ?staticMetaObject@QCameraExposureControl@@2UQMetaObject@@B @ 1544 NONAME ; struct QMetaObject const QCameraExposureControl::staticMetaObject
+ ?supportedApertures@QCameraExposure@@QBE?AV?$QList@M@@PA_N@Z @ 1545 NONAME ; class QList<float> QCameraExposure::supportedApertures(bool *) const
+ ?focusZonesChanged@QCameraFocus@@IAEXXZ @ 1546 NONAME ; void QCameraFocus::focusZonesChanged(void)
+ ?qt_metacast@QCameraImageCaptureControl@@UAEPAXPBD@Z @ 1547 NONAME ; void * QCameraImageCaptureControl::qt_metacast(char const *)
+ ?tr@QCameraControl@@SA?AVQString@@PBD0H@Z @ 1548 NONAME ; class QString QCameraControl::tr(char const *, char const *, int)
+ ?digitalZoomChanged@QCameraFocus@@IAEXM@Z @ 1549 NONAME ; void QCameraFocus::digitalZoomChanged(float)
+ ?metaObject@QCamera@@UBEPBUQMetaObject@@XZ @ 1550 NONAME ; struct QMetaObject const * QCamera::metaObject(void) const
+ ?trUtf8@QCameraExposureControl@@SA?AVQString@@PBD0@Z @ 1551 NONAME ; class QString QCameraExposureControl::trUtf8(char const *, char const *)
+ ?imageExposed@QCameraImageCaptureControl@@IAEXH@Z @ 1552 NONAME ; void QCameraImageCaptureControl::imageExposed(int)
+ ?tr@QCameraImageCaptureControl@@SA?AVQString@@PBD0@Z @ 1553 NONAME ; class QString QCameraImageCaptureControl::tr(char const *, char const *)
+ ?trUtf8@QCameraLocksControl@@SA?AVQString@@PBD0@Z @ 1554 NONAME ; class QString QCameraLocksControl::trUtf8(char const *, char const *)
+ ?isAvailable@QCamera@@UBE_NXZ @ 1555 NONAME ; bool QCamera::isAvailable(void) const
+ ?stateChanged@QCameraControl@@IAEXW4State@QCamera@@@Z @ 1556 NONAME ; void QCameraControl::stateChanged(enum QCamera::State)
+ ?nativeResolution@QAbstractVideoSurface@@QBE?AVQSize@@XZ @ 1557 NONAME ; class QSize QAbstractVideoSurface::nativeResolution(void) const
+ ??0QCameraFocusZone@@QAE@XZ @ 1558 NONAME ; QCameraFocusZone::QCameraFocusZone(void)
+ ?trUtf8@QCameraImageProcessing@@SA?AVQString@@PBD0@Z @ 1559 NONAME ; class QString QCameraImageProcessing::trUtf8(char const *, char const *)
+ ?exposureParameterRangeChanged@QCameraExposureControl@@IAEXH@Z @ 1560 NONAME ; void QCameraExposureControl::exposureParameterRangeChanged(int)
+ ?lockFailed@QCamera@@IAEXXZ @ 1561 NONAME ; void QCamera::lockFailed(void)
+ ?d_func@QCameraExposure@@AAEPAVQCameraExposurePrivate@@XZ @ 1562 NONAME ; class QCameraExposurePrivate * QCameraExposure::d_func(void)
+ ?isoSensitivity@QCameraExposure@@QBEHXZ @ 1563 NONAME ; int QCameraExposure::isoSensitivity(void) const
+ ?qt_metacall@QCameraExposureControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1564 NONAME ; int QCameraExposureControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?setExposureMode@QCameraExposure@@QAEXW4ExposureMode@1@@Z @ 1565 NONAME ; void QCameraExposure::setExposureMode(enum QCameraExposure::ExposureMode)
+ ?d_func@QCameraViewfinder@@ABEPBVQCameraViewfinderPrivate@@XZ @ 1566 NONAME ; class QCameraViewfinderPrivate const * QCameraViewfinder::d_func(void) const
+ ?trUtf8@QCameraImageCapture@@SA?AVQString@@PBD0@Z @ 1567 NONAME ; class QString QCameraImageCapture::trUtf8(char const *, char const *)
+ ?metaObject@QCameraImageProcessing@@UBEPBUQMetaObject@@XZ @ 1568 NONAME ; struct QMetaObject const * QCameraImageProcessing::metaObject(void) const
+ ?setMediaObject@QCameraViewfinder@@MAE_NPAVQMediaObject@@@Z @ 1569 NONAME ; bool QCameraViewfinder::setMediaObject(class QMediaObject *)
+ ?capture@QCameraImageCapture@@QAEHABVQString@@@Z @ 1570 NONAME ; int QCameraImageCapture::capture(class QString const &)
+ ??0QCameraImageCaptureControl@@IAE@PAVQObject@@@Z @ 1571 NONAME ; QCameraImageCaptureControl::QCameraImageCaptureControl(class QObject *)
+ ?trUtf8@QCameraExposureControl@@SA?AVQString@@PBD0H@Z @ 1572 NONAME ; class QString QCameraExposureControl::trUtf8(char const *, char const *, int)
+ ?tr@QCamera@@SA?AVQString@@PBD0@Z @ 1573 NONAME ; class QString QCamera::tr(char const *, char const *)
+ ?setViewfinder@QCamera@@QAEXPAVQVideoWidget@@@Z @ 1574 NONAME ; void QCamera::setViewfinder(class QVideoWidget *)
+ ?tr@QCameraFlashControl@@SA?AVQString@@PBD0@Z @ 1575 NONAME ; class QString QCameraFlashControl::tr(char const *, char const *)
+ ?customFocusPoint@QCameraFocus@@QBE?AVQPointF@@XZ @ 1576 NONAME ; class QPointF QCameraFocus::customFocusPoint(void) const
+ ??0QCameraExposure@@AAE@PAVQCamera@@@Z @ 1577 NONAME ; QCameraExposure::QCameraExposure(class QCamera *)
+ ?shutterSpeedChanged@QCameraExposure@@IAEXM@Z @ 1578 NONAME ; void QCameraExposure::shutterSpeedChanged(float)
+ ?qt_metacast@QCameraImageProcessingControl@@UAEPAXPBD@Z @ 1579 NONAME ; void * QCameraImageProcessingControl::qt_metacast(char const *)
+ ?error@QCameraImageCapture@@QBE?AW4Error@1@XZ @ 1580 NONAME ; enum QCameraImageCapture::Error QCameraImageCapture::error(void) const
+ ?state@QCamera@@QBE?AW4State@1@XZ @ 1581 NONAME ; enum QCamera::State QCamera::state(void) const
+ ?availabilityError@QCamera@@UBE?AW4AvailabilityError@QtMultimediaKit@@XZ @ 1582 NONAME ; enum QtMultimediaKit::AvailabilityError QCamera::availabilityError(void) const
+ ?cancelCapture@QCameraImageCapture@@QAEXXZ @ 1583 NONAME ; void QCameraImageCapture::cancelCapture(void)
+ ?trUtf8@QCamera@@SA?AVQString@@PBD0@Z @ 1584 NONAME ; class QString QCamera::trUtf8(char const *, char const *)
+ ?isExposureModeSupported@QCameraExposure@@QBE_NW4ExposureMode@1@@Z @ 1585 NONAME ; bool QCameraExposure::isExposureModeSupported(enum QCameraExposure::ExposureMode) const
+ ??0QCameraControl@@IAE@PAVQObject@@@Z @ 1586 NONAME ; QCameraControl::QCameraControl(class QObject *)
+ ?tr@QCameraExposure@@SA?AVQString@@PBD0H@Z @ 1587 NONAME ; class QString QCameraExposure::tr(char const *, char const *, int)
+ ?getStaticMetaObject@QCameraViewfinder@@SAABUQMetaObject@@XZ @ 1588 NONAME ; struct QMetaObject const & QCameraViewfinder::getStaticMetaObject(void)
+ ?stop@QSoundEffect@@QAEXXZ @ 1589 NONAME ; void QSoundEffect::stop(void)
+ ?loadedChanged@QSoundEffect@@IAEXXZ @ 1590 NONAME ; void QSoundEffect::loadedChanged(void)
+ ?isLoaded@QSoundEffect@@QBE_NXZ @ 1591 NONAME ; bool QSoundEffect::isLoaded(void) const
+ ?loopCountChanged@QSoundEffect@@IAEXXZ @ 1592 NONAME ; void QSoundEffect::loopCountChanged(void)
+ ?maximumOpticalZoomChanged@QCameraFocusControl@@IAEXM@Z @ 1593 NONAME ; void QCameraFocusControl::maximumOpticalZoomChanged(float)
+ ?maximumDigitalZoomChanged@QCameraFocus@@IAEXM@Z @ 1594 NONAME ; void QCameraFocus::maximumDigitalZoomChanged(float)
+ ?loopCount@QSoundEffect@@QBEHXZ @ 1595 NONAME ; int QSoundEffect::loopCount(void) const
+ ?supportedMimeTypes@QSoundEffect@@SA?AVQStringList@@XZ @ 1596 NONAME ; class QStringList QSoundEffect::supportedMimeTypes(void)
+ ?setLoopCount@QSoundEffect@@QAEXH@Z @ 1597 NONAME ; void QSoundEffect::setLoopCount(int)
+ ?maximumDigitalZoomChanged@QCameraFocusControl@@IAEXM@Z @ 1598 NONAME ; void QCameraFocusControl::maximumDigitalZoomChanged(float)
+ ?maximumOpticalZoomChanged@QCameraFocus@@IAEXM@Z @ 1599 NONAME ; void QCameraFocus::maximumOpticalZoomChanged(float)
+ ?status@QSoundEffect@@QBE?AW4Status@1@XZ @ 1600 NONAME ; enum QSoundEffect::Status QSoundEffect::status(void) const
+ ?playingChanged@QSoundEffect@@IAEXXZ @ 1601 NONAME ; void QSoundEffect::playingChanged(void)
+ ?isPlaying@QSoundEffect@@QBE_NXZ @ 1602 NONAME ; bool QSoundEffect::isPlaying(void) const
+ ?statusChanged@QSoundEffect@@IAEXXZ @ 1603 NONAME ; void QSoundEffect::statusChanged(void)
+ ?qt_metacall@QMediaNetworkAccessControl@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1604 NONAME ; int QMediaNetworkAccessControl::qt_metacall(enum QMetaObject::Call, int, void * *)
+ ?getStaticMetaObject@QMediaNetworkAccessControl@@SAABUQMetaObject@@XZ @ 1605 NONAME ; struct QMetaObject const & QMediaNetworkAccessControl::getStaticMetaObject(void)
+ ?tr@QMediaNetworkAccessControl@@SA?AVQString@@PBD0H@Z @ 1606 NONAME ; class QString QMediaNetworkAccessControl::tr(char const *, char const *, int)
+ ?setViewfinder@QCamera@@QAEXPAVQAbstractVideoSurface@@@Z @ 1607 NONAME ; void QCamera::setViewfinder(class QAbstractVideoSurface *)
+ ?trUtf8@QMediaNetworkAccessControl@@SA?AVQString@@PBD0@Z @ 1608 NONAME ; class QString QMediaNetworkAccessControl::trUtf8(char const *, char const *)
+ ?metaObject@QMediaNetworkAccessControl@@UBEPBUQMetaObject@@XZ @ 1609 NONAME ; struct QMetaObject const * QMediaNetworkAccessControl::metaObject(void) const
+ ?staticMetaObject@QMediaNetworkAccessControl@@2UQMetaObject@@B @ 1610 NONAME ; struct QMetaObject const QMediaNetworkAccessControl::staticMetaObject
+ ?setNetworkConfigurations@QMediaPlayer@@QAEXABV?$QList@VQNetworkConfiguration@@@@@Z @ 1611 NONAME ; void QMediaPlayer::setNetworkConfigurations(class QList<class QNetworkConfiguration> const &)
+ ?setVideoOutput@QMediaPlayer@@QAEXPAVQAbstractVideoSurface@@@Z @ 1612 NONAME ; void QMediaPlayer::setVideoOutput(class QAbstractVideoSurface *)
+ ?networkConfigurationChanged@QMediaPlayer@@IAEXABVQNetworkConfiguration@@@Z @ 1613 NONAME ; void QMediaPlayer::networkConfigurationChanged(class QNetworkConfiguration const &)
+ ??_EQMediaNetworkAccessControl@@UAE@I@Z @ 1614 NONAME ; QMediaNetworkAccessControl::~QMediaNetworkAccessControl(unsigned int)
+ ??0QMediaNetworkAccessControl@@IAE@PAVQObject@@@Z @ 1615 NONAME ; QMediaNetworkAccessControl::QMediaNetworkAccessControl(class QObject *)
+ ?trUtf8@QMediaNetworkAccessControl@@SA?AVQString@@PBD0H@Z @ 1616 NONAME ; class QString QMediaNetworkAccessControl::trUtf8(char const *, char const *, int)
+ ?currentNetworkConfiguration@QMediaPlayer@@QBE?AVQNetworkConfiguration@@XZ @ 1617 NONAME ; class QNetworkConfiguration QMediaPlayer::currentNetworkConfiguration(void) const
+ ??1QMediaNetworkAccessControl@@UAE@XZ @ 1618 NONAME ; QMediaNetworkAccessControl::~QMediaNetworkAccessControl(void)
+ ?setVideoOutput@QMediaImageViewer@@QAEXPAVQAbstractVideoSurface@@@Z @ 1619 NONAME ; void QMediaImageViewer::setVideoOutput(class QAbstractVideoSurface *)
+ ?configurationChanged@QMediaNetworkAccessControl@@IAEXABVQNetworkConfiguration@@@Z @ 1620 NONAME ; void QMediaNetworkAccessControl::configurationChanged(class QNetworkConfiguration const &)
+ ?tr@QMediaNetworkAccessControl@@SA?AVQString@@PBD0@Z @ 1621 NONAME ; class QString QMediaNetworkAccessControl::tr(char const *, char const *)
+ ?qt_metacast@QMediaNetworkAccessControl@@UAEPAXPBD@Z @ 1622 NONAME ; void * QMediaNetworkAccessControl::qt_metacast(char const *)
+
diff --git a/src/s60installs/deviceconfiguration/.gitignore b/src/s60installs/deviceconfiguration/.gitignore
new file mode 100644
index 000000000..2a654a0c7
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/.gitignore
@@ -0,0 +1,11 @@
+!bld.inf
+!config.pri
+!mobility.prf
+!mobilityconfig.prf
+!symbian3_qtmobility.pkg
+!symbian4_qtmobility.pkg
+!qtmobility.sisx
+!qtmobility_nonNR.pkg
+!qtmobility_stub.pkg
+!qtmobility_stub.sis
+!qtmobilityexampleapps.pkg
diff --git a/src/s60installs/deviceconfiguration/QtBearer{000a0000}.dll b/src/s60installs/deviceconfiguration/QtBearer{000a0000}.dll
new file mode 100644
index 000000000..5c60d4a41
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/QtBearer{000a0000}.dll
Binary files differ
diff --git a/src/s60installs/deviceconfiguration/bld.inf b/src/s60installs/deviceconfiguration/bld.inf
new file mode 100644
index 000000000..427160ffa
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/bld.inf
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, version 2.1 of the License.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not,
+* see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
+*
+* Description: Build information file for Qt Extensions configuration
+*
+*/
+
+#include <platform_paths.hrh>
+
+PRJ_PLATFORMS
+TOOLS2
+
+PRJ_EXPORTS
+symbian3_config.pri |../../../config.pri
+
+qtmobilityconfig.xml /epoc32/tools/makefile_templates/qt/qtmobilityconfig.xml
+qtmobilityheaders.flm /epoc32/tools/makefile_templates/qt/qtmobilityheaders.flm
+
+../../../features/mobility.prf.template /epoc32/tools/qt/mkspecs/features/mobility.prf
+mobilityconfig.prf /epoc32/tools/qt/mkspecs/features/mobilityconfig.prf
+
+qtmobility.iby CORE_MW_LAYER_IBY_EXPORT_PATH(qtmobility.iby)
+
+qtmobility.confml CONFML_EXPORT_PATH(qtmobility.confml,uda_content)
+qtmobility_copy.implml CRML_EXPORT_PATH(qtmobility_copy.implml,uda_content)
+qtmobility.sisx CRML_EXPORT_PATH(../content/sis/,uda_content)
+qtmobility_stub.sis /epoc32/data/z/system/install/qtmobility_stub.sis
+
+../../../bin/servicedbgen.exe /epoc32/tools/servicedbgen.exe
+../../../features/qtservice.xml /epoc32/tools/makefile_templates/qt/qtservice.xml
+../../../features/qtservice.flm /epoc32/tools/makefile_templates/qt/qtservice.flm
+../../../features/qtservice.prf /epoc32/tools/qt/mkspecs/features/symbian/qtservice.prf
+
+PRJ_MMPFILES
+
+
+PRJ_TESTMMPFILES
+
+
+PRJ_EXTENSIONS
+START EXTENSION qt/qtmobilityheaders
+OPTION MODULES bearer location contacts systeminfo publishsubscribe versit messaging sensors serviceframework multimedia gallery organizer feedback
+END
diff --git a/src/s60installs/deviceconfiguration/mobilityconfig.prf b/src/s60installs/deviceconfiguration/mobilityconfig.prf
new file mode 100644
index 000000000..91a50cf96
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/mobilityconfig.prf
@@ -0,0 +1,5 @@
+MOBILITY_CONFIG=bearer location contacts systeminfo publishsubscribe versit messaging sensors serviceframework multimedia gallery organizer feedback connectivity
+MOBILITY_VERSION = 1.2.0
+MOBILITY_MAJOR_VERSION = 1
+MOBILITY_MINOR_VERSION = 2
+MOBILITY_PATCH_VERSION = 0
diff --git a/src/s60installs/deviceconfiguration/qtmobility.confml b/src/s60installs/deviceconfiguration/qtmobility.confml
new file mode 100644
index 000000000..4da8443bc
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/qtmobility.confml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<confml:configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:confml="http://www.s60.com/xml/confml/2" xsi:schemaLocation="http://www.s60.com/xml/confml/2 http://www.s60.com/xml/confml/1#//confml2" version="2.0">
+ <confml:feature name="QtMobility" ref="qtmobility">
+ <confml:desc>QtMobility settings</confml:desc>
+ <confml:setting name="QtMobility enabled"
+ ref="Enabled"
+ type="boolean">
+ <confml:desc>To enable QtMobility usage</confml:desc>
+ </confml:setting>
+ </confml:feature>
+ <confml:data>
+ <confml:qtmobility>
+ <confml:Enabled>true</confml:Enabled>
+ </confml:qtmobility>
+ </confml:data>
+</confml:configuration> \ No newline at end of file
diff --git a/src/s60installs/deviceconfiguration/qtmobility.iby b/src/s60installs/deviceconfiguration/qtmobility.iby
new file mode 100644
index 000000000..03e9c40b5
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/qtmobility.iby
@@ -0,0 +1,134 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, version 2.1 of the License.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not,
+* see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
+*
+* Description:
+*
+*/
+
+#ifndef __QT_MOBILITY_IBY__
+#define __QT_MOBILITY_IBY__
+
+#include <bldvariant.hrh>
+#include <data_caging_paths_for_iby.hrh>
+
+#ifndef FF_QT_IN_UDA
+
+//Stub sis
+data=ZSYSTEM\install\qtmobility_stub.sis \system\install\qtmobility_stub.sis
+
+//Core
+file=ABI_DIR\BUILD_DIR\qtbearer.dll SHARED_LIB_DIR\qtbearer.dll
+file=ABI_DIR\BUILD_DIR\qtlocation.dll SHARED_LIB_DIR\qtlocation.dll
+file=ABI_DIR\BUILD_DIR\qtpublishsubscribe.dll SHARED_LIB_DIR\qtpublishsubscribe.dll
+file=ABI_DIR\BUILD_DIR\qpspathmapperserver.exe PROGRAMS_DIR\qpspathmapperserver.exe
+file=ABI_DIR\BUILD_DIR\qtserviceframework.dll SHARED_LIB_DIR\qtserviceframework.dll
+file=ABI_DIR\BUILD_DIR\qsfwdatabasemanagerserver.exe PROGRAMS_DIR\qsfwdatabasemanagerserver.exe
+file=ABI_DIR\BUILD_DIR\qtsysteminfo.dll SHARED_LIB_DIR\qtsysteminfo.dll
+file=ABI_DIR\BUILD_DIR\qtmessaging.dll SHARED_LIB_DIR\qtmessaging.dll
+file=ABI_DIR\BUILD_DIR\qtmultimediakit.dll SHARED_LIB_DIR\qtmultimediakit.dll
+file=ABI_DIR\BUILD_DIR\qtsensors.dll SHARED_LIB_DIR\qtsensors.dll
+file=ABI_DIR\BUILD_DIR\qtcontacts.dll SHARED_LIB_DIR\qtcontacts.dll
+file=ABI_DIR\BUILD_DIR\qtversit.dll SHARED_LIB_DIR\qtversit.dll
+file=ABI_DIR\BUILD_DIR\qtversitorganizer.dll SHARED_LIB_DIR\qtversitorganizer.dll
+file=ABI_DIR\BUILD_DIR\qtfeedback.dll SHARED_LIB_DIR\qtfeedback.dll
+file=ABI_DIR\BUILD_DIR\qtgallery.dll SHARED_LIB_DIR\qtgallery.dll
+file=ABI_DIR\BUILD_DIR\qtorganizer.dll SHARED_LIB_DIR\qtorganizer.dll
+
+//Plugins
+file=ABI_DIR\BUILD_DIR\qtcontacts_serviceactionmanager.dll SHARED_LIB_DIR\qtcontacts_serviceactionmanager.dll
+data=\epoc32\data\z\resource\qt\plugins\contacts\qtcontacts_serviceactionmanager.qtplugin resource\qt\plugins\contacts\qtcontacts_serviceactionmanager.qtplugin
+file=ABI_DIR\BUILD_DIR\qtcontacts_symbian.dll SHARED_LIB_DIR\qtcontacts_symbian.dll
+data=\epoc32\data\z\resource\qt\plugins\contacts\qtcontacts_symbian.qtplugin resource\qt\plugins\contacts\qtcontacts_symbian.qtplugin
+file=ABI_DIR\BUILD_DIR\qtcontacts_symbiansim.dll SHARED_LIB_DIR\qtcontacts_symbiansim.dll
+data=\epoc32\data\z\resource\qt\plugins\contacts\qtcontacts_symbiansim.qtplugin resource\qt\plugins\contacts\qtcontacts_symbiansim.qtplugin
+file=ABI_DIR\BUILD_DIR\qtfeedback_mmk.dll SHARED_LIB_DIR\qtfeedback_mmk.dll
+data=\epoc32\data\z\resource\qt\plugins\feedback\qtfeedback_mmk.qtplugin resource\qt\plugins\feedback\qtfeedback_mmk.qtplugin
+file=ABI_DIR\BUILD_DIR\qtfeedback_symbian.dll SHARED_LIB_DIR\qtfeedback_symbian.dll
+data=\epoc32\data\z\resource\qt\plugins\feedback\qtfeedback_symbian.qtplugin resource\qt\plugins\feedback\qtfeedback_symbian.qtplugin
+file=ABI_DIR\BUILD_DIR\qtgeoservices_nokia.dll SHARED_LIB_DIR\qtgeoservices_nokia.dll
+data=\epoc32\data\z\resource\qt\plugins\geoservices\qtgeoservices_nokia.qtplugin resource\qt\plugins\geoservices\qtgeoservices_nokia.qtplugin
+file=ABI_DIR\BUILD_DIR\qtlandmarks_symbian.dll SHARED_LIB_DIR\qtlandmarks_symbian.dll
+data=\epoc32\data\z\resource\qt\plugins\landmarks\qtlandmarks_symbian.qtplugin resource\qt\plugins\landmarks\qtlandmarks_symbian.qtplugin
+file=ABI_DIR\BUILD_DIR\qtmultimediakit_m3u.dll SHARED_LIB_DIR\qtmultimediakit_m3u.dll
+data=\epoc32\data\z\resource\qt\plugins\playlistformats\qtmultimediakit_m3u.qtplugin resource\qt\plugins\playlistformats\qtmultimediakit_m3u.qtplugin
+file=ABI_DIR\BUILD_DIR\qtmultimediakit_mmfengine.dll SHARED_LIB_DIR\qtmultimediakit_mmfengine.dll
+data=\epoc32\data\z\resource\qt\plugins\mediaservice\qtmultimediakit_mmfengine.qtplugin resource\qt\plugins\mediaservice\qtmultimediakit_mmfengine.qtplugin
+file=ABI_DIR\BUILD_DIR\qtmultimediakit_ecamengine.dll SHARED_LIB_DIR\qtmultimediakit_ecamengine.dll
+data=\epoc32\data\z\resource\qt\plugins\mediaservice\qtmultimediakit_ecamengine.qtplugin resource\qt\plugins\mediaservice\qtmultimediakit_ecamengine.qtplugin
+file=ABI_DIR\BUILD_DIR\qtorganizer_skeleton.dll SHARED_LIB_DIR\qtorganizer_skeleton.dll
+data=\epoc32\data\z\resource\qt\plugins\organizer\qtorganizer_skeleton.qtplugin resource\qt\plugins\organizer\qtorganizer_skeleton.qtplugin
+file=ABI_DIR\BUILD_DIR\qtorganizer_symbian.dll SHARED_LIB_DIR\qtorganizer_symbian.dll
+data=\epoc32\data\z\resource\qt\plugins\organizer\qtorganizer_symbian.qtplugin resource\qt\plugins\organizer\qtorganizer_symbian.qtplugin
+file=ABI_DIR\BUILD_DIR\qtsensors_generic.dll SHARED_LIB_DIR\qtsensors_generic.dll
+data=\epoc32\data\z\resource\qt\plugins\sensors\qtsensors_generic.qtplugin resource\qt\plugins\sensors\qtsensors_generic.qtplugin
+file=ABI_DIR\BUILD_DIR\qtsensors_sym.dll SHARED_LIB_DIR\qtsensors_sym.dll
+data=\epoc32\data\z\resource\qt\plugins\sensors\qtsensors_sym.qtplugin resource\qt\plugins\sensors\qtsensors_sym.qtplugin
+file=ABI_DIR\BUILD_DIR\qtversit_backuphandler.dll SHARED_LIB_DIR\qtversit_backuphandler.dll
+data=\epoc32\data\z\resource\qt\plugins\versit\qtversit_backuphandler.qtplugin resource\qt\plugins\versit\qtversit_backuphandler.qtplugin
+file=ABI_DIR\BUILD_DIR\qtversit_vcardpreserver.dll SHARED_LIB_DIR\qtversit_vcardpreserver.dll
+data=\epoc32\data\z\resource\qt\plugins\versit\qtversit_vcardpreserver.qtplugin resource\qt\plugins\versit\qtversit_vcardpreserver.qtplugin
+file=ABI_DIR\BUILD_DIR\cntversitfavoriteplugin.dll SHARED_LIB_DIR\cntversitfavoriteplugin.dll
+data=\epoc32\data\z\resource\qt\plugins\versit\cntversitfavoriteplugin.qtplugin resource\qt\plugins\versit\cntversitfavoriteplugin.qtplugin
+file=ABI_DIR\BUILD_DIR\cntversitlandlineplugin.dll SHARED_LIB_DIR\cntversitlandlineplugin.dll
+data=\epoc32\data\z\resource\qt\plugins\versit\cntversitlandlineplugin.qtplugin resource\qt\plugins\versit\cntversitlandlineplugin.qtplugin
+file=ABI_DIR\BUILD_DIR\cntversitmycardplugin.dll SHARED_LIB_DIR\cntversitmycardplugin.dll
+data=\epoc32\data\z\resource\qt\plugins\versit\cntversitmycardplugin.qtplugin resource\qt\plugins\versit\cntversitmycardplugin.qtplugin
+file=ABI_DIR\BUILD_DIR\cntversitprefplugin.dll SHARED_LIB_DIR\cntversitprefplugin.dll
+data=\epoc32\data\z\resource\qt\plugins\versit\cntversitprefplugin.qtplugin resource\qt\plugins\versit\cntversitprefplugin.qtplugin
+file=ABI_DIR\BUILD_DIR\declarative_contacts.dll SHARED_LIB_DIR\declarative_contacts.dll
+data=\epoc32\data\z\resource\qt\imports\qtmobility\contacts\declarative_contacts.qtplugin resource\qt\imports\qtmobility\contacts\declarative_contacts.qtplugin
+data=\epoc32\data\z\resource\qt\imports\qtmobility\contacts\qmldir resource\qt\imports\qtmobility\contacts\qmldir
+file=ABI_DIR\BUILD_DIR\declarative_feedback.dll SHARED_LIB_DIR\declarative_feedback.dll
+data=\epoc32\data\z\resource\qt\imports\qtmobility\feedback\declarative_feedback.qtplugin resource\qt\imports\qtmobility\feedback\declarative_feedback.qtplugin
+data=\epoc32\data\z\resource\qt\imports\qtmobility\feedback\qmldir resource\qt\imports\qtmobility\feedback\qmldir
+file=ABI_DIR\BUILD_DIR\declarative_gallery.dll SHARED_LIB_DIR\declarative_gallery.dll
+data=\epoc32\data\z\resource\qt\imports\qtmobility\gallery\declarative_gallery.qtplugin resource\qt\imports\qtmobility\gallery\declarative_gallery.qtplugin
+data=\epoc32\data\z\resource\qt\imports\qtmobility\gallery\qmldir resource\qt\imports\qtmobility\gallery\qmldir
+file=ABI_DIR\BUILD_DIR\declarative_location.dll SHARED_LIB_DIR\declarative_location.dll
+data=\epoc32\data\z\resource\qt\imports\qtmobility\location\declarative_location.qtplugin resource\qt\imports\qtmobility\location\declarative_location.qtplugin
+data=\epoc32\data\z\resource\qt\imports\qtmobility\location\qmldir resource\qt\imports\qtmobility\location\qmldir
+file=ABI_DIR\BUILD_DIR\declarative_messaging.dll SHARED_LIB_DIR\declarative_messaging.dll
+data=\epoc32\data\z\resource\qt\imports\qtmobility\messaging\declarative_messaging.qtplugin resource\qt\imports\qtmobility\messaging\declarative_messaging.qtplugin
+data=\epoc32\data\z\resource\qt\imports\qtmobility\messaging\qmldir resource\qt\imports\qtmobility\messaging\qmldir
+file=ABI_DIR\BUILD_DIR\declarative_multimedia.dll SHARED_LIB_DIR\declarative_multimedia.dll
+data=\epoc32\data\z\resource\qt\imports\qtmultimediakit\declarative_multimedia.qtplugin resource\qt\imports\qtmultimediakit\declarative_multimedia.qtplugin
+data=\epoc32\data\z\resource\qt\imports\qtmultimediakit\qmldir resource\qt\imports\qtmultimediakit\qmldir
+file=ABI_DIR\BUILD_DIR\declarative_organizer.dll SHARED_LIB_DIR\declarative_organizer.dll
+data=\epoc32\data\z\resource\qt\imports\qtmobility\organizer\declarative_organizer.qtplugin resource\qt\imports\qtmobility\organizer\declarative_organizer.qtplugin
+data=\epoc32\data\z\resource\qt\imports\qtmobility\organizer\qmldir resource\qt\imports\qtmobility\organizer\qmldir
+file=ABI_DIR\BUILD_DIR\declarative_publishsubscribe.dll SHARED_LIB_DIR\declarative_publishsubscribe.dll
+data=\epoc32\data\z\resource\qt\imports\qtmobility\publishsubscribe\declarative_publishsubscribe.qtplugin resource\qt\imports\qtmobility\publishsubscribe\declarative_publishsubscribe.qtplugin
+data=\epoc32\data\z\resource\qt\imports\qtmobility\publishsubscribe\qmldir resource\qt\imports\qtmobility\publishsubscribe\qmldir
+file=ABI_DIR\BUILD_DIR\declarative_sensors.dll SHARED_LIB_DIR\declarative_sensors.dll
+data=\epoc32\data\z\resource\qt\imports\qtmobility\sensors\declarative_sensors.qtplugin resource\qt\imports\qtmobility\sensors\declarative_sensors.qtplugin
+data=\epoc32\data\z\resource\qt\imports\qtmobility\sensors\qmldir resource\qt\imports\qtmobility\sensors\qmldir
+file=ABI_DIR\BUILD_DIR\declarative_serviceframework.dll SHARED_LIB_DIR\declarative_serviceframework.dll
+data=\epoc32\data\z\resource\qt\imports\qtmobility\serviceframework\declarative_serviceframework.qtplugin resource\qt\imports\qtmobility\serviceframework\declarative_serviceframework.qtplugin
+data=\epoc32\data\z\resource\qt\imports\qtmobility\serviceframework\qmldir resource\qt\imports\qtmobility\serviceframework\qmldir
+file=ABI_DIR\BUILD_DIR\declarative_systeminfo.dll SHARED_LIB_DIR\declarative_systeminfo.dll
+data=\epoc32\data\z\resource\qt\imports\qtmobility\systeminfo\declarative_systeminfo.qtplugin resource\qt\imports\qtmobility\systeminfo\declarative_systeminfo.qtplugin
+data=\epoc32\data\z\resource\qt\imports\qtmobility\systeminfo\qmldir resource\qt\imports\qtmobility\systeminfo\qmldir
+
+//Resource
+data=\epoc32\data\z\private\2002ac7f\qtserviceframework_4.7_system.db private\2002ac7f\qtserviceframework_4.7_system.db
+data=\epoc32\data\z\private\10202D56\import\packages\2002AC89\backup_registration.xml private\10202D56\import\packages\2002AC89\backup_registration.xml
+
+// Symbian3 PS1 support
+file=\sf\mw\qtmobility\src\s60installs\deviceconfiguration\QtBearer{000a0000}.dll SHARED_LIB_DIR\QtBearer{000a0000}.dll
+#endif // FF_QT_IN_UDA
+
+#endif // __QT_MOBILITY_IBY__
diff --git a/src/s60installs/deviceconfiguration/qtmobility.sisx b/src/s60installs/deviceconfiguration/qtmobility.sisx
new file mode 100644
index 000000000..56a6051ca
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/qtmobility.sisx
@@ -0,0 +1 @@
+1 \ No newline at end of file
diff --git a/src/s60installs/deviceconfiguration/qtmobility_copy.implml b/src/s60installs/deviceconfiguration/qtmobility_copy.implml
new file mode 100644
index 000000000..34608e883
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/qtmobility_copy.implml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<container xmlns="http://www.symbianfoundation.org/xml/implml/1"
+ condition="${qtmobility.Enabled}">
+ <tag name="target" value="uda" />
+ <content xmlns="http://www.s60.com/xml/content/2">
+ <output dir="sis" flatten="true">
+ <input file="sis/qtmobility.sisx" />
+ </output>
+ </content>
+</container>
diff --git a/src/s60installs/deviceconfiguration/qtmobility_stub.pkg b/src/s60installs/deviceconfiguration/qtmobility_stub.pkg
new file mode 100644
index 000000000..cad6632c6
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/qtmobility_stub.pkg
@@ -0,0 +1,12 @@
+
+; Language
+&EN
+
+; SIS header: name, uid, version
+#{"QtMobility"},(0x2002AC89),1,2,0,TYPE=SA
+
+; Localised Vendor name
+%{"Nokia"}
+
+; Unique Vendor name
+:"Nokia"
diff --git a/src/s60installs/deviceconfiguration/qtmobility_stub.sis b/src/s60installs/deviceconfiguration/qtmobility_stub.sis
new file mode 100644
index 000000000..730cc96f3
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/qtmobility_stub.sis
Binary files differ
diff --git a/src/s60installs/deviceconfiguration/qtmobilityconfig.xml b/src/s60installs/deviceconfiguration/qtmobilityconfig.xml
new file mode 100644
index 000000000..095a0d6ea
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/qtmobilityconfig.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<build xmlns="http://symbian.com/xml/build"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://symbian.com/xml/build http://symbian.com/xml/build/2_0.xsd">
+
+ <!-- Tools interfaces -->
+
+ <interface name="qt.qtmobilityheaders" extends="Symbian.UserFLM" flm="qtmobilityheaders.flm">
+ <param name='SYNCHEADERS' default='syncheaders' />
+ <param name='MODULES' default='' />
+ </interface>
+
+</build>
diff --git a/src/s60installs/deviceconfiguration/qtmobilityexampleapps.pkg b/src/s60installs/deviceconfiguration/qtmobilityexampleapps.pkg
new file mode 100644
index 000000000..7da132bdf
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/qtmobilityexampleapps.pkg
@@ -0,0 +1,111 @@
+; Language
+&EN
+
+; SIS header: name, uid, version
+#{"QtMobilityExamples"},(0xE001E61D),1,2,0,TYPE=SA
+
+; Localised Vendor name
+%{"Nokia"}
+
+; Unique Vendor name
+:"Nokia"
+
+; Default dependency to Qt libraries
+(0x2001E61C), 4, 7, 2, {"Qt"}
+; Default HW/platform dependencies
+[0x101F7961],0,0,0,{"S60ProductID"}
+[0x102032BE],0,0,0,{"S60ProductID"}
+[0x102752AE],0,0,0,{"S60ProductID"}
+[0x1028315F],0,0,0,{"S60ProductID"}
+[0x20022E6D],0,0,0,{"S60ProductID"}
+[0x20032DE7],0,0,0,{"S60ProductID"}
+; Default dependency to QtMobility libraries
+(0x2002AC89), 1, 2, 0, {"QtMobility"}
+
+;Bearer
+"/epoc32/release/armv5/urel/bearercloud.exe" - "!:\sys\bin\bearercloud.exe"
+"/epoc32/data/z/resource/apps/bearercloud.rsc" - "!:\resource\apps\bearercloud.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/bearercloud_reg.rsc" - "!:\private\10003a3f\import\apps\bearercloud_reg.rsc"
+
+"/epoc32/release/armv5/urel/bearermonitor.exe" - "!:\sys\bin\bearermonitor.exe"
+"/epoc32/data/z/resource/apps/bearermonitor.rsc" - "!:\resource\apps\bearermonitor.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/bearermonitor_reg.rsc" - "!:\private\10003a3f\import\apps\bearermonitor_reg.rsc"
+
+;Contacts
+"/epoc32/release/armv5/urel/samplephonebook.exe" - "!:\sys\bin\samplephonebook.exe"
+"/epoc32/data/z/resource/apps/samplephonebook.rsc" - "!:\resource\apps\samplephonebook.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/samplephonebook_reg.rsc" - "!:\private\10003a3f\import\apps\samplephonebook_reg.rsc"
+
+;Feedback
+"/epoc32/release/armv5/urel/hapticsplayer.exe" - "!:\sys\bin\hapticsplayer.exe"
+"/epoc32/data/z/resource/apps/hapticsplayer.rsc" - "!:\resource\apps\hapticsplayer.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/hapticsplayer_reg.rsc" - "!:\private\10003a3f\import\apps\hapticsplayer_reg.rsc"
+
+;Gallery
+"/epoc32/release/armv5/urel/mediabrowser.exe" - "!:\sys\bin\mediabrowser.exe"
+"/epoc32/data/z/resource/apps/mediabrowser.rsc" - "!:\resource\apps\mediabrowser.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/mediabrowser_reg.rsc" - "!:\private\10003a3f\import\apps\mediabrowser_reg.rsc"
+
+"/epoc32/release/armv5/urel/documentproperties.exe" - "!:\sys\bin\documentproperties.exe"
+"/epoc32/data/z/resource/apps/documentproperties.rsc" - "!:\resource\apps\documentproperties.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/documentproperties_reg.rsc" - "!:\private\10003a3f\import\apps\documentproperties_reg.rsc"
+
+;Location
+"/epoc32/release/armv5/urel/satellitedialog.exe" - "!:\sys\bin\satellitedialog.exe"
+"/epoc32/data/z/resource/apps/satellitedialog.rsc" - "!:\resource\apps\satellitedialog.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/satellitedialog_reg.rsc" - "!:\private\10003a3f\import\apps\satellitedialog_reg.rsc"
+
+;Messaging
+"/epoc32/release/armv5/urel/querymessages.exe" - "!:\sys\bin\querymessages.exe"
+"/epoc32/data/z/resource/apps/querymessages.rsc" - "!:\resource\apps\querymessages.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/querymessages_reg.rsc" - "!:\private\10003a3f\import\apps\querymessages_reg.rsc"
+
+"/epoc32/release/armv5/urel/writemessage.exe" - "!:\sys\bin\writemessage.exe"
+"/epoc32/data/z/resource/apps/writemessage.rsc" - "!:\resource\apps\writemessage.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/writemessage_reg.rsc" - "!:\private\10003a3f\import\apps\writemessage_reg.rsc"
+
+"/epoc32/release/armv5/urel/serviceactions.exe" - "!:\sys\bin\serviceactions.exe"
+"/epoc32/data/z/resource/apps/serviceactions.rsc" - "!:\resource\apps\serviceactions.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/serviceactions_reg.rsc" - "!:\private\10003a3f\import\apps\serviceactions_reg.rsc"
+
+;Multimedia
+"/epoc32/release/armv5/urel/player.exe" - "!:\sys\bin\player.exe"
+"/epoc32/data/z/resource/apps/player.rsc" - "!:\resource\apps\player.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/player_reg.rsc" - "!:\private\10003a3f\import\apps\player_reg.rsc"
+
+"/epoc32/release/armv5/urel/audiorecorder.exe" - "!:\sys\bin\audiorecorder.exe"
+"/epoc32/data/z/resource/apps/audiorecorder.rsc" - "!:\resource\apps\audiorecorder.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/audiorecorder_reg.rsc" - "!:\private\10003a3f\import\apps\audiorecorder_reg.rsc"
+
+"/epoc32/release/armv5/urel/radio.exe" - "!:\sys\bin\radio.exe"
+"/epoc32/data/z/resource/apps/radio.rsc" - "!:\resource\apps\radio.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/radio_reg.rsc" - "!:\private\10003a3f\import\apps\radio.rsc"
+
+"/epoc32/release/armv5/urel/slideshow.exe" - "!:\sys\bin\slideshow.exe"
+"/epoc32/data/z/resource/apps/slideshow.rsc" - "!:\resource\apps\slideshow.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/slideshow_reg.rsc" - "!:\private\10003a3f\import\apps\slideshow_reg.rsc"
+
+;Organizer
+"/epoc32/release/armv5/urel/calendardemo.exe" - "!:\sys\bin\calendardemo.exe"
+"/epoc32/data/z/resource/apps/calendardemo.rsc" - "!:\resource\apps\calendardemo.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/calendardemo_reg.rsc" - "!:\private\10003a3f\import\apps\calendardemo_reg.rsc"
+
+;Publish and Subscribe
+"/epoc32/release/armv5/urel/publish_subscribe.exe" - "!:\sys\bin\publish_subscribe.exe"
+"/epoc32/data/z/resource/apps/publish_subscribe.rsc" - "!:\resource\apps\publish_subscribe.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/publish_subscribe_reg.rsc" - "!:\private\10003a3f\import\apps\publish_subscribe_reg.rsc"
+
+;Sensors
+"/epoc32/release/armv5/urel/smallsensors.exe" - "!:\sys\bin\smallsensors.exe"
+"/epoc32/data/z/resource/apps/smallsensors.rsc" - "!:\resource\apps\smallsensors.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/smallsensors_reg.rsc" - "!:\private\10003a3f\import\apps\smallsensors_reg.rsc"
+
+;ServiceFramework
+"/epoc32/release/armv5/urel/servicebrowser.exe" - "!:\sys\bin\servicebrowser.exe"
+"/epoc32/data/z/resource/apps/servicebrowser.rsc" - "!:\resource\apps\servicebrowser.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/servicebrowser_reg.rsc" - "!:\private\10003a3f\import\apps\servicebrowser_reg.rsc"
+
+;SystemInfo
+"/epoc32/release/armv5/urel/qsysinfo.exe" - "!:\sys\bin\qsysinfo.exe"
+"/epoc32/data/z/resource/apps/qsysinfo.rsc" - "!:\resource\apps\qsysinfo.rsc"
+"/epoc32/data/z/private/10003a3f/import/apps/qsysinfo_reg.rsc" - "!:\private\10003a3f\import\apps\qsysinfo_reg.rsc"
diff --git a/src/s60installs/deviceconfiguration/qtmobilityexamples.iby b/src/s60installs/deviceconfiguration/qtmobilityexamples.iby
new file mode 100644
index 000000000..531d251ff
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/qtmobilityexamples.iby
@@ -0,0 +1,128 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, version 2.1 of the License.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not,
+* see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
+*
+* Description:
+*
+*/
+
+#ifndef __QT_MOBILITYEXAMPLES_IBY__
+#define __QT_MOBILITYEXAMPLES_IBY__
+
+#include <bldvariant.hrh>
+
+#define UPGRADABLE_APP_REG_RSC(NAME) data=DATAZ_\PRIVATE\10003A3F\IMPORT\APPS\ ## NAME ## _reg.rsc Private\10003a3f\import\apps\ ## NAME ## _reg.rsc
+
+S60_APP_EXE(audiorecorder)
+S60_APP_RESOURCE(audiorecorder)
+UPGRADABLE_APP_REG_RSC(audiorecorder)
+
+S60_APP_EXE(battery-publisher)
+S60_APP_RESOURCE(battery-publisher)
+UPGRADABLE_APP_REG_RSC(battery-publisher)
+
+S60_APP_EXE(battery-subscriber)
+S60_APP_RESOURCE(battery-subscriber)
+UPGRADABLE_APP_REG_RSC(battery-subscriber)
+
+S60_APP_EXE(bearercloud)
+S60_APP_RESOURCE(bearercloud)
+UPGRADABLE_APP_REG_RSC(bearercloud)
+
+S60_APP_EXE(bearermonitor)
+S60_APP_RESOURCE(bearermonitor)
+UPGRADABLE_APP_REG_RSC(bearermonitor)
+
+file=ABI_DIR\BUILD_DIR\serviceframework_bluetoothtransferplugin.dll SHARED_LIB_DIR\serviceframework_bluetoothtransferplugin.dll
+data=\epoc32\data\z\resource\qt\plugins\serviceframework_bluetoothtransferplugin.qtplugin resource\qt\plugins\serviceframework_bluetoothtransferplugin.qtplugin
+
+S60_APP_EXE(sfw-kinetic-example)
+S60_APP_RESOURCE(sfw-kinetic-example)
+UPGRADABLE_APP_REG_RSC(sfw-kinetic-example)
+file=ABI_DIR\BUILD_DIR\serviceframework_landlinedialerservice.dll SHARED_LIB_DIR\serviceframework_landlinedialerservice.dll
+file=ABI_DIR\BUILD_DIR\serviceframework_voipdialerservice.dll SHARED_LIB_DIR\serviceframework_voipdialerservice.dll
+
+file=ABI_DIR\BUILD_DIR\serviceframework_filemanagerplugin.dll SHARED_LIB_DIR\serviceframework_filemanagerplugin.dll
+data=\epoc32\data\z\resource\qt\plugins\serviceframework_filemanagerplugin.qtplugin resource\qt\plugins\serviceframework_filemanagerplugin.qtplugin
+
+file=ABI_DIR\BUILD_DIR\serviceframework_notesmanagerplugin.dll SHARED_LIB_DIR\serviceframework_notesmanagerplugin.dll
+data=\epoc32\data\z\resource\qt\plugins\serviceframework_notesmanagerplugin.qtplugin resource\qt\plugins\serviceframework_notesmanagerplugin.qtplugin
+
+S60_APP_EXE(player)
+S60_APP_RESOURCE(player)
+UPGRADABLE_APP_REG_RSC(player)
+
+S60_APP_EXE(publish-subscribe)
+S60_APP_RESOURCE(publish-subscribe)
+UPGRADABLE_APP_REG_RSC(publish-subscribe)
+data=\epoc32\data\z\resource\qt\crml\example.qcrml resource\qt\crml\example.qcrml
+
+S60_APP_EXE(querymessages)
+S60_APP_RESOURCE(querymessages)
+UPGRADABLE_APP_REG_RSC(querymessages)
+
+S60_APP_EXE(quickstart)
+S60_APP_RESOURCE(quickstart)
+UPGRADABLE_APP_REG_RSC(quickstart)
+
+S60_APP_EXE(radio)
+S60_APP_RESOURCE(radio)
+UPGRADABLE_APP_REG_RSC(radio)
+
+S60_APP_EXE(satellitedialog)
+S60_APP_RESOURCE(satellitedialog)
+UPGRADABLE_APP_REG_RSC(satellitedialog)
+
+S60_APP_EXE(accel)
+S60_APP_RESOURCE(accel)
+UPGRADABLE_APP_REG_RSC(accel)
+
+S60_APP_EXE(grueapp)
+S60_APP_RESOURCE(grueapp)
+UPGRADABLE_APP_REG_RSC(grueapp)
+
+file=ABI_DIR\BUILD_DIR\grueplugin.dll SHARED_LIB_DIR\grueplugin.dll
+data=\epoc32\data\z\resource\qt\plugins\sensors\grueplugin.qtplugin resource\qt\plugins\sensors\grueplugin.qtplugin
+
+S60_APP_EXE(orientation)
+S60_APP_RESOURCE(orientation)
+UPGRADABLE_APP_REG_RSC(orientation)
+
+S60_APP_EXE(reading_perf)
+S60_APP_RESOURCE(reading_perf)
+UPGRADABLE_APP_REG_RSC(reading_perf)
+
+S60_APP_EXE(sensor_explorer)
+S60_APP_RESOURCE(sensor_explorer)
+UPGRADABLE_APP_REG_RSC(sensor_explorer)
+
+S60_APP_EXE(serviceactions)
+S60_APP_RESOURCE(serviceactions)
+UPGRADABLE_APP_REG_RSC(serviceactions)
+
+S60_APP_EXE(slideshow)
+S60_APP_RESOURCE(slideshow)
+UPGRADABLE_APP_REG_RSC(slideshow)
+
+S60_APP_EXE(sysinfo)
+S60_APP_RESOURCE(sysinfo)
+UPGRADABLE_APP_REG_RSC(sysinfo)
+
+S60_APP_EXE(writemessage)
+S60_APP_RESOURCE(writemessage)
+UPGRADABLE_APP_REG_RSC(writemessage)
+
+#endif //__QT_MOBILITYEXAMPLES_IBY__
diff --git a/src/s60installs/deviceconfiguration/qtmobilityheaders.flm b/src/s60installs/deviceconfiguration/qtmobilityheaders.flm
new file mode 100644
index 000000000..0b2cfcb53
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/qtmobilityheaders.flm
@@ -0,0 +1,146 @@
+# /****************************************************************************
+# **
+# ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+# ** Contact:
+# **
+# ****************************************************************************/
+
+# FLM to generate Qt style headers for QtMobility
+QTMOBILITY_ROOT := $(subst src/s60installs/deviceconfiguration,,$(subst \,/,$(EXTENSION_ROOT)))
+QTMOBILITY_BIN := $(QTMOBILITY_ROOT)bin
+QTMOBILITY_INCLUDE := $(QTMOBILITY_ROOT)include
+QTMOBILITY_BEARER_INCLUDE := $(QTMOBILITY_INCLUDE)/QtBearer
+QTMOBILITY_CONTACTS_INCLUDE := $(QTMOBILITY_INCLUDE)/QtContacts
+QTMOBILITY_LOCATION_INCLUDE := $(QTMOBILITY_INCLUDE)/QtLocation
+QTMOBILITY_MESSAGING_INCLUDE := $(QTMOBILITY_INCLUDE)/QtMessaging
+QTMOBILITY_MULTIMEDIA_INCLUDE := $(QTMOBILITY_INCLUDE)/QtMultimediaKit
+QTMOBILITY_PUBLISHSUBSCRIBE_INCLUDE := $(QTMOBILITY_INCLUDE)/QtPublishSubscribe
+QTMOBILITY_SYSTEMINFO_INCLUDE := $(QTMOBILITY_INCLUDE)/QtSystemInfo
+QTMOBILITY_SERVICEFRAMEWORK_INCLUDE := $(QTMOBILITY_INCLUDE)/QtServiceFramework
+QTMOBILITY_VERSIT_INCLUDE := $(QTMOBILITY_INCLUDE)/QtVersit
+QTMOBILITY_VERSITORGANIZER_INCLUDE := $(QTMOBILITY_INCLUDE)/QtVersitOrganizer
+QTMOBILITY_SENSORS_INCLUDE := $(QTMOBILITY_INCLUDE)/QtSensors
+QTMOBILITY_GALLERY_INCLUDE := $(QTMOBILITY_INCLUDE)/QtGallery
+QTMOBILITY_ORGANIZER_INCLUDE := $(QTMOBILITY_INCLUDE)/QtOrganizer
+QTMOBILITY_FEEDBACK_INCLUDE := $(QTMOBILITY_INCLUDE)/QtFeedback
+QTMOBILITY_CONNECTIVITY_INCLUDE := $(QTMOBILITY_INCLUDE)/QtConnectivity
+QTMOBILITY_SRC := $(QTMOBILITY_ROOT)src
+QTMOBILITY_GLOBAL_SRC := $(QTMOBILITY_SRC)/global
+QTMOBILITY_BEARER_SRC := $(QTMOBILITY_SRC)/bearer
+QTMOBILITY_CONTACTS_SRC := $(QTMOBILITY_SRC)/contacts
+QTMOBILITY_LOCATION_SRC := $(QTMOBILITY_SRC)/location
+QTMOBILITY_MESSAGING_SRC := $(QTMOBILITY_SRC)/messaging
+QTMOBILITY_MULTIMEDIA_SRC := $(QTMOBILITY_SRC)/multimedia
+QTMOBILITY_PUBLISHSUBSCRIBE_SRC := $(QTMOBILITY_SRC)/publishsubscribe
+QTMOBILITY_SYSTEMINFO_SRC := $(QTMOBILITY_SRC)/systeminfo
+QTMOBILITY_SERVICEFRAMEWORK_SRC := $(QTMOBILITY_SRC)/serviceframework
+QTMOBILITY_VERSIT_SRC := $(QTMOBILITY_SRC)/versit
+QTMOBILITY_SENSORS_SRC := $(QTMOBILITY_SRC)/sensors
+QTMOBILITY_VERSITORGANIZER_SRC := $(QTMOBILITY_SRC)/versitorganizer
+QTMOBILITY_GALLERY_SRC := $(QTMOBILITY_SRC)/gallery
+QTMOBILITY_ORGANIZER_SRC := $(QTMOBILITY_SRC)/organizer
+QTMOBILITY_FEEDBACK_SRC := $(QTMOBILITY_SRC)/feedback
+QTMOBILITY_CONNECTIVITY_SRC := $(QTMOBILITY_SRC)/connectivity
+
+define generate_module_headers
+
+EXPORT::
+ $(call startrule,generate_module_headers,FORCESUCCESS) \
+ cd $(QTMOBILITY_ROOT) && \
+ $(PERL) -S $(QTMOBILITY_BIN)/$(SYNCHEADERS) $(1) $(2) \
+ $(call endrule,generate_module_headers)
+
+CLEAN::
+ $(call startrule,clean) \
+ $(GNURM) -rf $(1) \
+ $(call endrule,clean)
+
+WHAT::
+ @(echo "<whatlog bldinf='$(COMPONENT_META)' mmp='$(PROJECT_META)' config='$(SBS_CONFIGURATION)'>"; \
+ $(GNUFIND) $(1) -type f -print | (read LINE; \
+ while [ $$$$? -eq 0 ]; do \
+ echo "<build>$$$$LINE</build>"; \
+ read LINE; \
+ done); \
+ echo "</whatlog>") $(if $(DESCRAMBLE),2>&1 | $(DESCRAMBLE))
+
+endef
+
+GUARD:=done_$(call sanitise,$(QTMOBILITY_INCLUDE))
+ifeq ($($(GUARD)),)
+$(GUARD) := 1
+
+ifneq (,$(findstring bearer,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_BEARER_INCLUDE), $(QTMOBILITY_BEARER_SRC)))
+endif
+
+ifneq (,$(findstring contacts,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_CONTACTS_INCLUDE), $(QTMOBILITY_CONTACTS_SRC)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_CONTACTS_INCLUDE), $(QTMOBILITY_CONTACTS_SRC)/requests))
+$(eval $(call generate_module_headers, $(QTMOBILITY_CONTACTS_INCLUDE), $(QTMOBILITY_CONTACTS_SRC)/filters))
+$(eval $(call generate_module_headers, $(QTMOBILITY_CONTACTS_INCLUDE), $(QTMOBILITY_CONTACTS_SRC)/details))
+endif
+
+ifneq (,$(findstring location,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_LOCATION_INCLUDE), $(QTMOBILITY_LOCATION_SRC)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_LOCATION_INCLUDE), $(QTMOBILITY_LOCATION_SRC)/landmarks))
+$(eval $(call generate_module_headers, $(QTMOBILITY_LOCATION_INCLUDE), $(QTMOBILITY_LOCATION_SRC)/maps))
+$(eval $(call generate_module_headers, $(QTMOBILITY_LOCATION_INCLUDE), $(QTMOBILITY_LOCATION_SRC)/maps/tiled))
+endif
+
+ifneq (,$(findstring messaging,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_MESSAGING_INCLUDE), $(QTMOBILITY_MESSAGING_SRC)))
+endif
+
+ifneq (,$(findstring multimedia,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_MULTIMEDIA_INCLUDE), $(QTMOBILITY_MULTIMEDIA_SRC)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_MULTIMEDIA_INCLUDE), $(QTMOBILITY_MULTIMEDIA_SRC)/audio))
+$(eval $(call generate_module_headers, $(QTMOBILITY_MULTIMEDIA_INCLUDE), $(QTMOBILITY_MULTIMEDIA_SRC)/video))
+endif
+
+ifneq (,$(findstring publishsubscribe,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_PUBLISHSUBSCRIBE_INCLUDE), $(QTMOBILITY_PUBLISHSUBSCRIBE_SRC)))
+endif
+
+ifneq (,$(findstring systeminfo,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_SYSTEMINFO_INCLUDE), $(QTMOBILITY_SYSTEMINFO_SRC)))
+endif
+
+ifneq (,$(findstring serviceframework,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_SERVICEFRAMEWORK_INCLUDE), $(QTMOBILITY_SERVICEFRAMEWORK_SRC)))
+endif
+
+ifneq (,$(findstring versit,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_VERSIT_INCLUDE), $(QTMOBILITY_VERSIT_SRC)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_VERSITORGANIZER_INCLUDE), $(QTMOBILITY_VERSITORGANIZER_SRC)))
+endif
+
+ifneq (,$(findstring sensors,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_SENSORS_INCLUDE), $(QTMOBILITY_SENSORS_SRC)))
+endif
+
+ifneq (,$(findstring gallery,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_GALLERY_INCLUDE), $(QTMOBILITY_GALLERY_SRC)))
+endif
+
+ifneq (,$(findstring organizer,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_ORGANIZER_INCLUDE), $(QTMOBILITY_ORGANIZER_SRC)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_ORGANIZER_INCLUDE), $(QTMOBILITY_ORGANIZER_SRC)/items))
+$(eval $(call generate_module_headers, $(QTMOBILITY_ORGANIZER_INCLUDE), $(QTMOBILITY_ORGANIZER_SRC)/requests))
+$(eval $(call generate_module_headers, $(QTMOBILITY_ORGANIZER_INCLUDE), $(QTMOBILITY_ORGANIZER_SRC)/filters))
+$(eval $(call generate_module_headers, $(QTMOBILITY_ORGANIZER_INCLUDE), $(QTMOBILITY_ORGANIZER_SRC)/details))
+endif
+
+ifneq (,$(findstring feedback,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_FEEDBACK_INCLUDE), $(QTMOBILITY_FEEDBACK_SRC)))
+endif
+
+ifneq (,$(findstring connectivity,$(MODULES)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_CONNECTIVITY_INCLUDE), $(QTMOBILITY_CONNECTIVITY_SRC)))
+$(eval $(call generate_module_headers, $(QTMOBILITY_CONNECTIVITY_INCLUDE), $(QTMOBILITY_CONNECTIVITY_SRC)/bluetooth))
+$(eval $(call generate_module_headers, $(QTMOBILITY_CONNECTIVITY_INCLUDE), $(QTMOBILITY_CONNECTIVITY_SRC)/nfc))
+endif
+
+$(eval $(call generate_module_headers, $(QTMOBILITY_INCLUDE), $(QTMOBILITY_GLOBAL_SRC)))
+
+endif
diff --git a/src/s60installs/deviceconfiguration/qtmobilitytests.iby b/src/s60installs/deviceconfiguration/qtmobilitytests.iby
new file mode 100644
index 000000000..31968ae2e
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/qtmobilitytests.iby
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, version 2.1 of the License.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not,
+* see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
+*
+* Description:
+*
+*/
+
+#ifndef __QT_MOBILITYTESTS_IBY__
+#define __QT_MOBILITYTESTS_IBY__
+
+#include <bldvariant.hrh>
+
+#define UPGRADABLE_APP_REG_RSC(NAME) data=DATAZ_\PRIVATE\10003A3F\IMPORT\APPS\ ## NAME ## _reg.rsc Private\10003a3f\import\apps\ ## NAME ## _reg.rsc
+
+S60_APP_EXE(bearerex)
+S60_APP_RESOURCE(bearerex)
+UPGRADABLE_APP_REG_RSC(bearerex)
+
+S60_APP_EXE(messagingex)
+S60_APP_RESOURCE(messagingex)
+UPGRADABLE_APP_REG_RSC(messagingex)
+
+S60_APP_EXE(s60player)
+S60_APP_RESOURCE(s60player)
+UPGRADABLE_APP_REG_RSC(s60player)
+
+S60_APP_EXE(publishsubscribeex)
+S60_APP_RESOURCE(publishsubscribeex)
+UPGRADABLE_APP_REG_RSC(publishsubscribeex)
+data=\epoc32\data\z\resource\qt\crml\resources.qcrml resource\qt\crml\resources.qcrml
+data=\epoc32\data\z\resource\qt\crml\profile.qcrml resource\qt\crml\profile.qcrml
+
+#endif //__QT_MOBILITYTESTS_IBY__
diff --git a/src/s60installs/deviceconfiguration/symbian3_config.pri b/src/s60installs/deviceconfiguration/symbian3_config.pri
new file mode 100644
index 000000000..b97fa8d45
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/symbian3_config.pri
@@ -0,0 +1,50 @@
+CONFIG += release
+CONFIG_WIN32 += debug_and_release build_all release
+build_unit_tests = no
+build_public_unit_tests = no
+build_examples = no
+build_demos = no
+build_docs = no
+build_tools = no
+qmf_enabled = no
+!symbian:isEmpty($$QT_MOBILITY_INCLUDE):QT_MOBILITY_INCLUDE=$$QT_MOBILITY_PREFIX/include
+isEmpty($$QT_MOBILITY_LIB):QT_MOBILITY_LIB=$$QT_MOBILITY_PREFIX/lib
+isEmpty($$QT_MOBILITY_BIN):QT_MOBILITY_BIN=$$QT_MOBILITY_PREFIX/bin
+isEmpty($$QT_MOBILITY_PLUGINS):QT_MOBILITY_PLUGINS=$$QT_MOBILITY_PREFIX/plugins
+isEmpty($$QT_MOBILITY_EXAMPLES):QT_MOBILITY_EXAMPLES=$$QT_MOBILITY_PREFIX/bin
+isEmpty($$QT_MOBILITY_DEMOS):QT_MOBILITY_DEMOS=$$QT_MOBILITY_PREFIX/bin
+mobility_modules = bearer location contacts systeminfo publishsubscribe versit messaging sensors serviceframework multimedia gallery organizer feedback connectivity
+contains(mobility_modules,versit): mobility_modules *= contacts
+contains(mobility_modules,connectivity): mobility_modules *= serviceframework
+lbt_enabled = yes
+snap_enabled = yes
+occ_enabled = yes
+symbianenote_enabled = no
+symbiancntsim_enabled = yes
+symbiancntmodel_enabled = yes
+symbiancntmodelv2_enabled = no
+sensors_s60_31_enabled = no
+sensors_symbian_enabled = yes
+sensors_symbian_light_enabled = no
+hb_symbian_enabled = no
+audiorouting_s60_enabled = yes
+tunerlib_s60_enabled = no
+radioutility_s60_enabled = yes
+openmaxal_symbian_enabled = no
+surfaces_s60_enabled = yes
+messaging_freestyle_enabled = yes
+messaging_freestyle_mapi12_enabled = no
+callinformation_symbian_enabled = yes
+immersion_enabled = no
+symbian_camera_camautofocus_enabled = no
+symbian_camera_ecamadvsettings_enabled = yes
+symbian_camera_devvideorecord_enabled = yes
+advancedtouchfeedback_enabled = yes
+chwrmhaptics_enabled = yes
+mds_enabled = yes
+mds_25_enabled = yes
+mds_25_92mcl_enabled = yes
+nfc_enabled = yes
+btengconnman_symbian_enabled = yes
+btengdevman_symbian_enabled = yes
+MOBILITY_SD_MCL_BUILD = yes
diff --git a/src/s60installs/deviceconfiguration/symbian3_qtmobility.pkg b/src/s60installs/deviceconfiguration/symbian3_qtmobility.pkg
new file mode 100644
index 000000000..a96e9ac49
--- /dev/null
+++ b/src/s60installs/deviceconfiguration/symbian3_qtmobility.pkg
@@ -0,0 +1,128 @@
+
+; Language
+&EN
+
+; SIS header: name, uid, version
+#{"QtMobility"},(0x2002AC89),1,2,0,TYPE=SA,RU
+
+; Default dependency to Qt libraries
+(0x2001E61C), 4, 7, 2, {"Qt"}
+; Default HW/platform dependencies
+[0x102032BE],0,0,0,{"S60ProductID"}
+[0x102752AE],0,0,0,{"S60ProductID"}
+[0x1028315F],0,0,0,{"S60ProductID"}
+[0x20022E6D],0,0,0,{"S60ProductID"}
+[0x20032DE7],0,0,0,{"S60ProductID"}
+
+; Localised Vendor name
+%{"Nokia"}
+
+; Unique Vendor name
+:"Nokia"
+
+; DEPLOYMENT
+"/epoc32/release/armv5/urel/qtbearer.dll" - "!:\sys\bin\qtbearer.dll"
+"qtbearer{000a0000}.dll" - "!:\sys\bin\qtbearer{000a0000}.dll"
+"/epoc32/release/armv5/urel/qtlocation.dll" - "!:\sys\bin\qtlocation.dll"
+"/epoc32/release/armv5/urel/qtpublishsubscribe.dll" - "!:\sys\bin\qtpublishsubscribe.dll"
+"/epoc32/release/armv5/urel/qpspathmapperserver.exe" - "!:\sys\bin\qpspathmapperserver.exe"
+"/epoc32/release/armv5/urel/qtserviceframework.dll" - "!:\sys\bin\qtserviceframework.dll"
+"/epoc32/release/armv5/urel/qsfwdatabasemanagerserver.exe" - "!:\sys\bin\qsfwdatabasemanagerserver.exe"
+"/epoc32/release/armv5/urel/qtsysteminfo.dll" - "!:\sys\bin\qtsysteminfo.dll"
+"/epoc32/release/armv5/urel/qtmessaging.dll" - "!:\sys\bin\qtmessaging.dll"
+"/epoc32/release/armv5/urel/qtmultimediakit.dll" - "!:\sys\bin\qtmultimediakit.dll"
+"/epoc32/release/armv5/urel/qtsensors.dll" - "!:\sys\bin\qtsensors.dll"
+"/epoc32/release/armv5/urel/qtcontacts.dll" - "!:\sys\bin\qtcontacts.dll"
+"/epoc32/release/armv5/urel/qtversit.dll" - "!:\sys\bin\qtversit.dll"
+"/epoc32/release/armv5/urel/qtversitorganizer.dll" - "!:\sys\bin\qtversitorganizer.dll"
+"/epoc32/release/armv5/urel/qtfeedback.dll" - "!:\sys\bin\qtfeedback.dll"
+"/epoc32/release/armv5/urel/qtgallery.dll" - "!:\sys\bin\qtgallery.dll"
+"/epoc32/release/armv5/urel/qtorganizer.dll" - "!:\sys\bin\qtorganizer.dll"
+"/epoc32/release/armv5/urel/qtconnectivity.dll" - "!:\sys\bin\qtconnectivity.dll"
+
+"/epoc32/release/armv5/urel/qtcontacts_serviceactionmanager.dll" - "!:\sys\bin\qtcontacts_serviceactionmanager.dll"
+"/epoc32/data/z/resource/qt/plugins/contacts/qtcontacts_serviceactionmanager.qtplugin" - "!:\resource\qt\plugins\contacts\qtcontacts_serviceactionmanager.qtplugin"
+"/epoc32/release/armv5/urel/qtcontacts_symbian.dll" - "!:\sys\bin\qtcontacts_symbian.dll"
+"/epoc32/data/z/resource/qt/plugins/contacts/qtcontacts_symbian.qtplugin" - "!:\resource\qt\plugins\contacts\qtcontacts_symbian.qtplugin"
+"/epoc32/release/armv5/urel/qtcontacts_symbiansim.dll" - "!:\sys\bin\qtcontacts_symbiansim.dll"
+"/epoc32/data/z/resource/qt/plugins/contacts/qtcontacts_symbiansim.qtplugin" - "!:\resource\qt\plugins\contacts\qtcontacts_symbiansim.qtplugin"
+"/epoc32/release/armv5/urel/qtfeedback_mmk.dll" - "!:\sys\bin\qtfeedback_mmk.dll"
+"/epoc32/data/z/resource/qt/plugins/feedback/qtfeedback_mmk.qtplugin" - "!:\resource\qt\plugins\feedback\qtfeedback_mmk.qtplugin"
+"/epoc32/release/armv5/urel/qtfeedback_symbian.dll" - "!:\sys\bin\qtfeedback_symbian.dll"
+"/epoc32/data/z/resource/qt/plugins/feedback/qtfeedback_symbian.qtplugin" - "!:\resource\qt\plugins\feedback\qtfeedback_symbian.qtplugin"
+"/epoc32/release/armv5/urel/qtgeoservices_nokia.dll" - "!:\sys\bin\qtgeoservices_nokia.dll"
+"/epoc32/data/z/resource/qt/plugins/geoservices/qtgeoservices_nokia.qtplugin" - "!:\resource\qt\plugins\geoservices\qtgeoservices_nokia.qtplugin"
+"/epoc32/release/armv5/urel/qtlandmarks_symbian.dll" - "!:\sys\bin\qtlandmarks_symbian.dll"
+"/epoc32/data/z/resource/qt/plugins/landmarks/qtlandmarks_symbian.qtplugin" - "!:\resource\qt\plugins\landmarks\qtlandmarks_symbian.qtplugin"
+"/epoc32/release/armv5/urel/qtmultimediakit_m3u.dll" - "!:\sys\bin\qtmultimediakit_m3u.dll"
+"/epoc32/data/z/resource/qt/plugins/playlistformats/qtmultimediakit_m3u.qtplugin" - "!:\resource\qt\plugins\playlistformats\qtmultimediakit_m3u.qtplugin"
+"/epoc32/release/armv5/urel/qtmultimediakit_mmfengine.dll" - "!:\sys\bin\qtmultimediakit_mmfengine.dll"
+"/epoc32/data/z/resource/qt/plugins/mediaservice/qtmultimediakit_mmfengine.qtplugin" - "!:\resource\qt\plugins\mediaservice\qtmultimediakit_mmfengine.qtplugin"
+"/epoc32/release/armv5/urel/qtmultimediakit_ecamengine.dll" - "!:\sys\bin\qtmultimediakit_ecamengine.dll"
+"/epoc32/data/z/resource/qt/plugins/mediaservice/qtmultimediakit_ecamengine.qtplugin" - "!:\resource\qt\plugins\mediaservice\qtmultimediakit_ecamengine.qtplugin"
+"/epoc32/release/armv5/urel/qtorganizer_skeleton.dll" - "!:\sys\bin\qtorganizer_skeleton.dll"
+"/epoc32/data/z/resource/qt/plugins/organizer/qtorganizer_skeleton.qtplugin" - "!:\resource\qt\plugins\organizer\qtorganizer_skeleton.qtplugin"
+"/epoc32/release/armv5/urel/qtorganizer_symbian.dll" - "!:\sys\bin\qtorganizer_symbian.dll"
+"/epoc32/data/z/resource/qt/plugins/organizer/qtorganizer_symbian.qtplugin" - "!:\resource\qt\plugins\organizer\qtorganizer_symbian.qtplugin"
+"/epoc32/release/armv5/urel/qtsensors_generic.dll" - "!:\sys\bin\qtsensors_generic.dll"
+"/epoc32/data/z/resource/qt/plugins/sensors/qtsensors_generic.qtplugin" - "!:\resource\qt\plugins\sensors\qtsensors_generic.qtplugin"
+"/epoc32/release/armv5/urel/qtsensors_sym.dll" - "!:\sys\bin\qtsensors_sym.dll"
+"/epoc32/data/z/resource/qt/plugins/sensors/qtsensors_sym.qtplugin" - "!:\resource\qt\plugins\sensors\qtsensors_sym.qtplugin"
+"/epoc32/release/armv5/urel/qtversit_backuphandler.dll" - "!:\sys\bin\qtversit_backuphandler.dll"
+"/epoc32/data/z/resource/qt/plugins/versit/qtversit_backuphandler.qtplugin" - "!:\resource\qt\plugins\versit\qtversit_backuphandler.qtplugin"
+"/epoc32/release/armv5/urel/qtversit_vcardpreserver.dll" - "!:\sys\bin\qtversit_vcardpreserver.dll"
+"/epoc32/data/z/resource/qt/plugins/versit/qtversit_vcardpreserver.qtplugin" - "!:\resource\qt\plugins\versit\qtversit_vcardpreserver.qtplugin"
+"/epoc32/release/armv5/urel/cntversitfavoriteplugin.dll" - "!:\sys\bin\cntversitfavoriteplugin.dll"
+"/epoc32/data/z/resource/qt/plugins/versit/cntversitfavoriteplugin.qtplugin" - "!:\resource\qt\plugins\versit\cntversitfavoriteplugin.qtplugin"
+"/epoc32/release/armv5/urel/cntversitlandlineplugin.dll" - "!:\sys\bin\cntversitlandlineplugin.dll"
+"/epoc32/data/z/resource/qt/plugins/versit/cntversitlandlineplugin.qtplugin" - "!:\resource\qt\plugins\versit\cntversitlandlineplugin.qtplugin"
+"/epoc32/release/armv5/urel/cntversitmycardplugin.dll" - "!:\sys\bin\cntversitmycardplugin.dll"
+"/epoc32/data/z/resource/qt/plugins/versit/cntversitmycardplugin.qtplugin" - "!:\resource\qt\plugins\versit\cntversitmycardplugin.qtplugin"
+"/epoc32/release/armv5/urel/cntversitprefplugin.dll" - "!:\sys\bin\cntversitprefplugin.dll"
+"/epoc32/data/z/resource/qt/plugins/versit/cntversitprefplugin.qtplugin" - "!:\resource\qt\plugins\versit\cntversitprefplugin.qtplugin"
+"/epoc32/release/armv5/urel/declarative_contacts.dll" - "!:\sys\bin\declarative_contacts.dll"
+"/epoc32/data/z/resource/qt/imports/qtmobility/contacts/declarative_contacts.qtplugin" - "!:\resource\qt\imports\qtmobility\contacts\declarative_contacts.qtplugin"
+"/epoc32/data/z/resource/qt/imports/qtmobility/contacts/qmldir" - "!:\resource\qt\imports\qtmobility\contacts\qmldir"
+"/epoc32/release/armv5/urel/declarative_feedback.dll" - "!:\sys\bin\declarative_feedback.dll"
+"/epoc32/data/z/resource/qt/imports/qtmobility/feedback/declarative_feedback.qtplugin" - "!:\resource\qt\imports\qtmobility\feedback\declarative_feedback.qtplugin"
+"/epoc32/data/z/resource/qt/imports/qtmobility/feedback/qmldir" - "!:\resource\qt\imports\qtmobility\feedback\qmldir"
+"/epoc32/release/armv5/urel/declarative_gallery.dll" - "!:\sys\bin\declarative_gallery.dll"
+"/epoc32/data/z/resource/qt/imports/qtmobility/gallery/declarative_gallery.qtplugin" - "!:\resource\qt\imports\qtmobility\gallery\declarative_gallery.qtplugin"
+"/epoc32/data/z/resource/qt/imports/qtmobility/gallery/qmldir" - "!:\resource\qt\imports\qtmobility\gallery\qmldir"
+"/epoc32/release/armv5/urel/declarative_location.dll" - "!:\sys\bin\declarative_location.dll"
+"/epoc32/data/z/resource/qt/imports/qtmobility/location/declarative_location.qtplugin" - "!:\resource\qt\imports\qtmobility\location\declarative_location.qtplugin"
+"/epoc32/data/z/resource/qt/imports/qtmobility/location/qmldir" - "!:\resource\qt\imports\qtmobility\location\qmldir"
+"/epoc32/release/armv5/urel/declarative_messaging.dll" - "!:\sys\bin\declarative_messaging.dll"
+"/epoc32/data/z/resource/qt/imports/qtmobility/messaging/declarative_messaging.qtplugin" - "!:\resource\qt\imports\qtmobility\messaging\declarative_messaging.qtplugin"
+"/epoc32/data/z/resource/qt/imports/qtmobility/messaging/qmldir" - "!:\resource\qt\imports\qtmobility\messaging\qmldir"
+"/epoc32/release/armv5/urel/declarative_multimedia.dll" - "!:\sys\bin\declarative_multimedia.dll"
+"/epoc32/data/z/resource/qt/imports/qtmultimediakit/declarative_multimedia.qtplugin" - "!:\resource\qt\imports\qtmultimediakit\declarative_multimedia.qtplugin"
+"/epoc32/data/z/resource/qt/imports/qtmultimediakit/qmldir" - "!:\resource\qt\imports\qtmultimediakit\qmldir"
+"/epoc32/release/armv5/urel/declarative_organizer.dll" - "!:\sys\bin\declarative_organizer.dll"
+"/epoc32/data/z/resource/qt/imports/qtmobility/organizer/declarative_organizer.qtplugin" - "!:\resource\qt\imports\qtmobility\organizer\declarative_organizer.qtplugin"
+"/epoc32/data/z/resource/qt/imports/qtmobility/organizer/qmldir" - "!:\resource\qt\imports\qtmobility\organizer\qmldir"
+"/epoc32/release/armv5/urel/declarative_publishsubscribe.dll" - "!:\sys\bin\declarative_publishsubscribe.dll"
+"/epoc32/data/z/resource/qt/imports/qtmobility/publishsubscribe/declarative_publishsubscribe.qtplugin" - "!:\resource\qt\imports\qtmobility\publishsubscribe\declarative_publishsubscribe.qtplugin"
+"/epoc32/data/z/resource/qt/imports/qtmobility/publishsubscribe/qmldir" - "!:\resource\qt\imports\qtmobility\publishsubscribe\qmldir"
+"/epoc32/release/armv5/urel/declarative_sensors.dll" - "!:\sys\bin\declarative_sensors.dll"
+"/epoc32/data/z/resource/qt/imports/qtmobility/sensors/declarative_sensors.qtplugin" - "!:\resource\qt\imports\qtmobility\sensors\declarative_sensors.qtplugin"
+"/epoc32/data/z/resource/qt/imports/qtmobility/sensors/qmldir" - "!:\resource\qt\imports\qtmobility\sensors\qmldir"
+"/epoc32/release/armv5/urel/declarative_serviceframework.dll" - "!:\sys\bin\declarative_serviceframework.dll"
+"/epoc32/data/z/resource/qt/imports/qtmobility/serviceframework/declarative_serviceframework.qtplugin" - "!:\resource\qt\imports\qtmobility\serviceframework\declarative_serviceframework.qtplugin"
+"/epoc32/data/z/resource/qt/imports/qtmobility/serviceframework/qmldir" - "!:\resource\qt\imports\qtmobility\serviceframework\qmldir"
+"/epoc32/release/armv5/urel/declarative_systeminfo.dll" - "!:\sys\bin\declarative_systeminfo.dll"
+"/epoc32/data/z/resource/qt/imports/qtmobility/systeminfo/declarative_systeminfo.qtplugin" - "!:\resource\qt\imports\qtmobility\systeminfo\declarative_systeminfo.qtplugin"
+"/epoc32/data/z/resource/qt/imports/qtmobility/systeminfo/qmldir" - "!:\resource\qt\imports\qtmobility\systeminfo\qmldir"
+
+"/epoc32/data/z/private/10202D56/import/packages/2002AC89/backup_registration.xml" - "!:\private\10202D56\import\packages\2002AC89\backup_registration.xml"
+
+"/epoc32/release/armv5/urel/cntsrv.exe" - "!:\sys\bin\cntsrv.exe"
+"/epoc32/release/armv5/urel/cntmodel.dll" - "!:\sys\bin\cntmodel.dll"
+"/epoc32/release/armv5/urel/cntview.dll" - "!:\sys\bin\cntview.dll"
+"/epoc32/release/armv5/urel/cntplsql.dll" - "!:\sys\bin\cntplsql.dll"
+"/epoc32/release/armv5/urel/cntvcard.dll" - "!:\sys\bin\cntvcard.dll"
+"/epoc32/release/armv5/urel/cntphone.dll" - "!:\sys\bin\cntphone.dll"
+"/epoc32/release/armv5/urel/cntmatchlog.dll" - "!:\sys\bin\cntmatchlog.dll"
+"/epoc32/data/z/resource/plugins/cntvcard.rsc" - "!:\resource\plugins\cntvcard.rsc"
+"/epoc32/data/z/resource/plugins/cntphone.rsc" - "!:\resource\plugins\cntphone.rsc"
+"/epoc32/data/z/resource/plugins/cntmatchlog.rsc" - "!:\resource\plugins\cntmatchlog.rsc"
diff --git a/src/s60installs/eabi/QtMultimediaKitu.def b/src/s60installs/eabi/QtMultimediaKitu.def
new file mode 100644
index 000000000..178d78430
--- /dev/null
+++ b/src/s60installs/eabi/QtMultimediaKitu.def
@@ -0,0 +1,1640 @@
+EXPORTS
+ _ZN11QAudioInput11qt_metacallEN11QMetaObject4CallEiPPv @ 1 NONAME
+ _ZN11QAudioInput11qt_metacastEPKc @ 2 NONAME
+ _ZN11QAudioInput12stateChangedEN6QAudio5StateE @ 3 NONAME
+ _ZN11QAudioInput13setBufferSizeEi @ 4 NONAME
+ _ZN11QAudioInput16staticMetaObjectE @ 5 NONAME DATA 16
+ _ZN11QAudioInput17setNotifyIntervalEi @ 6 NONAME
+ _ZN11QAudioInput19getStaticMetaObjectEv @ 7 NONAME
+ _ZN11QAudioInput4stopEv @ 8 NONAME
+ _ZN11QAudioInput5resetEv @ 9 NONAME
+ _ZN11QAudioInput5startEP9QIODevice @ 10 NONAME
+ _ZN11QAudioInput5startEv @ 11 NONAME
+ _ZN11QAudioInput6notifyEv @ 12 NONAME
+ _ZN11QAudioInput6resumeEv @ 13 NONAME
+ _ZN11QAudioInput7suspendEv @ 14 NONAME
+ _ZN11QAudioInputC1ERK12QAudioFormatP7QObject @ 15 NONAME
+ _ZN11QAudioInputC1ERK16QAudioDeviceInfoRK12QAudioFormatP7QObject @ 16 NONAME
+ _ZN11QAudioInputC2ERK12QAudioFormatP7QObject @ 17 NONAME
+ _ZN11QAudioInputC2ERK16QAudioDeviceInfoRK12QAudioFormatP7QObject @ 18 NONAME
+ _ZN11QAudioInputD0Ev @ 19 NONAME
+ _ZN11QAudioInputD1Ev @ 20 NONAME
+ _ZN11QAudioInputD2Ev @ 21 NONAME
+ _ZN11QRadioTuner11bandChangedENS_4BandE @ 22 NONAME
+ _ZN11QRadioTuner11qt_metacallEN11QMetaObject4CallEiPPv @ 23 NONAME
+ _ZN11QRadioTuner11qt_metacastEPKc @ 24 NONAME
+ _ZN11QRadioTuner12cancelSearchEv @ 25 NONAME
+ _ZN11QRadioTuner12mutedChangedEb @ 26 NONAME
+ _ZN11QRadioTuner12setFrequencyEi @ 27 NONAME
+ _ZN11QRadioTuner12stateChangedENS_5StateE @ 28 NONAME
+ _ZN11QRadioTuner13searchForwardEv @ 29 NONAME
+ _ZN11QRadioTuner13setStereoModeENS_10StereoModeE @ 30 NONAME
+ _ZN11QRadioTuner13volumeChangedEi @ 31 NONAME
+ _ZN11QRadioTuner14searchBackwardEv @ 32 NONAME
+ _ZN11QRadioTuner16frequencyChangedEi @ 33 NONAME
+ _ZN11QRadioTuner16searchingChangedEb @ 34 NONAME
+ _ZN11QRadioTuner16staticMetaObjectE @ 35 NONAME DATA 16
+ _ZN11QRadioTuner19getStaticMetaObjectEv @ 36 NONAME
+ _ZN11QRadioTuner19stereoStatusChangedEb @ 37 NONAME
+ _ZN11QRadioTuner21signalStrengthChangedEi @ 38 NONAME
+ _ZN11QRadioTuner4stopEv @ 39 NONAME
+ _ZN11QRadioTuner5errorENS_5ErrorE @ 40 NONAME
+ _ZN11QRadioTuner5startEv @ 41 NONAME
+ _ZN11QRadioTuner7setBandENS_4BandE @ 42 NONAME
+ _ZN11QRadioTuner8setMutedEb @ 43 NONAME
+ _ZN11QRadioTuner9setVolumeEi @ 44 NONAME
+ _ZN11QRadioTunerC1EP7QObjectP21QMediaServiceProvider @ 45 NONAME
+ _ZN11QRadioTunerC2EP7QObjectP21QMediaServiceProvider @ 46 NONAME
+ _ZN11QRadioTunerD0Ev @ 47 NONAME
+ _ZN11QRadioTunerD1Ev @ 48 NONAME
+ _ZN11QRadioTunerD2Ev @ 49 NONAME
+ _ZN11QVideoFrame10setEndTimeEx @ 50 NONAME
+ _ZN11QVideoFrame12setFieldTypeENS_9FieldTypeE @ 51 NONAME
+ _ZN11QVideoFrame12setStartTimeEx @ 52 NONAME
+ _ZN11QVideoFrame26imageFormatFromPixelFormatENS_11PixelFormatE @ 53 NONAME
+ _ZN11QVideoFrame26pixelFormatFromImageFormatEN6QImage6FormatE @ 54 NONAME
+ _ZN11QVideoFrame3mapEN20QAbstractVideoBuffer7MapModeE @ 55 NONAME
+ _ZN11QVideoFrame4bitsEv @ 56 NONAME
+ _ZN11QVideoFrame5unmapEv @ 57 NONAME
+ _ZN11QVideoFrameC1EP20QAbstractVideoBufferRK5QSizeNS_11PixelFormatE @ 58 NONAME
+ _ZN11QVideoFrameC1ERK6QImage @ 59 NONAME
+ _ZN11QVideoFrameC1ERKS_ @ 60 NONAME
+ _ZN11QVideoFrameC1EiRK5QSizeiNS_11PixelFormatE @ 61 NONAME
+ _ZN11QVideoFrameC1Ev @ 62 NONAME
+ _ZN11QVideoFrameC2EP20QAbstractVideoBufferRK5QSizeNS_11PixelFormatE @ 63 NONAME
+ _ZN11QVideoFrameC2ERK6QImage @ 64 NONAME
+ _ZN11QVideoFrameC2ERKS_ @ 65 NONAME
+ _ZN11QVideoFrameC2EiRK5QSizeiNS_11PixelFormatE @ 66 NONAME
+ _ZN11QVideoFrameC2Ev @ 67 NONAME
+ _ZN11QVideoFrameD1Ev @ 68 NONAME
+ _ZN11QVideoFrameD2Ev @ 69 NONAME
+ _ZN11QVideoFrameaSERKS_ @ 70 NONAME
+ _ZN12QAudioFormat11setChannelsEi @ 71 NONAME
+ _ZN12QAudioFormat12setByteOrderENS_6EndianE @ 72 NONAME
+ _ZN12QAudioFormat12setFrequencyEi @ 73 NONAME
+ _ZN12QAudioFormat13setSampleRateEi @ 74 NONAME
+ _ZN12QAudioFormat13setSampleSizeEi @ 75 NONAME
+ _ZN12QAudioFormat13setSampleTypeENS_10SampleTypeE @ 76 NONAME
+ _ZN12QAudioFormat15setChannelCountEi @ 77 NONAME
+ _ZN12QAudioFormat8setCodecERK7QString @ 78 NONAME
+ _ZN12QAudioFormatC1ERKS_ @ 79 NONAME
+ _ZN12QAudioFormatC1Ev @ 80 NONAME
+ _ZN12QAudioFormatC2ERKS_ @ 81 NONAME
+ _ZN12QAudioFormatC2Ev @ 82 NONAME
+ _ZN12QAudioFormatD1Ev @ 83 NONAME
+ _ZN12QAudioFormatD2Ev @ 84 NONAME
+ _ZN12QAudioFormataSERKS_ @ 85 NONAME
+ _ZN12QAudioOutput11qt_metacallEN11QMetaObject4CallEiPPv @ 86 NONAME
+ _ZN12QAudioOutput11qt_metacastEPKc @ 87 NONAME
+ _ZN12QAudioOutput12stateChangedEN6QAudio5StateE @ 88 NONAME
+ _ZN12QAudioOutput13setBufferSizeEi @ 89 NONAME
+ _ZN12QAudioOutput16staticMetaObjectE @ 90 NONAME DATA 16
+ _ZN12QAudioOutput17setNotifyIntervalEi @ 91 NONAME
+ _ZN12QAudioOutput19getStaticMetaObjectEv @ 92 NONAME
+ _ZN12QAudioOutput4stopEv @ 93 NONAME
+ _ZN12QAudioOutput5resetEv @ 94 NONAME
+ _ZN12QAudioOutput5startEP9QIODevice @ 95 NONAME
+ _ZN12QAudioOutput5startEv @ 96 NONAME
+ _ZN12QAudioOutput6notifyEv @ 97 NONAME
+ _ZN12QAudioOutput6resumeEv @ 98 NONAME
+ _ZN12QAudioOutput7suspendEv @ 99 NONAME
+ _ZN12QAudioOutputC1ERK12QAudioFormatP7QObject @ 100 NONAME
+ _ZN12QAudioOutputC1ERK16QAudioDeviceInfoRK12QAudioFormatP7QObject @ 101 NONAME
+ _ZN12QAudioOutputC2ERK12QAudioFormatP7QObject @ 102 NONAME
+ _ZN12QAudioOutputC2ERK16QAudioDeviceInfoRK12QAudioFormatP7QObject @ 103 NONAME
+ _ZN12QAudioOutputD0Ev @ 104 NONAME
+ _ZN12QAudioOutputD1Ev @ 105 NONAME
+ _ZN12QAudioOutputD2Ev @ 106 NONAME
+ _ZN12QMediaObject11qt_metacallEN11QMetaObject4CallEiPPv @ 107 NONAME
+ _ZN12QMediaObject11qt_metacastEPKc @ 108 NONAME
+ _ZN12QMediaObject13setupMetaDataEv @ 109 NONAME
+ _ZN12QMediaObject15metaDataChangedEv @ 110 NONAME
+ _ZN12QMediaObject16addPropertyWatchERK10QByteArray @ 111 NONAME
+ _ZN12QMediaObject16staticMetaObjectE @ 112 NONAME DATA 16
+ _ZN12QMediaObject17setNotifyIntervalEi @ 113 NONAME
+ _ZN12QMediaObject19availabilityChangedEb @ 114 NONAME
+ _ZN12QMediaObject19getStaticMetaObjectEv @ 115 NONAME
+ _ZN12QMediaObject19removePropertyWatchERK10QByteArray @ 116 NONAME
+ _ZN12QMediaObject21notifyIntervalChangedEi @ 117 NONAME
+ _ZN12QMediaObject24metaDataAvailableChangedEb @ 118 NONAME
+ _ZN12QMediaObject4bindEP7QObject @ 119 NONAME
+ _ZN12QMediaObject6unbindEP7QObject @ 120 NONAME
+ _ZN12QMediaObjectC1EP7QObjectP13QMediaService @ 121 NONAME
+ _ZN12QMediaObjectC1ER19QMediaObjectPrivateP7QObjectP13QMediaService @ 122 NONAME
+ _ZN12QMediaObjectC2EP7QObjectP13QMediaService @ 123 NONAME
+ _ZN12QMediaObjectC2ER19QMediaObjectPrivateP7QObjectP13QMediaService @ 124 NONAME
+ _ZN12QMediaObjectD0Ev @ 125 NONAME
+ _ZN12QMediaObjectD1Ev @ 126 NONAME
+ _ZN12QMediaObjectD2Ev @ 127 NONAME
+ _ZN12QMediaPlayer10hasSupportERK7QStringRK11QStringList6QFlagsINS_4FlagEE @ 128 NONAME
+ _ZN12QMediaPlayer11qt_metacallEN11QMetaObject4CallEiPPv @ 129 NONAME
+ _ZN12QMediaPlayer11qt_metacastEPKc @ 130 NONAME
+ _ZN12QMediaPlayer11setPlaylistEP14QMediaPlaylist @ 131 NONAME
+ _ZN12QMediaPlayer11setPositionEx @ 132 NONAME
+ _ZN12QMediaPlayer12mediaChangedERK13QMediaContent @ 133 NONAME
+ _ZN12QMediaPlayer12mutedChangedEb @ 134 NONAME
+ _ZN12QMediaPlayer12stateChangedENS_5StateE @ 135 NONAME
+ _ZN12QMediaPlayer13volumeChangedEi @ 136 NONAME
+ _ZN12QMediaPlayer14setVideoOutputEP12QVideoWidget @ 137 NONAME
+ _ZN12QMediaPlayer14setVideoOutputEP18QGraphicsVideoItem @ 138 NONAME
+ _ZN12QMediaPlayer15durationChangedEx @ 139 NONAME
+ _ZN12QMediaPlayer15positionChangedEx @ 140 NONAME
+ _ZN12QMediaPlayer15seekableChangedEb @ 141 NONAME
+ _ZN12QMediaPlayer15setPlaybackRateEf @ 142 NONAME
+ _ZN12QMediaPlayer16staticMetaObjectE @ 143 NONAME DATA 16
+ _ZN12QMediaPlayer18mediaStatusChangedENS_11MediaStatusE @ 144 NONAME
+ _ZN12QMediaPlayer18supportedMimeTypesE6QFlagsINS_4FlagEE @ 145 NONAME
+ _ZN12QMediaPlayer19bufferStatusChangedEi @ 146 NONAME
+ _ZN12QMediaPlayer19getStaticMetaObjectEv @ 147 NONAME
+ _ZN12QMediaPlayer19playbackRateChangedEf @ 148 NONAME
+ _ZN12QMediaPlayer21audioAvailableChangedEb @ 149 NONAME
+ _ZN12QMediaPlayer21videoAvailableChangedEb @ 150 NONAME
+ _ZN12QMediaPlayer4bindEP7QObject @ 151 NONAME
+ _ZN12QMediaPlayer4playEv @ 152 NONAME
+ _ZN12QMediaPlayer4stopEv @ 153 NONAME
+ _ZN12QMediaPlayer5errorENS_5ErrorE @ 154 NONAME
+ _ZN12QMediaPlayer5pauseEv @ 155 NONAME
+ _ZN12QMediaPlayer6unbindEP7QObject @ 156 NONAME
+ _ZN12QMediaPlayer8setMediaERK13QMediaContentP9QIODevice @ 157 NONAME
+ _ZN12QMediaPlayer8setMutedEb @ 158 NONAME
+ _ZN12QMediaPlayer9setVolumeEi @ 159 NONAME
+ _ZN12QMediaPlayerC1EP7QObject6QFlagsINS_4FlagEEP21QMediaServiceProvider @ 160 NONAME
+ _ZN12QMediaPlayerC2EP7QObject6QFlagsINS_4FlagEEP21QMediaServiceProvider @ 161 NONAME
+ _ZN12QMediaPlayerD0Ev @ 162 NONAME
+ _ZN12QMediaPlayerD1Ev @ 163 NONAME
+ _ZN12QMediaPlayerD2Ev @ 164 NONAME
+ _ZN12QSoundEffect11qt_metacallEN11QMetaObject4CallEiPPv @ 165 NONAME
+ _ZN12QSoundEffect11qt_metacastEPKc @ 166 NONAME
+ _ZN12QSoundEffect12loopsChangedEv @ 167 NONAME ABSENT
+ _ZN12QSoundEffect12mutedChangedEv @ 168 NONAME
+ _ZN12QSoundEffect13sourceChangedEv @ 169 NONAME
+ _ZN12QSoundEffect13volumeChangedEv @ 170 NONAME
+ _ZN12QSoundEffect16staticMetaObjectE @ 171 NONAME DATA 16
+ _ZN12QSoundEffect19getStaticMetaObjectEv @ 172 NONAME
+ _ZN12QSoundEffect4playEv @ 173 NONAME
+ _ZN12QSoundEffect8setLoopsEi @ 174 NONAME ABSENT
+ _ZN12QSoundEffect8setMutedEb @ 175 NONAME
+ _ZN12QSoundEffect9setSourceERK4QUrl @ 176 NONAME
+ _ZN12QSoundEffect9setVolumeEf @ 177 NONAME
+ _ZN12QSoundEffectC1EP7QObject @ 178 NONAME
+ _ZN12QSoundEffectC2EP7QObject @ 179 NONAME
+ _ZN12QSoundEffectD0Ev @ 180 NONAME
+ _ZN12QSoundEffectD1Ev @ 181 NONAME
+ _ZN12QSoundEffectD2Ev @ 182 NONAME
+ _ZN12QVideoWidget10hueChangedEi @ 183 NONAME
+ _ZN12QVideoWidget10paintEventEP11QPaintEvent @ 184 NONAME
+ _ZN12QVideoWidget11qt_metacallEN11QMetaObject4CallEiPPv @ 185 NONAME
+ _ZN12QVideoWidget11qt_metacastEPKc @ 186 NONAME
+ _ZN12QVideoWidget11resizeEventEP12QResizeEvent @ 187 NONAME
+ _ZN12QVideoWidget11setContrastEi @ 188 NONAME
+ _ZN12QVideoWidget13setBrightnessEi @ 189 NONAME
+ _ZN12QVideoWidget13setFullScreenEb @ 190 NONAME
+ _ZN12QVideoWidget13setSaturationEi @ 191 NONAME
+ _ZN12QVideoWidget14setMediaObjectEP12QMediaObject @ 192 NONAME
+ _ZN12QVideoWidget15contrastChangedEi @ 193 NONAME
+ _ZN12QVideoWidget16staticMetaObjectE @ 194 NONAME DATA 16
+ _ZN12QVideoWidget17brightnessChangedEi @ 195 NONAME
+ _ZN12QVideoWidget17fullScreenChangedEb @ 196 NONAME
+ _ZN12QVideoWidget17saturationChangedEi @ 197 NONAME
+ _ZN12QVideoWidget18setAspectRatioModeEN2Qt15AspectRatioModeE @ 198 NONAME
+ _ZN12QVideoWidget19getStaticMetaObjectEv @ 199 NONAME
+ _ZN12QVideoWidget5eventEP6QEvent @ 200 NONAME
+ _ZN12QVideoWidget6setHueEi @ 201 NONAME
+ _ZN12QVideoWidget9hideEventEP10QHideEvent @ 202 NONAME
+ _ZN12QVideoWidget9moveEventEP10QMoveEvent @ 203 NONAME
+ _ZN12QVideoWidget9showEventEP10QShowEvent @ 204 NONAME
+ _ZN12QVideoWidgetC1EP7QWidget @ 205 NONAME
+ _ZN12QVideoWidgetC2EP7QWidget @ 206 NONAME
+ _ZN12QVideoWidgetD0Ev @ 207 NONAME
+ _ZN12QVideoWidgetD1Ev @ 208 NONAME
+ _ZN12QVideoWidgetD2Ev @ 209 NONAME
+ _ZN13QMediaContentC1ERK14QMediaResource @ 210 NONAME
+ _ZN13QMediaContentC1ERK15QNetworkRequest @ 211 NONAME
+ _ZN13QMediaContentC1ERK4QUrl @ 212 NONAME
+ _ZN13QMediaContentC1ERK5QListI14QMediaResourceE @ 213 NONAME
+ _ZN13QMediaContentC1ERKS_ @ 214 NONAME
+ _ZN13QMediaContentC1Ev @ 215 NONAME
+ _ZN13QMediaContentC2ERK14QMediaResource @ 216 NONAME
+ _ZN13QMediaContentC2ERK15QNetworkRequest @ 217 NONAME
+ _ZN13QMediaContentC2ERK4QUrl @ 218 NONAME
+ _ZN13QMediaContentC2ERK5QListI14QMediaResourceE @ 219 NONAME
+ _ZN13QMediaContentC2ERKS_ @ 220 NONAME
+ _ZN13QMediaContentC2Ev @ 221 NONAME
+ _ZN13QMediaContentD1Ev @ 222 NONAME
+ _ZN13QMediaContentD2Ev @ 223 NONAME
+ _ZN13QMediaContentaSERKS_ @ 224 NONAME
+ _ZN13QMediaControl11qt_metacallEN11QMetaObject4CallEiPPv @ 225 NONAME
+ _ZN13QMediaControl11qt_metacastEPKc @ 226 NONAME
+ _ZN13QMediaControl16staticMetaObjectE @ 227 NONAME DATA 16
+ _ZN13QMediaControl19getStaticMetaObjectEv @ 228 NONAME
+ _ZN13QMediaControlC1EP7QObject @ 229 NONAME
+ _ZN13QMediaControlC1ER20QMediaControlPrivateP7QObject @ 230 NONAME
+ _ZN13QMediaControlC2EP7QObject @ 231 NONAME
+ _ZN13QMediaControlC2ER20QMediaControlPrivateP7QObject @ 232 NONAME
+ _ZN13QMediaControlD0Ev @ 233 NONAME
+ _ZN13QMediaControlD1Ev @ 234 NONAME
+ _ZN13QMediaControlD2Ev @ 235 NONAME
+ _ZN13QMediaService11qt_metacallEN11QMetaObject4CallEiPPv @ 236 NONAME
+ _ZN13QMediaService11qt_metacastEPKc @ 237 NONAME
+ _ZN13QMediaService16staticMetaObjectE @ 238 NONAME DATA 16
+ _ZN13QMediaService19getStaticMetaObjectEv @ 239 NONAME
+ _ZN13QMediaServiceC2EP7QObject @ 240 NONAME
+ _ZN13QMediaServiceC2ER20QMediaServicePrivateP7QObject @ 241 NONAME
+ _ZN13QMediaServiceD0Ev @ 242 NONAME
+ _ZN13QMediaServiceD1Ev @ 243 NONAME
+ _ZN13QMediaServiceD2Ev @ 244 NONAME
+ _ZN14QMediaPlaylist10loadFailedEv @ 245 NONAME
+ _ZN14QMediaPlaylist11insertMediaEiRK13QMediaContent @ 246 NONAME
+ _ZN14QMediaPlaylist11insertMediaEiRK5QListI13QMediaContentE @ 247 NONAME
+ _ZN14QMediaPlaylist11qt_metacallEN11QMetaObject4CallEiPPv @ 248 NONAME
+ _ZN14QMediaPlaylist11qt_metacastEPKc @ 249 NONAME
+ _ZN14QMediaPlaylist11removeMediaEi @ 250 NONAME
+ _ZN14QMediaPlaylist11removeMediaEii @ 251 NONAME
+ _ZN14QMediaPlaylist12mediaChangedEii @ 252 NONAME
+ _ZN14QMediaPlaylist12mediaRemovedEii @ 253 NONAME
+ _ZN14QMediaPlaylist13mediaInsertedEii @ 254 NONAME
+ _ZN14QMediaPlaylist14setMediaObjectEP12QMediaObject @ 255 NONAME
+ _ZN14QMediaPlaylist15setCurrentIndexEi @ 256 NONAME
+ _ZN14QMediaPlaylist15setPlaybackModeENS_12PlaybackModeE @ 257 NONAME
+ _ZN14QMediaPlaylist16staticMetaObjectE @ 258 NONAME DATA 16
+ _ZN14QMediaPlaylist19currentIndexChangedEi @ 259 NONAME
+ _ZN14QMediaPlaylist19currentMediaChangedERK13QMediaContent @ 260 NONAME
+ _ZN14QMediaPlaylist19getStaticMetaObjectEv @ 261 NONAME
+ _ZN14QMediaPlaylist19playbackModeChangedENS_12PlaybackModeE @ 262 NONAME
+ _ZN14QMediaPlaylist21mediaAboutToBeRemovedEii @ 263 NONAME
+ _ZN14QMediaPlaylist22mediaAboutToBeInsertedEii @ 264 NONAME
+ _ZN14QMediaPlaylist4loadEP9QIODevicePKc @ 265 NONAME
+ _ZN14QMediaPlaylist4loadERK4QUrlPKc @ 266 NONAME
+ _ZN14QMediaPlaylist4nextEv @ 267 NONAME
+ _ZN14QMediaPlaylist4saveEP9QIODevicePKc @ 268 NONAME
+ _ZN14QMediaPlaylist4saveERK4QUrlPKc @ 269 NONAME
+ _ZN14QMediaPlaylist5clearEv @ 270 NONAME
+ _ZN14QMediaPlaylist6loadedEv @ 271 NONAME
+ _ZN14QMediaPlaylist7shuffleEv @ 272 NONAME
+ _ZN14QMediaPlaylist8addMediaERK13QMediaContent @ 273 NONAME
+ _ZN14QMediaPlaylist8addMediaERK5QListI13QMediaContentE @ 274 NONAME
+ _ZN14QMediaPlaylist8previousEv @ 275 NONAME
+ _ZN14QMediaPlaylistC1EP7QObject @ 276 NONAME
+ _ZN14QMediaPlaylistC2EP7QObject @ 277 NONAME
+ _ZN14QMediaPlaylistD0Ev @ 278 NONAME
+ _ZN14QMediaPlaylistD1Ev @ 279 NONAME
+ _ZN14QMediaPlaylistD2Ev @ 280 NONAME
+ _ZN14QMediaRecorder11qt_metacallEN11QMetaObject4CallEiPPv @ 281 NONAME
+ _ZN14QMediaRecorder11qt_metacastEPKc @ 282 NONAME
+ _ZN14QMediaRecorder11setMetaDataEN15QtMultimediaKit8MetaDataERK8QVariant @ 283 NONAME
+ _ZN14QMediaRecorder12mutedChangedEb @ 284 NONAME
+ _ZN14QMediaRecorder12stateChangedENS_5StateE @ 285 NONAME
+ _ZN14QMediaRecorder14setMediaObjectEP12QMediaObject @ 286 NONAME
+ _ZN14QMediaRecorder15durationChangedEx @ 287 NONAME
+ _ZN14QMediaRecorder15metaDataChangedEv @ 288 NONAME
+ _ZN14QMediaRecorder16staticMetaObjectE @ 289 NONAME DATA 16
+ _ZN14QMediaRecorder17setOutputLocationERK4QUrl @ 290 NONAME
+ _ZN14QMediaRecorder19getStaticMetaObjectEv @ 291 NONAME
+ _ZN14QMediaRecorder19setEncodingSettingsERK21QAudioEncoderSettingsRK21QVideoEncoderSettingsRK7QString @ 292 NONAME
+ _ZN14QMediaRecorder19setExtendedMetaDataERK7QStringRK8QVariant @ 293 NONAME
+ _ZN14QMediaRecorder23metaDataWritableChangedEb @ 294 NONAME
+ _ZN14QMediaRecorder24metaDataAvailableChangedEb @ 295 NONAME
+ _ZN14QMediaRecorder4stopEv @ 296 NONAME
+ _ZN14QMediaRecorder5errorENS_5ErrorE @ 297 NONAME
+ _ZN14QMediaRecorder5pauseEv @ 298 NONAME
+ _ZN14QMediaRecorder6recordEv @ 299 NONAME
+ _ZN14QMediaRecorder8setMutedEb @ 300 NONAME
+ _ZN14QMediaRecorderC1EP12QMediaObjectP7QObject @ 301 NONAME
+ _ZN14QMediaRecorderC2EP12QMediaObjectP7QObject @ 302 NONAME
+ _ZN14QMediaRecorderD0Ev @ 303 NONAME
+ _ZN14QMediaRecorderD1Ev @ 304 NONAME
+ _ZN14QMediaRecorderD2Ev @ 305 NONAME
+ _ZN14QMediaResource11setDataSizeEx @ 306 NONAME
+ _ZN14QMediaResource11setLanguageERK7QString @ 307 NONAME
+ _ZN14QMediaResource13setAudioCodecERK7QString @ 308 NONAME
+ _ZN14QMediaResource13setResolutionERK5QSize @ 309 NONAME
+ _ZN14QMediaResource13setResolutionEii @ 310 NONAME
+ _ZN14QMediaResource13setSampleRateEi @ 311 NONAME
+ _ZN14QMediaResource13setVideoCodecERK7QString @ 312 NONAME
+ _ZN14QMediaResource15setAudioBitRateEi @ 313 NONAME
+ _ZN14QMediaResource15setChannelCountEi @ 314 NONAME
+ _ZN14QMediaResource15setVideoBitRateEi @ 315 NONAME
+ _ZN14QMediaResourceC1ERK15QNetworkRequestRK7QString @ 316 NONAME
+ _ZN14QMediaResourceC1ERK4QUrlRK7QString @ 317 NONAME
+ _ZN14QMediaResourceC1ERKS_ @ 318 NONAME
+ _ZN14QMediaResourceC1Ev @ 319 NONAME
+ _ZN14QMediaResourceC2ERK15QNetworkRequestRK7QString @ 320 NONAME
+ _ZN14QMediaResourceC2ERK4QUrlRK7QString @ 321 NONAME
+ _ZN14QMediaResourceC2ERKS_ @ 322 NONAME
+ _ZN14QMediaResourceC2Ev @ 323 NONAME
+ _ZN14QMediaResourceD1Ev @ 324 NONAME
+ _ZN14QMediaResourceD2Ev @ 325 NONAME
+ _ZN14QMediaResourceaSERKS_ @ 326 NONAME
+ _ZN15QMediaTimeRange11addIntervalERK18QMediaTimeInterval @ 327 NONAME
+ _ZN15QMediaTimeRange11addIntervalExx @ 328 NONAME
+ _ZN15QMediaTimeRange12addTimeRangeERKS_ @ 329 NONAME
+ _ZN15QMediaTimeRange14removeIntervalERK18QMediaTimeInterval @ 330 NONAME
+ _ZN15QMediaTimeRange14removeIntervalExx @ 331 NONAME
+ _ZN15QMediaTimeRange15removeTimeRangeERKS_ @ 332 NONAME
+ _ZN15QMediaTimeRange5clearEv @ 333 NONAME
+ _ZN15QMediaTimeRangeC1ERK18QMediaTimeInterval @ 334 NONAME
+ _ZN15QMediaTimeRangeC1ERKS_ @ 335 NONAME
+ _ZN15QMediaTimeRangeC1Ev @ 336 NONAME
+ _ZN15QMediaTimeRangeC1Exx @ 337 NONAME
+ _ZN15QMediaTimeRangeC2ERK18QMediaTimeInterval @ 338 NONAME
+ _ZN15QMediaTimeRangeC2ERKS_ @ 339 NONAME
+ _ZN15QMediaTimeRangeC2Ev @ 340 NONAME
+ _ZN15QMediaTimeRangeC2Exx @ 341 NONAME
+ _ZN15QMediaTimeRangeD1Ev @ 342 NONAME
+ _ZN15QMediaTimeRangeD2Ev @ 343 NONAME
+ _ZN15QMediaTimeRangeaSERK18QMediaTimeInterval @ 344 NONAME
+ _ZN15QMediaTimeRangeaSERKS_ @ 345 NONAME
+ _ZN15QMediaTimeRangemIERK18QMediaTimeInterval @ 346 NONAME
+ _ZN15QMediaTimeRangemIERKS_ @ 347 NONAME
+ _ZN15QMediaTimeRangepLERK18QMediaTimeInterval @ 348 NONAME
+ _ZN15QMediaTimeRangepLERKS_ @ 349 NONAME
+ _ZN16QAudioDeviceInfo16availableDevicesEN6QAudio4ModeE @ 350 NONAME
+ _ZN16QAudioDeviceInfo18defaultInputDeviceEv @ 351 NONAME
+ _ZN16QAudioDeviceInfo19defaultOutputDeviceEv @ 352 NONAME
+ _ZN16QAudioDeviceInfoC1ERK7QStringRK10QByteArrayN6QAudio4ModeE @ 353 NONAME
+ _ZN16QAudioDeviceInfoC1ERKS_ @ 354 NONAME
+ _ZN16QAudioDeviceInfoC1Ev @ 355 NONAME
+ _ZN16QAudioDeviceInfoC2ERK7QStringRK10QByteArrayN6QAudio4ModeE @ 356 NONAME
+ _ZN16QAudioDeviceInfoC2ERKS_ @ 357 NONAME
+ _ZN16QAudioDeviceInfoC2Ev @ 358 NONAME
+ _ZN16QAudioDeviceInfoD1Ev @ 359 NONAME
+ _ZN16QAudioDeviceInfoD2Ev @ 360 NONAME
+ _ZN16QAudioDeviceInfoaSERKS_ @ 361 NONAME
+ _ZN17QImageVideoBuffer3mapEN20QAbstractVideoBuffer7MapModeEPiS2_ @ 362 NONAME
+ _ZN17QImageVideoBuffer5unmapEv @ 363 NONAME
+ _ZN17QImageVideoBufferC1ERK6QImage @ 364 NONAME
+ _ZN17QImageVideoBufferC2ERK6QImage @ 365 NONAME
+ _ZN17QImageVideoBufferD0Ev @ 366 NONAME
+ _ZN17QImageVideoBufferD1Ev @ 367 NONAME
+ _ZN17QImageVideoBufferD2Ev @ 368 NONAME
+ _ZN17QMediaImageViewer10setTimeoutEi @ 369 NONAME
+ _ZN17QMediaImageViewer10timerEventEP11QTimerEvent @ 370 NONAME
+ _ZN17QMediaImageViewer11qt_metacallEN11QMetaObject4CallEiPPv @ 371 NONAME
+ _ZN17QMediaImageViewer11qt_metacastEPKc @ 372 NONAME
+ _ZN17QMediaImageViewer11setPlaylistEP14QMediaPlaylist @ 373 NONAME
+ _ZN17QMediaImageViewer12mediaChangedERK13QMediaContent @ 374 NONAME
+ _ZN17QMediaImageViewer12stateChangedENS_5StateE @ 375 NONAME
+ _ZN17QMediaImageViewer16staticMetaObjectE @ 376 NONAME DATA 16
+ _ZN17QMediaImageViewer18elapsedTimeChangedEi @ 377 NONAME
+ _ZN17QMediaImageViewer18mediaStatusChangedENS_11MediaStatusE @ 378 NONAME
+ _ZN17QMediaImageViewer19getStaticMetaObjectEv @ 379 NONAME
+ _ZN17QMediaImageViewer4bindEP7QObject @ 380 NONAME
+ _ZN17QMediaImageViewer4playEv @ 381 NONAME
+ _ZN17QMediaImageViewer4stopEv @ 382 NONAME
+ _ZN17QMediaImageViewer5pauseEv @ 383 NONAME
+ _ZN17QMediaImageViewer6unbindEP7QObject @ 384 NONAME
+ _ZN17QMediaImageViewer8setMediaERK13QMediaContent @ 385 NONAME
+ _ZN17QMediaImageViewerC1EP7QObject @ 386 NONAME
+ _ZN17QMediaImageViewerC2EP7QObject @ 387 NONAME
+ _ZN17QMediaImageViewerD0Ev @ 388 NONAME
+ _ZN17QMediaImageViewerD1Ev @ 389 NONAME
+ _ZN17QMediaImageViewerD2Ev @ 390 NONAME
+ _ZN18QAudioSystemPlugin11qt_metacallEN11QMetaObject4CallEiPPv @ 391 NONAME
+ _ZN18QAudioSystemPlugin11qt_metacastEPKc @ 392 NONAME
+ _ZN18QAudioSystemPlugin16staticMetaObjectE @ 393 NONAME DATA 16
+ _ZN18QAudioSystemPlugin19getStaticMetaObjectEv @ 394 NONAME
+ _ZN18QAudioSystemPluginC2EP7QObject @ 395 NONAME
+ _ZN18QAudioSystemPluginD0Ev @ 396 NONAME
+ _ZN18QAudioSystemPluginD1Ev @ 397 NONAME
+ _ZN18QAudioSystemPluginD2Ev @ 398 NONAME
+ _ZN18QGraphicsVideoItem10itemChangeEN13QGraphicsItem18GraphicsItemChangeERK8QVariant @ 399 NONAME
+ _ZN18QGraphicsVideoItem10timerEventEP11QTimerEvent @ 400 NONAME
+ _ZN18QGraphicsVideoItem11qt_metacallEN11QMetaObject4CallEiPPv @ 401 NONAME
+ _ZN18QGraphicsVideoItem11qt_metacastEPKc @ 402 NONAME
+ _ZN18QGraphicsVideoItem14setMediaObjectEP12QMediaObject @ 403 NONAME
+ _ZN18QGraphicsVideoItem16staticMetaObjectE @ 404 NONAME DATA 16
+ _ZN18QGraphicsVideoItem17nativeSizeChangedERK6QSizeF @ 405 NONAME
+ _ZN18QGraphicsVideoItem18setAspectRatioModeEN2Qt15AspectRatioModeE @ 406 NONAME
+ _ZN18QGraphicsVideoItem19getStaticMetaObjectEv @ 407 NONAME
+ _ZN18QGraphicsVideoItem5paintEP8QPainterPK24QStyleOptionGraphicsItemP7QWidget @ 408 NONAME
+ _ZN18QGraphicsVideoItem7setSizeERK6QSizeF @ 409 NONAME
+ _ZN18QGraphicsVideoItem9setOffsetERK7QPointF @ 410 NONAME
+ _ZN18QGraphicsVideoItemC1EP13QGraphicsItem @ 411 NONAME
+ _ZN18QGraphicsVideoItemC2EP13QGraphicsItem @ 412 NONAME
+ _ZN18QGraphicsVideoItemD0Ev @ 413 NONAME
+ _ZN18QGraphicsVideoItemD1Ev @ 414 NONAME
+ _ZN18QGraphicsVideoItemD2Ev @ 415 NONAME
+ _ZN18QMediaTimeIntervalC1ERKS_ @ 416 NONAME
+ _ZN18QMediaTimeIntervalC1Ev @ 417 NONAME
+ _ZN18QMediaTimeIntervalC1Exx @ 418 NONAME
+ _ZN18QMediaTimeIntervalC2ERKS_ @ 419 NONAME
+ _ZN18QMediaTimeIntervalC2Ev @ 420 NONAME
+ _ZN18QMediaTimeIntervalC2Exx @ 421 NONAME
+ _ZN18QMemoryVideoBuffer3mapEN20QAbstractVideoBuffer7MapModeEPiS2_ @ 422 NONAME
+ _ZN18QMemoryVideoBuffer5unmapEv @ 423 NONAME
+ _ZN18QMemoryVideoBufferC1ERK10QByteArrayi @ 424 NONAME
+ _ZN18QMemoryVideoBufferC2ERK10QByteArrayi @ 425 NONAME
+ _ZN18QMemoryVideoBufferD0Ev @ 426 NONAME
+ _ZN18QMemoryVideoBufferD1Ev @ 427 NONAME
+ _ZN18QMemoryVideoBufferD2Ev @ 428 NONAME
+ _ZN18QRadioTunerControl11bandChangedEN11QRadioTuner4BandE @ 429 NONAME
+ _ZN18QRadioTunerControl11qt_metacallEN11QMetaObject4CallEiPPv @ 430 NONAME
+ _ZN18QRadioTunerControl11qt_metacastEPKc @ 431 NONAME
+ _ZN18QRadioTunerControl12mutedChangedEb @ 432 NONAME
+ _ZN18QRadioTunerControl12stateChangedEN11QRadioTuner5StateE @ 433 NONAME
+ _ZN18QRadioTunerControl13volumeChangedEi @ 434 NONAME
+ _ZN18QRadioTunerControl16frequencyChangedEi @ 435 NONAME
+ _ZN18QRadioTunerControl16searchingChangedEb @ 436 NONAME
+ _ZN18QRadioTunerControl16staticMetaObjectE @ 437 NONAME DATA 16
+ _ZN18QRadioTunerControl19getStaticMetaObjectEv @ 438 NONAME
+ _ZN18QRadioTunerControl19stereoStatusChangedEb @ 439 NONAME
+ _ZN18QRadioTunerControl21signalStrengthChangedEi @ 440 NONAME
+ _ZN18QRadioTunerControl5errorEN11QRadioTuner5ErrorE @ 441 NONAME
+ _ZN18QRadioTunerControlC2EP7QObject @ 442 NONAME
+ _ZN18QRadioTunerControlD0Ev @ 443 NONAME
+ _ZN18QRadioTunerControlD1Ev @ 444 NONAME
+ _ZN18QRadioTunerControlD2Ev @ 445 NONAME
+ _ZN19QAbstractAudioInput11qt_metacallEN11QMetaObject4CallEiPPv @ 446 NONAME
+ _ZN19QAbstractAudioInput11qt_metacastEPKc @ 447 NONAME
+ _ZN19QAbstractAudioInput12errorChangedEN6QAudio5ErrorE @ 448 NONAME
+ _ZN19QAbstractAudioInput12stateChangedEN6QAudio5StateE @ 449 NONAME
+ _ZN19QAbstractAudioInput16staticMetaObjectE @ 450 NONAME DATA 16
+ _ZN19QAbstractAudioInput19getStaticMetaObjectEv @ 451 NONAME
+ _ZN19QAbstractAudioInput6notifyEv @ 452 NONAME
+ _ZN19QAudioCaptureSource11qt_metacallEN11QMetaObject4CallEiPPv @ 453 NONAME
+ _ZN19QAudioCaptureSource11qt_metacastEPKc @ 454 NONAME
+ _ZN19QAudioCaptureSource13setAudioInputERK7QString @ 455 NONAME
+ _ZN19QAudioCaptureSource13statusChangedEv @ 456 NONAME
+ _ZN19QAudioCaptureSource16staticMetaObjectE @ 457 NONAME DATA 16
+ _ZN19QAudioCaptureSource19getStaticMetaObjectEv @ 458 NONAME
+ _ZN19QAudioCaptureSource23activeAudioInputChangedERK7QString @ 459 NONAME
+ _ZN19QAudioCaptureSource27availableAudioInputsChangedEv @ 460 NONAME
+ _ZN19QAudioCaptureSourceC1EP7QObjectP21QMediaServiceProvider @ 461 NONAME
+ _ZN19QAudioCaptureSourceC2EP7QObjectP21QMediaServiceProvider @ 462 NONAME
+ _ZN19QAudioCaptureSourceD0Ev @ 463 NONAME
+ _ZN19QAudioCaptureSourceD1Ev @ 464 NONAME
+ _ZN19QAudioCaptureSourceD2Ev @ 465 NONAME
+ _ZN19QMediaPlayerControl11qt_metacallEN11QMetaObject4CallEiPPv @ 466 NONAME
+ _ZN19QMediaPlayerControl11qt_metacastEPKc @ 467 NONAME
+ _ZN19QMediaPlayerControl12mediaChangedERK13QMediaContent @ 468 NONAME
+ _ZN19QMediaPlayerControl12mutedChangedEb @ 469 NONAME
+ _ZN19QMediaPlayerControl12stateChangedEN12QMediaPlayer5StateE @ 470 NONAME
+ _ZN19QMediaPlayerControl13volumeChangedEi @ 471 NONAME
+ _ZN19QMediaPlayerControl15durationChangedEx @ 472 NONAME
+ _ZN19QMediaPlayerControl15positionChangedEx @ 473 NONAME
+ _ZN19QMediaPlayerControl15seekableChangedEb @ 474 NONAME
+ _ZN19QMediaPlayerControl16staticMetaObjectE @ 475 NONAME DATA 16
+ _ZN19QMediaPlayerControl18mediaStatusChangedEN12QMediaPlayer11MediaStatusE @ 476 NONAME
+ _ZN19QMediaPlayerControl19bufferStatusChangedEi @ 477 NONAME
+ _ZN19QMediaPlayerControl19getStaticMetaObjectEv @ 478 NONAME
+ _ZN19QMediaPlayerControl19playbackRateChangedEf @ 479 NONAME
+ _ZN19QMediaPlayerControl21audioAvailableChangedEb @ 480 NONAME
+ _ZN19QMediaPlayerControl21videoAvailableChangedEb @ 481 NONAME
+ _ZN19QMediaPlayerControl30availablePlaybackRangesChangedERK15QMediaTimeRange @ 482 NONAME
+ _ZN19QMediaPlayerControl5errorEiRK7QString @ 483 NONAME
+ _ZN19QMediaPlayerControlC2EP7QObject @ 484 NONAME
+ _ZN19QMediaPlayerControlD0Ev @ 485 NONAME
+ _ZN19QMediaPlayerControlD1Ev @ 486 NONAME
+ _ZN19QMediaPlayerControlD2Ev @ 487 NONAME
+ _ZN19QVideoDeviceControl11qt_metacallEN11QMetaObject4CallEiPPv @ 488 NONAME
+ _ZN19QVideoDeviceControl11qt_metacastEPKc @ 489 NONAME
+ _ZN19QVideoDeviceControl14devicesChangedEv @ 490 NONAME
+ _ZN19QVideoDeviceControl16staticMetaObjectE @ 491 NONAME DATA 16
+ _ZN19QVideoDeviceControl19getStaticMetaObjectEv @ 492 NONAME
+ _ZN19QVideoDeviceControl21selectedDeviceChangedERK7QString @ 493 NONAME
+ _ZN19QVideoDeviceControl21selectedDeviceChangedEi @ 494 NONAME
+ _ZN19QVideoDeviceControlC2EP7QObject @ 495 NONAME
+ _ZN19QVideoDeviceControlD0Ev @ 496 NONAME
+ _ZN19QVideoDeviceControlD1Ev @ 497 NONAME
+ _ZN19QVideoDeviceControlD2Ev @ 498 NONAME
+ _ZN19QVideoSurfaceFormat11setPropertyEPKcRK8QVariant @ 499 NONAME
+ _ZN19QVideoSurfaceFormat11setViewportERK5QRect @ 500 NONAME
+ _ZN19QVideoSurfaceFormat12setFrameRateEf @ 501 NONAME
+ _ZN19QVideoSurfaceFormat12setFrameSizeERK5QSize @ 502 NONAME
+ _ZN19QVideoSurfaceFormat12setFrameSizeEii @ 503 NONAME
+ _ZN19QVideoSurfaceFormat18setYCbCrColorSpaceENS_15YCbCrColorSpaceE @ 504 NONAME
+ _ZN19QVideoSurfaceFormat19setPixelAspectRatioERK5QSize @ 505 NONAME
+ _ZN19QVideoSurfaceFormat19setPixelAspectRatioEii @ 506 NONAME
+ _ZN19QVideoSurfaceFormat20setScanLineDirectionENS_9DirectionE @ 507 NONAME
+ _ZN19QVideoSurfaceFormatC1ERK5QSizeN11QVideoFrame11PixelFormatEN20QAbstractVideoBuffer10HandleTypeE @ 508 NONAME
+ _ZN19QVideoSurfaceFormatC1ERKS_ @ 509 NONAME
+ _ZN19QVideoSurfaceFormatC1Ev @ 510 NONAME
+ _ZN19QVideoSurfaceFormatC2ERK5QSizeN11QVideoFrame11PixelFormatEN20QAbstractVideoBuffer10HandleTypeE @ 511 NONAME
+ _ZN19QVideoSurfaceFormatC2ERKS_ @ 512 NONAME
+ _ZN19QVideoSurfaceFormatC2Ev @ 513 NONAME
+ _ZN19QVideoSurfaceFormatD1Ev @ 514 NONAME
+ _ZN19QVideoSurfaceFormatD2Ev @ 515 NONAME
+ _ZN19QVideoSurfaceFormataSERKS_ @ 516 NONAME
+ _ZN19QVideoWidgetControl10hueChangedEi @ 517 NONAME
+ _ZN19QVideoWidgetControl11qt_metacallEN11QMetaObject4CallEiPPv @ 518 NONAME
+ _ZN19QVideoWidgetControl11qt_metacastEPKc @ 519 NONAME
+ _ZN19QVideoWidgetControl15contrastChangedEi @ 520 NONAME
+ _ZN19QVideoWidgetControl16staticMetaObjectE @ 521 NONAME DATA 16
+ _ZN19QVideoWidgetControl17brightnessChangedEi @ 522 NONAME
+ _ZN19QVideoWidgetControl17fullScreenChangedEb @ 523 NONAME
+ _ZN19QVideoWidgetControl17saturationChangedEi @ 524 NONAME
+ _ZN19QVideoWidgetControl19getStaticMetaObjectEv @ 525 NONAME
+ _ZN19QVideoWidgetControlC2EP7QObject @ 526 NONAME
+ _ZN19QVideoWidgetControlD0Ev @ 527 NONAME
+ _ZN19QVideoWidgetControlD1Ev @ 528 NONAME
+ _ZN19QVideoWidgetControlD2Ev @ 529 NONAME
+ _ZN19QVideoWindowControl10hueChangedEi @ 530 NONAME
+ _ZN19QVideoWindowControl11qt_metacallEN11QMetaObject4CallEiPPv @ 531 NONAME
+ _ZN19QVideoWindowControl11qt_metacastEPKc @ 532 NONAME
+ _ZN19QVideoWindowControl15contrastChangedEi @ 533 NONAME
+ _ZN19QVideoWindowControl16staticMetaObjectE @ 534 NONAME DATA 16
+ _ZN19QVideoWindowControl17brightnessChangedEi @ 535 NONAME
+ _ZN19QVideoWindowControl17fullScreenChangedEb @ 536 NONAME
+ _ZN19QVideoWindowControl17nativeSizeChangedEv @ 537 NONAME
+ _ZN19QVideoWindowControl17saturationChangedEi @ 538 NONAME
+ _ZN19QVideoWindowControl19getStaticMetaObjectEv @ 539 NONAME
+ _ZN19QVideoWindowControlC2EP7QObject @ 540 NONAME
+ _ZN19QVideoWindowControlD0Ev @ 541 NONAME
+ _ZN19QVideoWindowControlD1Ev @ 542 NONAME
+ _ZN19QVideoWindowControlD2Ev @ 543 NONAME
+ _ZN20QAbstractAudioOutput11qt_metacallEN11QMetaObject4CallEiPPv @ 544 NONAME
+ _ZN20QAbstractAudioOutput11qt_metacastEPKc @ 545 NONAME
+ _ZN20QAbstractAudioOutput12errorChangedEN6QAudio5ErrorE @ 546 NONAME
+ _ZN20QAbstractAudioOutput12stateChangedEN6QAudio5StateE @ 547 NONAME
+ _ZN20QAbstractAudioOutput16staticMetaObjectE @ 548 NONAME DATA 16
+ _ZN20QAbstractAudioOutput19getStaticMetaObjectEv @ 549 NONAME
+ _ZN20QAbstractAudioOutput6notifyEv @ 550 NONAME
+ _ZN20QAbstractVideoBufferC2ENS_10HandleTypeE @ 551 NONAME
+ _ZN20QAbstractVideoBufferC2ER27QAbstractVideoBufferPrivateNS_10HandleTypeE @ 552 NONAME
+ _ZN20QAbstractVideoBufferD0Ev @ 553 NONAME
+ _ZN20QAbstractVideoBufferD1Ev @ 554 NONAME
+ _ZN20QAbstractVideoBufferD2Ev @ 555 NONAME
+ _ZN20QAudioEncoderControl11qt_metacallEN11QMetaObject4CallEiPPv @ 556 NONAME
+ _ZN20QAudioEncoderControl11qt_metacastEPKc @ 557 NONAME
+ _ZN20QAudioEncoderControl16staticMetaObjectE @ 558 NONAME DATA 16
+ _ZN20QAudioEncoderControl19getStaticMetaObjectEv @ 559 NONAME
+ _ZN20QAudioEncoderControlC2EP7QObject @ 560 NONAME
+ _ZN20QAudioEncoderControlD0Ev @ 561 NONAME
+ _ZN20QAudioEncoderControlD1Ev @ 562 NONAME
+ _ZN20QAudioEncoderControlD2Ev @ 563 NONAME
+ _ZN20QImageEncoderControl11qt_metacallEN11QMetaObject4CallEiPPv @ 564 NONAME
+ _ZN20QImageEncoderControl11qt_metacastEPKc @ 565 NONAME
+ _ZN20QImageEncoderControl16staticMetaObjectE @ 566 NONAME DATA 16
+ _ZN20QImageEncoderControl19getStaticMetaObjectEv @ 567 NONAME
+ _ZN20QImageEncoderControlC2EP7QObject @ 568 NONAME
+ _ZN20QImageEncoderControlD0Ev @ 569 NONAME
+ _ZN20QImageEncoderControlD1Ev @ 570 NONAME
+ _ZN20QImageEncoderControlD2Ev @ 571 NONAME
+ _ZN20QMediaPlaylistReaderD0Ev @ 572 NONAME
+ _ZN20QMediaPlaylistReaderD1Ev @ 573 NONAME
+ _ZN20QMediaPlaylistReaderD2Ev @ 574 NONAME
+ _ZN20QMediaPlaylistWriterD0Ev @ 575 NONAME
+ _ZN20QMediaPlaylistWriterD1Ev @ 576 NONAME
+ _ZN20QMediaPlaylistWriterD2Ev @ 577 NONAME
+ _ZN20QMediaStreamsControl11qt_metacallEN11QMetaObject4CallEiPPv @ 578 NONAME
+ _ZN20QMediaStreamsControl11qt_metacastEPKc @ 579 NONAME
+ _ZN20QMediaStreamsControl14streamsChangedEv @ 580 NONAME
+ _ZN20QMediaStreamsControl16staticMetaObjectE @ 581 NONAME DATA 16
+ _ZN20QMediaStreamsControl19getStaticMetaObjectEv @ 582 NONAME
+ _ZN20QMediaStreamsControl20activeStreamsChangedEv @ 583 NONAME
+ _ZN20QMediaStreamsControlC2EP7QObject @ 584 NONAME
+ _ZN20QMediaStreamsControlD0Ev @ 585 NONAME
+ _ZN20QMediaStreamsControlD1Ev @ 586 NONAME
+ _ZN20QMediaStreamsControlD2Ev @ 587 NONAME
+ _ZN20QVideoEncoderControl11qt_metacallEN11QMetaObject4CallEiPPv @ 588 NONAME
+ _ZN20QVideoEncoderControl11qt_metacastEPKc @ 589 NONAME
+ _ZN20QVideoEncoderControl16staticMetaObjectE @ 590 NONAME DATA 16
+ _ZN20QVideoEncoderControl19getStaticMetaObjectEv @ 591 NONAME
+ _ZN20QVideoEncoderControlC2EP7QObject @ 592 NONAME
+ _ZN20QVideoEncoderControlD0Ev @ 593 NONAME
+ _ZN20QVideoEncoderControlD1Ev @ 594 NONAME
+ _ZN20QVideoEncoderControlD2Ev @ 595 NONAME
+ _ZN21QAbstractVideoSurface11qt_metacallEN11QMetaObject4CallEiPPv @ 596 NONAME
+ _ZN21QAbstractVideoSurface11qt_metacastEPKc @ 597 NONAME
+ _ZN21QAbstractVideoSurface13activeChangedEb @ 598 NONAME
+ _ZN21QAbstractVideoSurface16staticMetaObjectE @ 599 NONAME DATA 16
+ _ZN21QAbstractVideoSurface19getStaticMetaObjectEv @ 600 NONAME
+ _ZN21QAbstractVideoSurface20surfaceFormatChangedERK19QVideoSurfaceFormat @ 601 NONAME
+ _ZN21QAbstractVideoSurface23supportedFormatsChangedEv @ 602 NONAME
+ _ZN21QAbstractVideoSurface4stopEv @ 603 NONAME
+ _ZN21QAbstractVideoSurface5startERK19QVideoSurfaceFormat @ 604 NONAME
+ _ZN21QAbstractVideoSurface8setErrorENS_5ErrorE @ 605 NONAME
+ _ZN21QAbstractVideoSurfaceC2EP7QObject @ 606 NONAME
+ _ZN21QAbstractVideoSurfaceC2ER28QAbstractVideoSurfacePrivateP7QObject @ 607 NONAME
+ _ZN21QAbstractVideoSurfaceD0Ev @ 608 NONAME
+ _ZN21QAbstractVideoSurfaceD1Ev @ 609 NONAME
+ _ZN21QAbstractVideoSurfaceD2Ev @ 610 NONAME
+ _ZN21QAudioEncoderSettings10setBitRateEi @ 611 NONAME
+ _ZN21QAudioEncoderSettings10setQualityEN15QtMultimediaKit15EncodingQualityE @ 612 NONAME
+ _ZN21QAudioEncoderSettings13setSampleRateEi @ 613 NONAME
+ _ZN21QAudioEncoderSettings15setChannelCountEi @ 614 NONAME
+ _ZN21QAudioEncoderSettings15setEncodingModeEN15QtMultimediaKit12EncodingModeE @ 615 NONAME
+ _ZN21QAudioEncoderSettings8setCodecERK7QString @ 616 NONAME
+ _ZN21QAudioEncoderSettingsC1ERKS_ @ 617 NONAME
+ _ZN21QAudioEncoderSettingsC1Ev @ 618 NONAME
+ _ZN21QAudioEncoderSettingsC2ERKS_ @ 619 NONAME
+ _ZN21QAudioEncoderSettingsC2Ev @ 620 NONAME
+ _ZN21QAudioEncoderSettingsD1Ev @ 621 NONAME
+ _ZN21QAudioEncoderSettingsD2Ev @ 622 NONAME
+ _ZN21QAudioEncoderSettingsaSERKS_ @ 623 NONAME
+ _ZN21QImageEncoderSettings10setQualityEN15QtMultimediaKit15EncodingQualityE @ 624 NONAME
+ _ZN21QImageEncoderSettings13setResolutionERK5QSize @ 625 NONAME
+ _ZN21QImageEncoderSettings13setResolutionEii @ 626 NONAME
+ _ZN21QImageEncoderSettings8setCodecERK7QString @ 627 NONAME
+ _ZN21QImageEncoderSettingsC1ERKS_ @ 628 NONAME
+ _ZN21QImageEncoderSettingsC1Ev @ 629 NONAME
+ _ZN21QImageEncoderSettingsC2ERKS_ @ 630 NONAME
+ _ZN21QImageEncoderSettingsC2Ev @ 631 NONAME
+ _ZN21QImageEncoderSettingsD1Ev @ 632 NONAME
+ _ZN21QImageEncoderSettingsD2Ev @ 633 NONAME
+ _ZN21QImageEncoderSettingsaSERKS_ @ 634 NONAME
+ _ZN21QMediaPlaylistControl11qt_metacallEN11QMetaObject4CallEiPPv @ 635 NONAME
+ _ZN21QMediaPlaylistControl11qt_metacastEPKc @ 636 NONAME
+ _ZN21QMediaPlaylistControl16staticMetaObjectE @ 637 NONAME DATA 16
+ _ZN21QMediaPlaylistControl19currentIndexChangedEi @ 638 NONAME
+ _ZN21QMediaPlaylistControl19currentMediaChangedERK13QMediaContent @ 639 NONAME
+ _ZN21QMediaPlaylistControl19getStaticMetaObjectEv @ 640 NONAME
+ _ZN21QMediaPlaylistControl19playbackModeChangedEN14QMediaPlaylist12PlaybackModeE @ 641 NONAME
+ _ZN21QMediaPlaylistControl23playlistProviderChangedEv @ 642 NONAME
+ _ZN21QMediaPlaylistControlC2EP7QObject @ 643 NONAME
+ _ZN21QMediaPlaylistControlD0Ev @ 644 NONAME
+ _ZN21QMediaPlaylistControlD1Ev @ 645 NONAME
+ _ZN21QMediaPlaylistControlD2Ev @ 646 NONAME
+ _ZN21QMediaRecorderControl11qt_metacallEN11QMetaObject4CallEiPPv @ 647 NONAME
+ _ZN21QMediaRecorderControl11qt_metacastEPKc @ 648 NONAME
+ _ZN21QMediaRecorderControl12mutedChangedEb @ 649 NONAME
+ _ZN21QMediaRecorderControl12stateChangedEN14QMediaRecorder5StateE @ 650 NONAME
+ _ZN21QMediaRecorderControl15durationChangedEx @ 651 NONAME
+ _ZN21QMediaRecorderControl16staticMetaObjectE @ 652 NONAME DATA 16
+ _ZN21QMediaRecorderControl19getStaticMetaObjectEv @ 653 NONAME
+ _ZN21QMediaRecorderControl5errorEiRK7QString @ 654 NONAME
+ _ZN21QMediaRecorderControlC2EP7QObject @ 655 NONAME
+ _ZN21QMediaRecorderControlD0Ev @ 656 NONAME
+ _ZN21QMediaRecorderControlD1Ev @ 657 NONAME
+ _ZN21QMediaRecorderControlD2Ev @ 658 NONAME
+ _ZN21QMediaServiceProvider11qt_metacallEN11QMetaObject4CallEiPPv @ 659 NONAME
+ _ZN21QMediaServiceProvider11qt_metacastEPKc @ 660 NONAME
+ _ZN21QMediaServiceProvider16staticMetaObjectE @ 661 NONAME DATA 16
+ _ZN21QMediaServiceProvider17deviceDescriptionERK10QByteArrayS2_ @ 662 NONAME
+ _ZN21QMediaServiceProvider19getStaticMetaObjectEv @ 663 NONAME
+ _ZN21QMediaServiceProvider22defaultServiceProviderEv @ 664 NONAME
+ _ZN21QVideoEncoderSettings10setBitRateEi @ 665 NONAME
+ _ZN21QVideoEncoderSettings10setQualityEN15QtMultimediaKit15EncodingQualityE @ 666 NONAME
+ _ZN21QVideoEncoderSettings12setFrameRateEf @ 667 NONAME
+ _ZN21QVideoEncoderSettings13setResolutionERK5QSize @ 668 NONAME
+ _ZN21QVideoEncoderSettings13setResolutionEii @ 669 NONAME
+ _ZN21QVideoEncoderSettings15setEncodingModeEN15QtMultimediaKit12EncodingModeE @ 670 NONAME
+ _ZN21QVideoEncoderSettings8setCodecERK7QString @ 671 NONAME
+ _ZN21QVideoEncoderSettingsC1ERKS_ @ 672 NONAME
+ _ZN21QVideoEncoderSettingsC1Ev @ 673 NONAME
+ _ZN21QVideoEncoderSettingsC2ERKS_ @ 674 NONAME
+ _ZN21QVideoEncoderSettingsC2Ev @ 675 NONAME
+ _ZN21QVideoEncoderSettingsD1Ev @ 676 NONAME
+ _ZN21QVideoEncoderSettingsD2Ev @ 677 NONAME
+ _ZN21QVideoEncoderSettingsaSERKS_ @ 678 NONAME
+ _ZN21QVideoRendererControl11qt_metacallEN11QMetaObject4CallEiPPv @ 679 NONAME
+ _ZN21QVideoRendererControl11qt_metacastEPKc @ 680 NONAME
+ _ZN21QVideoRendererControl16staticMetaObjectE @ 681 NONAME DATA 16
+ _ZN21QVideoRendererControl19getStaticMetaObjectEv @ 682 NONAME
+ _ZN21QVideoRendererControlC2EP7QObject @ 683 NONAME
+ _ZN21QVideoRendererControlD0Ev @ 684 NONAME
+ _ZN21QVideoRendererControlD1Ev @ 685 NONAME
+ _ZN21QVideoRendererControlD2Ev @ 686 NONAME
+ _ZN22QAudioEndpointSelector11qt_metacallEN11QMetaObject4CallEiPPv @ 687 NONAME
+ _ZN22QAudioEndpointSelector11qt_metacastEPKc @ 688 NONAME
+ _ZN22QAudioEndpointSelector16staticMetaObjectE @ 689 NONAME DATA 16
+ _ZN22QAudioEndpointSelector19getStaticMetaObjectEv @ 690 NONAME
+ _ZN22QAudioEndpointSelector21activeEndpointChangedERK7QString @ 691 NONAME
+ _ZN22QAudioEndpointSelector25availableEndpointsChangedEv @ 692 NONAME
+ _ZN22QAudioEndpointSelectorC2EP7QObject @ 693 NONAME
+ _ZN22QAudioEndpointSelectorD0Ev @ 694 NONAME
+ _ZN22QAudioEndpointSelectorD1Ev @ 695 NONAME
+ _ZN22QAudioEndpointSelectorD2Ev @ 696 NONAME
+ _ZN22QMediaContainerControl11qt_metacallEN11QMetaObject4CallEiPPv @ 697 NONAME
+ _ZN22QMediaContainerControl11qt_metacastEPKc @ 698 NONAME
+ _ZN22QMediaContainerControl16staticMetaObjectE @ 699 NONAME DATA 16
+ _ZN22QMediaContainerControl19getStaticMetaObjectEv @ 700 NONAME
+ _ZN22QMediaContainerControlC2EP7QObject @ 701 NONAME
+ _ZN22QMediaContainerControlD0Ev @ 702 NONAME
+ _ZN22QMediaContainerControlD1Ev @ 703 NONAME
+ _ZN22QMediaContainerControlD2Ev @ 704 NONAME
+ _ZN22QMediaPlaylistIOPlugin11qt_metacallEN11QMetaObject4CallEiPPv @ 705 NONAME
+ _ZN22QMediaPlaylistIOPlugin11qt_metacastEPKc @ 706 NONAME
+ _ZN22QMediaPlaylistIOPlugin16staticMetaObjectE @ 707 NONAME DATA 16
+ _ZN22QMediaPlaylistIOPlugin19getStaticMetaObjectEv @ 708 NONAME
+ _ZN22QMediaPlaylistIOPluginC2EP7QObject @ 709 NONAME
+ _ZN22QMediaPlaylistIOPluginD0Ev @ 710 NONAME
+ _ZN22QMediaPlaylistIOPluginD1Ev @ 711 NONAME
+ _ZN22QMediaPlaylistIOPluginD2Ev @ 712 NONAME
+ _ZN22QMediaPlaylistProvider10loadFailedEN14QMediaPlaylist5ErrorERK7QString @ 713 NONAME
+ _ZN22QMediaPlaylistProvider11insertMediaEiRK13QMediaContent @ 714 NONAME
+ _ZN22QMediaPlaylistProvider11insertMediaEiRK5QListI13QMediaContentE @ 715 NONAME
+ _ZN22QMediaPlaylistProvider11qt_metacallEN11QMetaObject4CallEiPPv @ 716 NONAME
+ _ZN22QMediaPlaylistProvider11qt_metacastEPKc @ 717 NONAME
+ _ZN22QMediaPlaylistProvider11removeMediaEi @ 718 NONAME
+ _ZN22QMediaPlaylistProvider11removeMediaEii @ 719 NONAME
+ _ZN22QMediaPlaylistProvider12mediaChangedEii @ 720 NONAME
+ _ZN22QMediaPlaylistProvider12mediaRemovedEii @ 721 NONAME
+ _ZN22QMediaPlaylistProvider13mediaInsertedEii @ 722 NONAME
+ _ZN22QMediaPlaylistProvider16staticMetaObjectE @ 723 NONAME DATA 16
+ _ZN22QMediaPlaylistProvider19getStaticMetaObjectEv @ 724 NONAME
+ _ZN22QMediaPlaylistProvider21mediaAboutToBeRemovedEii @ 725 NONAME
+ _ZN22QMediaPlaylistProvider22mediaAboutToBeInsertedEii @ 726 NONAME
+ _ZN22QMediaPlaylistProvider4loadEP9QIODevicePKc @ 727 NONAME
+ _ZN22QMediaPlaylistProvider4loadERK4QUrlPKc @ 728 NONAME
+ _ZN22QMediaPlaylistProvider4saveEP9QIODevicePKc @ 729 NONAME
+ _ZN22QMediaPlaylistProvider4saveERK4QUrlPKc @ 730 NONAME
+ _ZN22QMediaPlaylistProvider5clearEv @ 731 NONAME
+ _ZN22QMediaPlaylistProvider6loadedEv @ 732 NONAME
+ _ZN22QMediaPlaylistProvider7shuffleEv @ 733 NONAME
+ _ZN22QMediaPlaylistProvider8addMediaERK13QMediaContent @ 734 NONAME
+ _ZN22QMediaPlaylistProvider8addMediaERK5QListI13QMediaContentE @ 735 NONAME
+ _ZN22QMediaPlaylistProviderC2EP7QObject @ 736 NONAME
+ _ZN22QMediaPlaylistProviderC2ER29QMediaPlaylistProviderPrivateP7QObject @ 737 NONAME
+ _ZN22QMediaPlaylistProviderD0Ev @ 738 NONAME
+ _ZN22QMediaPlaylistProviderD1Ev @ 739 NONAME
+ _ZN22QMediaPlaylistProviderD2Ev @ 740 NONAME
+ _ZN22QMetaDataReaderControl11qt_metacallEN11QMetaObject4CallEiPPv @ 741 NONAME
+ _ZN22QMetaDataReaderControl11qt_metacastEPKc @ 742 NONAME
+ _ZN22QMetaDataReaderControl15metaDataChangedEv @ 743 NONAME
+ _ZN22QMetaDataReaderControl16staticMetaObjectE @ 744 NONAME DATA 16
+ _ZN22QMetaDataReaderControl19getStaticMetaObjectEv @ 745 NONAME
+ _ZN22QMetaDataReaderControl24metaDataAvailableChangedEb @ 746 NONAME
+ _ZN22QMetaDataReaderControlC2EP7QObject @ 747 NONAME
+ _ZN22QMetaDataReaderControlD0Ev @ 748 NONAME
+ _ZN22QMetaDataReaderControlD1Ev @ 749 NONAME
+ _ZN22QMetaDataReaderControlD2Ev @ 750 NONAME
+ _ZN22QMetaDataWriterControl11qt_metacallEN11QMetaObject4CallEiPPv @ 751 NONAME
+ _ZN22QMetaDataWriterControl11qt_metacastEPKc @ 752 NONAME
+ _ZN22QMetaDataWriterControl15metaDataChangedEv @ 753 NONAME
+ _ZN22QMetaDataWriterControl15writableChangedEb @ 754 NONAME
+ _ZN22QMetaDataWriterControl16staticMetaObjectE @ 755 NONAME DATA 16
+ _ZN22QMetaDataWriterControl19getStaticMetaObjectEv @ 756 NONAME
+ _ZN22QMetaDataWriterControl24metaDataAvailableChangedEb @ 757 NONAME
+ _ZN22QMetaDataWriterControlC2EP7QObject @ 758 NONAME
+ _ZN22QMetaDataWriterControlD0Ev @ 759 NONAME
+ _ZN22QMetaDataWriterControlD1Ev @ 760 NONAME
+ _ZN22QMetaDataWriterControlD2Ev @ 761 NONAME
+ _ZN23QMediaBindableInterfaceD0Ev @ 762 NONAME
+ _ZN23QMediaBindableInterfaceD1Ev @ 763 NONAME
+ _ZN23QMediaBindableInterfaceD2Ev @ 764 NONAME
+ _ZN23QMediaPlaylistNavigator11qt_metacallEN11QMetaObject4CallEiPPv @ 765 NONAME
+ _ZN23QMediaPlaylistNavigator11qt_metacastEPKc @ 766 NONAME
+ _ZN23QMediaPlaylistNavigator11setPlaylistEP22QMediaPlaylistProvider @ 767 NONAME
+ _ZN23QMediaPlaylistNavigator15setPlaybackModeEN14QMediaPlaylist12PlaybackModeE @ 768 NONAME
+ _ZN23QMediaPlaylistNavigator16staticMetaObjectE @ 769 NONAME DATA 16
+ _ZN23QMediaPlaylistNavigator19currentIndexChangedEi @ 770 NONAME
+ _ZN23QMediaPlaylistNavigator19getStaticMetaObjectEv @ 771 NONAME
+ _ZN23QMediaPlaylistNavigator19playbackModeChangedEN14QMediaPlaylist12PlaybackModeE @ 772 NONAME
+ _ZN23QMediaPlaylistNavigator23surroundingItemsChangedEv @ 773 NONAME
+ _ZN23QMediaPlaylistNavigator4jumpEi @ 774 NONAME
+ _ZN23QMediaPlaylistNavigator4nextEv @ 775 NONAME
+ _ZN23QMediaPlaylistNavigator8previousEv @ 776 NONAME
+ _ZN23QMediaPlaylistNavigator9activatedERK13QMediaContent @ 777 NONAME
+ _ZN23QMediaPlaylistNavigatorC1EP22QMediaPlaylistProviderP7QObject @ 778 NONAME
+ _ZN23QMediaPlaylistNavigatorC2EP22QMediaPlaylistProviderP7QObject @ 779 NONAME
+ _ZN23QMediaPlaylistNavigatorD0Ev @ 780 NONAME
+ _ZN23QMediaPlaylistNavigatorD1Ev @ 781 NONAME
+ _ZN23QMediaPlaylistNavigatorD2Ev @ 782 NONAME
+ _ZN24QAbstractAudioDeviceInfo11qt_metacallEN11QMetaObject4CallEiPPv @ 783 NONAME
+ _ZN24QAbstractAudioDeviceInfo11qt_metacastEPKc @ 784 NONAME
+ _ZN24QAbstractAudioDeviceInfo16staticMetaObjectE @ 785 NONAME DATA 16
+ _ZN24QAbstractAudioDeviceInfo19getStaticMetaObjectEv @ 786 NONAME
+ _ZN25QMediaServiceProviderHintC1E6QFlagsINS_7FeatureEE @ 787 NONAME
+ _ZN25QMediaServiceProviderHintC1ERK10QByteArray @ 788 NONAME
+ _ZN25QMediaServiceProviderHintC1ERK7QStringRK11QStringList @ 789 NONAME
+ _ZN25QMediaServiceProviderHintC1ERKS_ @ 790 NONAME
+ _ZN25QMediaServiceProviderHintC1Ev @ 791 NONAME
+ _ZN25QMediaServiceProviderHintC2E6QFlagsINS_7FeatureEE @ 792 NONAME
+ _ZN25QMediaServiceProviderHintC2ERK10QByteArray @ 793 NONAME
+ _ZN25QMediaServiceProviderHintC2ERK7QStringRK11QStringList @ 794 NONAME
+ _ZN25QMediaServiceProviderHintC2ERKS_ @ 795 NONAME
+ _ZN25QMediaServiceProviderHintC2Ev @ 796 NONAME
+ _ZN25QMediaServiceProviderHintD1Ev @ 797 NONAME
+ _ZN25QMediaServiceProviderHintD2Ev @ 798 NONAME
+ _ZN25QMediaServiceProviderHintaSERKS_ @ 799 NONAME
+ _ZN27QLocalMediaPlaylistProvider11insertMediaEiRK13QMediaContent @ 800 NONAME
+ _ZN27QLocalMediaPlaylistProvider11insertMediaEiRK5QListI13QMediaContentE @ 801 NONAME
+ _ZN27QLocalMediaPlaylistProvider11qt_metacallEN11QMetaObject4CallEiPPv @ 802 NONAME
+ _ZN27QLocalMediaPlaylistProvider11qt_metacastEPKc @ 803 NONAME
+ _ZN27QLocalMediaPlaylistProvider11removeMediaEi @ 804 NONAME
+ _ZN27QLocalMediaPlaylistProvider11removeMediaEii @ 805 NONAME
+ _ZN27QLocalMediaPlaylistProvider16staticMetaObjectE @ 806 NONAME DATA 16
+ _ZN27QLocalMediaPlaylistProvider19getStaticMetaObjectEv @ 807 NONAME
+ _ZN27QLocalMediaPlaylistProvider5clearEv @ 808 NONAME
+ _ZN27QLocalMediaPlaylistProvider7shuffleEv @ 809 NONAME
+ _ZN27QLocalMediaPlaylistProvider8addMediaERK13QMediaContent @ 810 NONAME
+ _ZN27QLocalMediaPlaylistProvider8addMediaERK5QListI13QMediaContentE @ 811 NONAME
+ _ZN27QLocalMediaPlaylistProviderC1EP7QObject @ 812 NONAME
+ _ZN27QLocalMediaPlaylistProviderC2EP7QObject @ 813 NONAME
+ _ZN27QLocalMediaPlaylistProviderD0Ev @ 814 NONAME
+ _ZN27QLocalMediaPlaylistProviderD1Ev @ 815 NONAME
+ _ZN27QLocalMediaPlaylistProviderD2Ev @ 816 NONAME
+ _ZN27QMediaPlaylistSourceControl11qt_metacallEN11QMetaObject4CallEiPPv @ 817 NONAME
+ _ZN27QMediaPlaylistSourceControl11qt_metacastEPKc @ 818 NONAME
+ _ZN27QMediaPlaylistSourceControl15playlistChangedEP14QMediaPlaylist @ 819 NONAME
+ _ZN27QMediaPlaylistSourceControl16staticMetaObjectE @ 820 NONAME DATA 16
+ _ZN27QMediaPlaylistSourceControl19getStaticMetaObjectEv @ 821 NONAME
+ _ZN27QMediaPlaylistSourceControlC2EP7QObject @ 822 NONAME
+ _ZN27QMediaPlaylistSourceControlD0Ev @ 823 NONAME
+ _ZN27QMediaPlaylistSourceControlD1Ev @ 824 NONAME
+ _ZN27QMediaPlaylistSourceControlD2Ev @ 825 NONAME
+ _ZN27QMediaServiceProviderPlugin11qt_metacallEN11QMetaObject4CallEiPPv @ 826 NONAME
+ _ZN27QMediaServiceProviderPlugin11qt_metacastEPKc @ 827 NONAME
+ _ZN27QMediaServiceProviderPlugin16staticMetaObjectE @ 828 NONAME DATA 16
+ _ZN27QMediaServiceProviderPlugin19getStaticMetaObjectEv @ 829 NONAME
+ _ZNK11QAudioInput10bufferSizeEv @ 830 NONAME
+ _ZNK11QAudioInput10bytesReadyEv @ 831 NONAME
+ _ZNK11QAudioInput10metaObjectEv @ 832 NONAME
+ _ZNK11QAudioInput10periodSizeEv @ 833 NONAME
+ _ZNK11QAudioInput12elapsedUSecsEv @ 834 NONAME
+ _ZNK11QAudioInput14notifyIntervalEv @ 835 NONAME
+ _ZNK11QAudioInput14processedUSecsEv @ 836 NONAME
+ _ZNK11QAudioInput5errorEv @ 837 NONAME
+ _ZNK11QAudioInput5stateEv @ 838 NONAME
+ _ZNK11QAudioInput6formatEv @ 839 NONAME
+ _ZNK11QRadioTuner10metaObjectEv @ 840 NONAME
+ _ZNK11QRadioTuner10stereoModeEv @ 841 NONAME
+ _ZNK11QRadioTuner11errorStringEv @ 842 NONAME
+ _ZNK11QRadioTuner11isAvailableEv @ 843 NONAME
+ _ZNK11QRadioTuner11isSearchingEv @ 844 NONAME
+ _ZNK11QRadioTuner13frequencyStepENS_4BandE @ 845 NONAME
+ _ZNK11QRadioTuner14frequencyRangeENS_4BandE @ 846 NONAME
+ _ZNK11QRadioTuner14signalStrengthEv @ 847 NONAME
+ _ZNK11QRadioTuner15isBandSupportedENS_4BandE @ 848 NONAME
+ _ZNK11QRadioTuner17availabilityErrorEv @ 849 NONAME
+ _ZNK11QRadioTuner4bandEv @ 850 NONAME
+ _ZNK11QRadioTuner5errorEv @ 851 NONAME
+ _ZNK11QRadioTuner5stateEv @ 852 NONAME
+ _ZNK11QRadioTuner6volumeEv @ 853 NONAME
+ _ZNK11QRadioTuner7isMutedEv @ 854 NONAME
+ _ZNK11QRadioTuner8isStereoEv @ 855 NONAME
+ _ZNK11QRadioTuner9frequencyEv @ 856 NONAME
+ _ZNK11QVideoFrame10handleTypeEv @ 857 NONAME
+ _ZNK11QVideoFrame10isReadableEv @ 858 NONAME
+ _ZNK11QVideoFrame10isWritableEv @ 859 NONAME
+ _ZNK11QVideoFrame11mappedBytesEv @ 860 NONAME
+ _ZNK11QVideoFrame11pixelFormatEv @ 861 NONAME
+ _ZNK11QVideoFrame12bytesPerLineEv @ 862 NONAME
+ _ZNK11QVideoFrame4bitsEv @ 863 NONAME
+ _ZNK11QVideoFrame4sizeEv @ 864 NONAME
+ _ZNK11QVideoFrame5widthEv @ 865 NONAME
+ _ZNK11QVideoFrame6handleEv @ 866 NONAME
+ _ZNK11QVideoFrame6heightEv @ 867 NONAME
+ _ZNK11QVideoFrame7endTimeEv @ 868 NONAME
+ _ZNK11QVideoFrame7isValidEv @ 869 NONAME
+ _ZNK11QVideoFrame7mapModeEv @ 870 NONAME
+ _ZNK11QVideoFrame8isMappedEv @ 871 NONAME
+ _ZNK11QVideoFrame9fieldTypeEv @ 872 NONAME
+ _ZNK11QVideoFrame9startTimeEv @ 873 NONAME
+ _ZNK12QAudioFormat10sampleRateEv @ 874 NONAME
+ _ZNK12QAudioFormat10sampleSizeEv @ 875 NONAME
+ _ZNK12QAudioFormat10sampleTypeEv @ 876 NONAME
+ _ZNK12QAudioFormat12channelCountEv @ 877 NONAME
+ _ZNK12QAudioFormat5codecEv @ 878 NONAME
+ _ZNK12QAudioFormat7isValidEv @ 879 NONAME
+ _ZNK12QAudioFormat8channelsEv @ 880 NONAME
+ _ZNK12QAudioFormat9byteOrderEv @ 881 NONAME
+ _ZNK12QAudioFormat9frequencyEv @ 882 NONAME
+ _ZNK12QAudioFormateqERKS_ @ 883 NONAME
+ _ZNK12QAudioFormatneERKS_ @ 884 NONAME
+ _ZNK12QAudioOutput10bufferSizeEv @ 885 NONAME
+ _ZNK12QAudioOutput10metaObjectEv @ 886 NONAME
+ _ZNK12QAudioOutput10periodSizeEv @ 887 NONAME
+ _ZNK12QAudioOutput12elapsedUSecsEv @ 888 NONAME
+ _ZNK12QAudioOutput14notifyIntervalEv @ 889 NONAME
+ _ZNK12QAudioOutput14processedUSecsEv @ 890 NONAME
+ _ZNK12QAudioOutput5errorEv @ 891 NONAME
+ _ZNK12QAudioOutput5stateEv @ 892 NONAME
+ _ZNK12QAudioOutput6formatEv @ 893 NONAME
+ _ZNK12QAudioOutput9bytesFreeEv @ 894 NONAME
+ _ZNK12QMediaObject10metaObjectEv @ 895 NONAME
+ _ZNK12QMediaObject11isAvailableEv @ 896 NONAME
+ _ZNK12QMediaObject14notifyIntervalEv @ 897 NONAME
+ _ZNK12QMediaObject16extendedMetaDataERK7QString @ 898 NONAME
+ _ZNK12QMediaObject17availabilityErrorEv @ 899 NONAME
+ _ZNK12QMediaObject17availableMetaDataEv @ 900 NONAME
+ _ZNK12QMediaObject19isMetaDataAvailableEv @ 901 NONAME
+ _ZNK12QMediaObject25availableExtendedMetaDataEv @ 902 NONAME
+ _ZNK12QMediaObject7serviceEv @ 903 NONAME
+ _ZNK12QMediaObject8metaDataEN15QtMultimediaKit8MetaDataE @ 904 NONAME
+ _ZNK12QMediaPlayer10isSeekableEv @ 905 NONAME
+ _ZNK12QMediaPlayer10metaObjectEv @ 906 NONAME
+ _ZNK12QMediaPlayer11errorStringEv @ 907 NONAME
+ _ZNK12QMediaPlayer11mediaStatusEv @ 908 NONAME
+ _ZNK12QMediaPlayer11mediaStreamEv @ 909 NONAME
+ _ZNK12QMediaPlayer12bufferStatusEv @ 910 NONAME
+ _ZNK12QMediaPlayer12playbackRateEv @ 911 NONAME
+ _ZNK12QMediaPlayer16isAudioAvailableEv @ 912 NONAME
+ _ZNK12QMediaPlayer16isVideoAvailableEv @ 913 NONAME
+ _ZNK12QMediaPlayer5errorEv @ 914 NONAME
+ _ZNK12QMediaPlayer5mediaEv @ 915 NONAME
+ _ZNK12QMediaPlayer5stateEv @ 916 NONAME
+ _ZNK12QMediaPlayer6volumeEv @ 917 NONAME
+ _ZNK12QMediaPlayer7isMutedEv @ 918 NONAME
+ _ZNK12QMediaPlayer8durationEv @ 919 NONAME
+ _ZNK12QMediaPlayer8playlistEv @ 920 NONAME
+ _ZNK12QMediaPlayer8positionEv @ 921 NONAME
+ _ZNK12QSoundEffect10metaObjectEv @ 922 NONAME
+ _ZNK12QSoundEffect5loopsEv @ 923 NONAME ABSENT
+ _ZNK12QSoundEffect6sourceEv @ 924 NONAME
+ _ZNK12QSoundEffect6volumeEv @ 925 NONAME
+ _ZNK12QSoundEffect7isMutedEv @ 926 NONAME
+ _ZNK12QVideoWidget10brightnessEv @ 927 NONAME
+ _ZNK12QVideoWidget10metaObjectEv @ 928 NONAME
+ _ZNK12QVideoWidget10saturationEv @ 929 NONAME
+ _ZNK12QVideoWidget11mediaObjectEv @ 930 NONAME
+ _ZNK12QVideoWidget15aspectRatioModeEv @ 931 NONAME
+ _ZNK12QVideoWidget3hueEv @ 932 NONAME
+ _ZNK12QVideoWidget8contrastEv @ 933 NONAME
+ _ZNK12QVideoWidget8sizeHintEv @ 934 NONAME
+ _ZNK13QMediaContent12canonicalUrlEv @ 935 NONAME
+ _ZNK13QMediaContent16canonicalRequestEv @ 936 NONAME
+ _ZNK13QMediaContent17canonicalResourceEv @ 937 NONAME
+ _ZNK13QMediaContent6isNullEv @ 938 NONAME
+ _ZNK13QMediaContent9resourcesEv @ 939 NONAME
+ _ZNK13QMediaContenteqERKS_ @ 940 NONAME
+ _ZNK13QMediaContentneERKS_ @ 941 NONAME
+ _ZNK13QMediaControl10metaObjectEv @ 942 NONAME
+ _ZNK13QMediaService10metaObjectEv @ 943 NONAME
+ _ZNK14QMediaPlaylist10isReadOnlyEv @ 944 NONAME
+ _ZNK14QMediaPlaylist10mediaCountEv @ 945 NONAME
+ _ZNK14QMediaPlaylist10metaObjectEv @ 946 NONAME
+ _ZNK14QMediaPlaylist11errorStringEv @ 947 NONAME
+ _ZNK14QMediaPlaylist11mediaObjectEv @ 948 NONAME
+ _ZNK14QMediaPlaylist12currentIndexEv @ 949 NONAME
+ _ZNK14QMediaPlaylist12currentMediaEv @ 950 NONAME
+ _ZNK14QMediaPlaylist12playbackModeEv @ 951 NONAME
+ _ZNK14QMediaPlaylist13previousIndexEi @ 952 NONAME
+ _ZNK14QMediaPlaylist5errorEv @ 953 NONAME
+ _ZNK14QMediaPlaylist5mediaEi @ 954 NONAME
+ _ZNK14QMediaPlaylist7isEmptyEv @ 955 NONAME
+ _ZNK14QMediaPlaylist9nextIndexEi @ 956 NONAME
+ _ZNK14QMediaRecorder10metaObjectEv @ 957 NONAME
+ _ZNK14QMediaRecorder11errorStringEv @ 958 NONAME
+ _ZNK14QMediaRecorder11isAvailableEv @ 959 NONAME
+ _ZNK14QMediaRecorder11mediaObjectEv @ 960 NONAME
+ _ZNK14QMediaRecorder13audioSettingsEv @ 961 NONAME
+ _ZNK14QMediaRecorder13videoSettingsEv @ 962 NONAME
+ _ZNK14QMediaRecorder14outputLocationEv @ 963 NONAME
+ _ZNK14QMediaRecorder16extendedMetaDataERK7QString @ 964 NONAME
+ _ZNK14QMediaRecorder17availabilityErrorEv @ 965 NONAME
+ _ZNK14QMediaRecorder17availableMetaDataEv @ 966 NONAME
+ _ZNK14QMediaRecorder17containerMimeTypeEv @ 967 NONAME
+ _ZNK14QMediaRecorder18isMetaDataWritableEv @ 968 NONAME
+ _ZNK14QMediaRecorder19isMetaDataAvailableEv @ 969 NONAME
+ _ZNK14QMediaRecorder19supportedContainersEv @ 970 NONAME
+ _ZNK14QMediaRecorder19supportedFrameRatesERK21QVideoEncoderSettingsPb @ 971 NONAME
+ _ZNK14QMediaRecorder20containerDescriptionERK7QString @ 972 NONAME
+ _ZNK14QMediaRecorder20supportedAudioCodecsEv @ 973 NONAME
+ _ZNK14QMediaRecorder20supportedResolutionsERK21QVideoEncoderSettingsPb @ 974 NONAME
+ _ZNK14QMediaRecorder20supportedVideoCodecsEv @ 975 NONAME
+ _ZNK14QMediaRecorder21audioCodecDescriptionERK7QString @ 976 NONAME
+ _ZNK14QMediaRecorder21videoCodecDescriptionERK7QString @ 977 NONAME
+ _ZNK14QMediaRecorder25availableExtendedMetaDataEv @ 978 NONAME
+ _ZNK14QMediaRecorder25supportedAudioSampleRatesERK21QAudioEncoderSettingsPb @ 979 NONAME
+ _ZNK14QMediaRecorder5errorEv @ 980 NONAME
+ _ZNK14QMediaRecorder5stateEv @ 981 NONAME
+ _ZNK14QMediaRecorder7isMutedEv @ 982 NONAME
+ _ZNK14QMediaRecorder8durationEv @ 983 NONAME
+ _ZNK14QMediaRecorder8metaDataEN15QtMultimediaKit8MetaDataE @ 984 NONAME
+ _ZNK14QMediaResource10audioCodecEv @ 985 NONAME
+ _ZNK14QMediaResource10resolutionEv @ 986 NONAME
+ _ZNK14QMediaResource10sampleRateEv @ 987 NONAME
+ _ZNK14QMediaResource10videoCodecEv @ 988 NONAME
+ _ZNK14QMediaResource12audioBitRateEv @ 989 NONAME
+ _ZNK14QMediaResource12channelCountEv @ 990 NONAME
+ _ZNK14QMediaResource12videoBitRateEv @ 991 NONAME
+ _ZNK14QMediaResource3urlEv @ 992 NONAME
+ _ZNK14QMediaResource6isNullEv @ 993 NONAME
+ _ZNK14QMediaResource7requestEv @ 994 NONAME
+ _ZNK14QMediaResource8dataSizeEv @ 995 NONAME
+ _ZNK14QMediaResource8languageEv @ 996 NONAME
+ _ZNK14QMediaResource8mimeTypeEv @ 997 NONAME
+ _ZNK14QMediaResourceeqERKS_ @ 998 NONAME
+ _ZNK14QMediaResourceneERKS_ @ 999 NONAME
+ _ZNK15QMediaTimeRange10latestTimeEv @ 1000 NONAME
+ _ZNK15QMediaTimeRange12earliestTimeEv @ 1001 NONAME
+ _ZNK15QMediaTimeRange12isContinuousEv @ 1002 NONAME
+ _ZNK15QMediaTimeRange7isEmptyEv @ 1003 NONAME
+ _ZNK15QMediaTimeRange8containsEx @ 1004 NONAME
+ _ZNK15QMediaTimeRange9intervalsEv @ 1005 NONAME
+ _ZNK16QAudioDeviceInfo10deviceNameEv @ 1006 NONAME
+ _ZNK16QAudioDeviceInfo13nearestFormatERK12QAudioFormat @ 1007 NONAME
+ _ZNK16QAudioDeviceInfo15preferredFormatEv @ 1008 NONAME
+ _ZNK16QAudioDeviceInfo15supportedCodecsEv @ 1009 NONAME
+ _ZNK16QAudioDeviceInfo17isFormatSupportedERK12QAudioFormat @ 1010 NONAME
+ _ZNK16QAudioDeviceInfo17supportedChannelsEv @ 1011 NONAME
+ _ZNK16QAudioDeviceInfo19supportedByteOrdersEv @ 1012 NONAME
+ _ZNK16QAudioDeviceInfo20supportedFrequenciesEv @ 1013 NONAME
+ _ZNK16QAudioDeviceInfo20supportedSampleRatesEv @ 1014 NONAME
+ _ZNK16QAudioDeviceInfo20supportedSampleSizesEv @ 1015 NONAME
+ _ZNK16QAudioDeviceInfo20supportedSampleTypesEv @ 1016 NONAME
+ _ZNK16QAudioDeviceInfo22supportedChannelCountsEv @ 1017 NONAME
+ _ZNK16QAudioDeviceInfo4modeEv @ 1018 NONAME
+ _ZNK16QAudioDeviceInfo5realmEv @ 1019 NONAME
+ _ZNK16QAudioDeviceInfo6handleEv @ 1020 NONAME
+ _ZNK16QAudioDeviceInfo6isNullEv @ 1021 NONAME
+ _ZNK17QImageVideoBuffer7mapModeEv @ 1022 NONAME
+ _ZNK17QMediaImageViewer10metaObjectEv @ 1023 NONAME
+ _ZNK17QMediaImageViewer11elapsedTimeEv @ 1024 NONAME
+ _ZNK17QMediaImageViewer11mediaStatusEv @ 1025 NONAME
+ _ZNK17QMediaImageViewer5mediaEv @ 1026 NONAME
+ _ZNK17QMediaImageViewer5stateEv @ 1027 NONAME
+ _ZNK17QMediaImageViewer7timeoutEv @ 1028 NONAME
+ _ZNK18QAudioSystemPlugin10metaObjectEv @ 1029 NONAME
+ _ZNK18QGraphicsVideoItem10metaObjectEv @ 1030 NONAME
+ _ZNK18QGraphicsVideoItem10nativeSizeEv @ 1031 NONAME
+ _ZNK18QGraphicsVideoItem11mediaObjectEv @ 1032 NONAME
+ _ZNK18QGraphicsVideoItem12boundingRectEv @ 1033 NONAME
+ _ZNK18QGraphicsVideoItem15aspectRatioModeEv @ 1034 NONAME
+ _ZNK18QGraphicsVideoItem4sizeEv @ 1035 NONAME
+ _ZNK18QGraphicsVideoItem6offsetEv @ 1036 NONAME
+ _ZNK18QMediaTimeInterval10normalizedEv @ 1037 NONAME
+ _ZNK18QMediaTimeInterval10translatedEx @ 1038 NONAME
+ _ZNK18QMediaTimeInterval3endEv @ 1039 NONAME
+ _ZNK18QMediaTimeInterval5startEv @ 1040 NONAME
+ _ZNK18QMediaTimeInterval8containsEx @ 1041 NONAME
+ _ZNK18QMediaTimeInterval8isNormalEv @ 1042 NONAME
+ _ZNK18QMemoryVideoBuffer7mapModeEv @ 1043 NONAME
+ _ZNK18QRadioTunerControl10metaObjectEv @ 1044 NONAME
+ _ZNK19QAbstractAudioInput10metaObjectEv @ 1045 NONAME
+ _ZNK19QAudioCaptureSource10metaObjectEv @ 1046 NONAME
+ _ZNK19QAudioCaptureSource11audioInputsEv @ 1047 NONAME
+ _ZNK19QAudioCaptureSource11isAvailableEv @ 1048 NONAME
+ _ZNK19QAudioCaptureSource16activeAudioInputEv @ 1049 NONAME
+ _ZNK19QAudioCaptureSource16audioDescriptionERK7QString @ 1050 NONAME
+ _ZNK19QAudioCaptureSource17availabilityErrorEv @ 1051 NONAME
+ _ZNK19QAudioCaptureSource17defaultAudioInputEv @ 1052 NONAME
+ _ZNK19QMediaPlayerControl10metaObjectEv @ 1053 NONAME
+ _ZNK19QVideoDeviceControl10metaObjectEv @ 1054 NONAME
+ _ZNK19QVideoSurfaceFormat10frameWidthEv @ 1055 NONAME
+ _ZNK19QVideoSurfaceFormat10handleTypeEv @ 1056 NONAME
+ _ZNK19QVideoSurfaceFormat11frameHeightEv @ 1057 NONAME
+ _ZNK19QVideoSurfaceFormat11pixelFormatEv @ 1058 NONAME
+ _ZNK19QVideoSurfaceFormat13propertyNamesEv @ 1059 NONAME
+ _ZNK19QVideoSurfaceFormat15yCbCrColorSpaceEv @ 1060 NONAME
+ _ZNK19QVideoSurfaceFormat16pixelAspectRatioEv @ 1061 NONAME
+ _ZNK19QVideoSurfaceFormat17scanLineDirectionEv @ 1062 NONAME
+ _ZNK19QVideoSurfaceFormat7isValidEv @ 1063 NONAME
+ _ZNK19QVideoSurfaceFormat8propertyEPKc @ 1064 NONAME
+ _ZNK19QVideoSurfaceFormat8sizeHintEv @ 1065 NONAME
+ _ZNK19QVideoSurfaceFormat8viewportEv @ 1066 NONAME
+ _ZNK19QVideoSurfaceFormat9frameRateEv @ 1067 NONAME
+ _ZNK19QVideoSurfaceFormat9frameSizeEv @ 1068 NONAME
+ _ZNK19QVideoSurfaceFormateqERKS_ @ 1069 NONAME
+ _ZNK19QVideoSurfaceFormatneERKS_ @ 1070 NONAME
+ _ZNK19QVideoWidgetControl10metaObjectEv @ 1071 NONAME
+ _ZNK19QVideoWindowControl10metaObjectEv @ 1072 NONAME
+ _ZNK20QAbstractAudioOutput10metaObjectEv @ 1073 NONAME
+ _ZNK20QAbstractVideoBuffer10handleTypeEv @ 1074 NONAME
+ _ZNK20QAbstractVideoBuffer6handleEv @ 1075 NONAME
+ _ZNK20QAudioEncoderControl10metaObjectEv @ 1076 NONAME
+ _ZNK20QImageEncoderControl10metaObjectEv @ 1077 NONAME
+ _ZNK20QMediaStreamsControl10metaObjectEv @ 1078 NONAME
+ _ZNK20QVideoEncoderControl10metaObjectEv @ 1079 NONAME
+ _ZNK21QAbstractVideoSurface10metaObjectEv @ 1080 NONAME
+ _ZNK21QAbstractVideoSurface13nearestFormatERK19QVideoSurfaceFormat @ 1081 NONAME
+ _ZNK21QAbstractVideoSurface13surfaceFormatEv @ 1082 NONAME
+ _ZNK21QAbstractVideoSurface17isFormatSupportedERK19QVideoSurfaceFormat @ 1083 NONAME
+ _ZNK21QAbstractVideoSurface5errorEv @ 1084 NONAME
+ _ZNK21QAbstractVideoSurface8isActiveEv @ 1085 NONAME
+ _ZNK21QAudioEncoderSettings10sampleRateEv @ 1086 NONAME
+ _ZNK21QAudioEncoderSettings12channelCountEv @ 1087 NONAME
+ _ZNK21QAudioEncoderSettings12encodingModeEv @ 1088 NONAME
+ _ZNK21QAudioEncoderSettings5codecEv @ 1089 NONAME
+ _ZNK21QAudioEncoderSettings6isNullEv @ 1090 NONAME
+ _ZNK21QAudioEncoderSettings7bitRateEv @ 1091 NONAME
+ _ZNK21QAudioEncoderSettings7qualityEv @ 1092 NONAME
+ _ZNK21QAudioEncoderSettingseqERKS_ @ 1093 NONAME
+ _ZNK21QAudioEncoderSettingsneERKS_ @ 1094 NONAME
+ _ZNK21QImageEncoderSettings10resolutionEv @ 1095 NONAME
+ _ZNK21QImageEncoderSettings5codecEv @ 1096 NONAME
+ _ZNK21QImageEncoderSettings6isNullEv @ 1097 NONAME
+ _ZNK21QImageEncoderSettings7qualityEv @ 1098 NONAME
+ _ZNK21QImageEncoderSettingseqERKS_ @ 1099 NONAME
+ _ZNK21QImageEncoderSettingsneERKS_ @ 1100 NONAME
+ _ZNK21QMediaPlaylistControl10metaObjectEv @ 1101 NONAME
+ _ZNK21QMediaRecorderControl10metaObjectEv @ 1102 NONAME
+ _ZNK21QMediaServiceProvider10hasSupportERK10QByteArrayRK7QStringRK11QStringListi @ 1103 NONAME
+ _ZNK21QMediaServiceProvider10metaObjectEv @ 1104 NONAME
+ _ZNK21QMediaServiceProvider18supportedMimeTypesERK10QByteArrayi @ 1105 NONAME
+ _ZNK21QMediaServiceProvider7devicesERK10QByteArray @ 1106 NONAME
+ _ZNK21QVideoEncoderSettings10resolutionEv @ 1107 NONAME
+ _ZNK21QVideoEncoderSettings12encodingModeEv @ 1108 NONAME
+ _ZNK21QVideoEncoderSettings5codecEv @ 1109 NONAME
+ _ZNK21QVideoEncoderSettings6isNullEv @ 1110 NONAME
+ _ZNK21QVideoEncoderSettings7bitRateEv @ 1111 NONAME
+ _ZNK21QVideoEncoderSettings7qualityEv @ 1112 NONAME
+ _ZNK21QVideoEncoderSettings9frameRateEv @ 1113 NONAME
+ _ZNK21QVideoEncoderSettingseqERKS_ @ 1114 NONAME
+ _ZNK21QVideoEncoderSettingsneERKS_ @ 1115 NONAME
+ _ZNK21QVideoRendererControl10metaObjectEv @ 1116 NONAME
+ _ZNK22QAudioEndpointSelector10metaObjectEv @ 1117 NONAME
+ _ZNK22QMediaContainerControl10metaObjectEv @ 1118 NONAME
+ _ZNK22QMediaPlaylistIOPlugin10metaObjectEv @ 1119 NONAME
+ _ZNK22QMediaPlaylistProvider10isReadOnlyEv @ 1120 NONAME
+ _ZNK22QMediaPlaylistProvider10metaObjectEv @ 1121 NONAME
+ _ZNK22QMetaDataReaderControl10metaObjectEv @ 1122 NONAME
+ _ZNK22QMetaDataWriterControl10metaObjectEv @ 1123 NONAME
+ _ZNK23QMediaPlaylistNavigator10metaObjectEv @ 1124 NONAME
+ _ZNK23QMediaPlaylistNavigator11currentItemEv @ 1125 NONAME
+ _ZNK23QMediaPlaylistNavigator12currentIndexEv @ 1126 NONAME
+ _ZNK23QMediaPlaylistNavigator12playbackModeEv @ 1127 NONAME
+ _ZNK23QMediaPlaylistNavigator12previousItemEi @ 1128 NONAME
+ _ZNK23QMediaPlaylistNavigator13previousIndexEi @ 1129 NONAME
+ _ZNK23QMediaPlaylistNavigator6itemAtEi @ 1130 NONAME
+ _ZNK23QMediaPlaylistNavigator8nextItemEi @ 1131 NONAME
+ _ZNK23QMediaPlaylistNavigator8playlistEv @ 1132 NONAME
+ _ZNK23QMediaPlaylistNavigator9nextIndexEi @ 1133 NONAME
+ _ZNK24QAbstractAudioDeviceInfo10metaObjectEv @ 1134 NONAME
+ _ZNK25QMediaServiceProviderHint4typeEv @ 1135 NONAME
+ _ZNK25QMediaServiceProviderHint6codecsEv @ 1136 NONAME
+ _ZNK25QMediaServiceProviderHint6deviceEv @ 1137 NONAME
+ _ZNK25QMediaServiceProviderHint6isNullEv @ 1138 NONAME
+ _ZNK25QMediaServiceProviderHint8featuresEv @ 1139 NONAME
+ _ZNK25QMediaServiceProviderHint8mimeTypeEv @ 1140 NONAME
+ _ZNK25QMediaServiceProviderHinteqERKS_ @ 1141 NONAME
+ _ZNK25QMediaServiceProviderHintneERKS_ @ 1142 NONAME
+ _ZNK27QLocalMediaPlaylistProvider10isReadOnlyEv @ 1143 NONAME
+ _ZNK27QLocalMediaPlaylistProvider10mediaCountEv @ 1144 NONAME
+ _ZNK27QLocalMediaPlaylistProvider10metaObjectEv @ 1145 NONAME
+ _ZNK27QLocalMediaPlaylistProvider5mediaEi @ 1146 NONAME
+ _ZNK27QMediaPlaylistSourceControl10metaObjectEv @ 1147 NONAME
+ _ZNK27QMediaServiceProviderPlugin10metaObjectEv @ 1148 NONAME
+ _ZTI11QAudioInput @ 1149 NONAME
+ _ZTI11QRadioTuner @ 1150 NONAME
+ _ZTI12QAudioOutput @ 1151 NONAME
+ _ZTI12QMediaObject @ 1152 NONAME
+ _ZTI12QMediaPlayer @ 1153 NONAME
+ _ZTI12QSoundEffect @ 1154 NONAME
+ _ZTI12QVideoWidget @ 1155 NONAME
+ _ZTI13QMediaControl @ 1156 NONAME
+ _ZTI13QMediaService @ 1157 NONAME
+ _ZTI14QMediaPlaylist @ 1158 NONAME
+ _ZTI14QMediaRecorder @ 1159 NONAME
+ _ZTI17QImageVideoBuffer @ 1160 NONAME
+ _ZTI17QMediaImageViewer @ 1161 NONAME
+ _ZTI18QAudioSystemPlugin @ 1162 NONAME
+ _ZTI18QGraphicsVideoItem @ 1163 NONAME
+ _ZTI18QMemoryVideoBuffer @ 1164 NONAME
+ _ZTI18QRadioTunerControl @ 1165 NONAME
+ _ZTI19QAbstractAudioInput @ 1166 NONAME
+ _ZTI19QAudioCaptureSource @ 1167 NONAME
+ _ZTI19QMediaPlayerControl @ 1168 NONAME
+ _ZTI19QVideoDeviceControl @ 1169 NONAME
+ _ZTI19QVideoWidgetControl @ 1170 NONAME
+ _ZTI19QVideoWindowControl @ 1171 NONAME
+ _ZTI20QAbstractAudioOutput @ 1172 NONAME
+ _ZTI20QAbstractVideoBuffer @ 1173 NONAME
+ _ZTI20QAudioEncoderControl @ 1174 NONAME
+ _ZTI20QImageEncoderControl @ 1175 NONAME
+ _ZTI20QMediaPlaylistReader @ 1176 NONAME
+ _ZTI20QMediaPlaylistWriter @ 1177 NONAME
+ _ZTI20QMediaStreamsControl @ 1178 NONAME
+ _ZTI20QVideoEncoderControl @ 1179 NONAME
+ _ZTI21QAbstractVideoSurface @ 1180 NONAME
+ _ZTI21QMediaPlaylistControl @ 1181 NONAME
+ _ZTI21QMediaRecorderControl @ 1182 NONAME
+ _ZTI21QMediaServiceProvider @ 1183 NONAME
+ _ZTI21QVideoRendererControl @ 1184 NONAME
+ _ZTI22QAudioEndpointSelector @ 1185 NONAME
+ _ZTI22QMediaContainerControl @ 1186 NONAME
+ _ZTI22QMediaPlaylistIOPlugin @ 1187 NONAME
+ _ZTI22QMediaPlaylistProvider @ 1188 NONAME
+ _ZTI22QMetaDataReaderControl @ 1189 NONAME
+ _ZTI22QMetaDataWriterControl @ 1190 NONAME
+ _ZTI23QMediaBindableInterface @ 1191 NONAME
+ _ZTI23QMediaPlaylistNavigator @ 1192 NONAME
+ _ZTI24QAbstractAudioDeviceInfo @ 1193 NONAME
+ _ZTI25QMediaPlaylistIOInterface @ 1194 NONAME
+ _ZTI27QLocalMediaPlaylistProvider @ 1195 NONAME
+ _ZTI27QMediaPlaylistSourceControl @ 1196 NONAME
+ _ZTI27QMediaServiceProviderPlugin @ 1197 NONAME
+ _ZTI28QAudioSystemFactoryInterface @ 1198 NONAME
+ _ZTI37QMediaServiceProviderFactoryInterface @ 1199 NONAME
+ _ZTV11QAudioInput @ 1200 NONAME
+ _ZTV11QRadioTuner @ 1201 NONAME
+ _ZTV12QAudioOutput @ 1202 NONAME
+ _ZTV12QMediaObject @ 1203 NONAME
+ _ZTV12QMediaPlayer @ 1204 NONAME
+ _ZTV12QSoundEffect @ 1205 NONAME
+ _ZTV12QVideoWidget @ 1206 NONAME
+ _ZTV13QMediaControl @ 1207 NONAME
+ _ZTV13QMediaService @ 1208 NONAME
+ _ZTV14QMediaPlaylist @ 1209 NONAME
+ _ZTV14QMediaRecorder @ 1210 NONAME
+ _ZTV17QImageVideoBuffer @ 1211 NONAME
+ _ZTV17QMediaImageViewer @ 1212 NONAME
+ _ZTV18QAudioSystemPlugin @ 1213 NONAME
+ _ZTV18QGraphicsVideoItem @ 1214 NONAME
+ _ZTV18QMemoryVideoBuffer @ 1215 NONAME
+ _ZTV18QRadioTunerControl @ 1216 NONAME
+ _ZTV19QAbstractAudioInput @ 1217 NONAME
+ _ZTV19QAudioCaptureSource @ 1218 NONAME
+ _ZTV19QMediaPlayerControl @ 1219 NONAME
+ _ZTV19QVideoDeviceControl @ 1220 NONAME
+ _ZTV19QVideoWidgetControl @ 1221 NONAME
+ _ZTV19QVideoWindowControl @ 1222 NONAME
+ _ZTV20QAbstractAudioOutput @ 1223 NONAME
+ _ZTV20QAbstractVideoBuffer @ 1224 NONAME
+ _ZTV20QAudioEncoderControl @ 1225 NONAME
+ _ZTV20QImageEncoderControl @ 1226 NONAME
+ _ZTV20QMediaPlaylistReader @ 1227 NONAME
+ _ZTV20QMediaPlaylistWriter @ 1228 NONAME
+ _ZTV20QMediaStreamsControl @ 1229 NONAME
+ _ZTV20QVideoEncoderControl @ 1230 NONAME
+ _ZTV21QAbstractVideoSurface @ 1231 NONAME
+ _ZTV21QMediaPlaylistControl @ 1232 NONAME
+ _ZTV21QMediaRecorderControl @ 1233 NONAME
+ _ZTV21QMediaServiceProvider @ 1234 NONAME
+ _ZTV21QVideoRendererControl @ 1235 NONAME
+ _ZTV22QAudioEndpointSelector @ 1236 NONAME
+ _ZTV22QMediaContainerControl @ 1237 NONAME
+ _ZTV22QMediaPlaylistIOPlugin @ 1238 NONAME
+ _ZTV22QMediaPlaylistProvider @ 1239 NONAME
+ _ZTV22QMetaDataReaderControl @ 1240 NONAME
+ _ZTV22QMetaDataWriterControl @ 1241 NONAME
+ _ZTV23QMediaBindableInterface @ 1242 NONAME
+ _ZTV23QMediaPlaylistNavigator @ 1243 NONAME
+ _ZTV24QAbstractAudioDeviceInfo @ 1244 NONAME
+ _ZTV27QLocalMediaPlaylistProvider @ 1245 NONAME
+ _ZTV27QMediaPlaylistSourceControl @ 1246 NONAME
+ _ZTV27QMediaServiceProviderPlugin @ 1247 NONAME
+ _ZThn16_N18QGraphicsVideoItem14setMediaObjectEP12QMediaObject @ 1248 NONAME
+ _ZThn16_N18QGraphicsVideoItemD0Ev @ 1249 NONAME
+ _ZThn16_N18QGraphicsVideoItemD1Ev @ 1250 NONAME
+ _ZThn16_NK18QGraphicsVideoItem11mediaObjectEv @ 1251 NONAME
+ _ZThn20_N12QVideoWidget14setMediaObjectEP12QMediaObject @ 1252 NONAME
+ _ZThn20_N12QVideoWidgetD0Ev @ 1253 NONAME
+ _ZThn20_N12QVideoWidgetD1Ev @ 1254 NONAME
+ _ZThn20_NK12QVideoWidget11mediaObjectEv @ 1255 NONAME
+ _ZThn8_N12QVideoWidgetD0Ev @ 1256 NONAME
+ _ZThn8_N12QVideoWidgetD1Ev @ 1257 NONAME
+ _ZThn8_N14QMediaPlaylist14setMediaObjectEP12QMediaObject @ 1258 NONAME
+ _ZThn8_N14QMediaPlaylistD0Ev @ 1259 NONAME
+ _ZThn8_N14QMediaPlaylistD1Ev @ 1260 NONAME
+ _ZThn8_N14QMediaRecorder14setMediaObjectEP12QMediaObject @ 1261 NONAME
+ _ZThn8_N14QMediaRecorderD0Ev @ 1262 NONAME
+ _ZThn8_N14QMediaRecorderD1Ev @ 1263 NONAME
+ _ZThn8_N18QAudioSystemPluginD0Ev @ 1264 NONAME
+ _ZThn8_N18QAudioSystemPluginD1Ev @ 1265 NONAME
+ _ZThn8_N18QGraphicsVideoItem10itemChangeEN13QGraphicsItem18GraphicsItemChangeERK8QVariant @ 1266 NONAME
+ _ZThn8_N18QGraphicsVideoItem5paintEP8QPainterPK24QStyleOptionGraphicsItemP7QWidget @ 1267 NONAME
+ _ZThn8_N18QGraphicsVideoItemD0Ev @ 1268 NONAME
+ _ZThn8_N18QGraphicsVideoItemD1Ev @ 1269 NONAME
+ _ZThn8_N22QMediaPlaylistIOPluginD0Ev @ 1270 NONAME
+ _ZThn8_N22QMediaPlaylistIOPluginD1Ev @ 1271 NONAME
+ _ZThn8_NK14QMediaPlaylist11mediaObjectEv @ 1272 NONAME
+ _ZThn8_NK14QMediaRecorder11mediaObjectEv @ 1273 NONAME
+ _ZThn8_NK18QGraphicsVideoItem12boundingRectEv @ 1274 NONAME
+ _ZeqRK15QMediaTimeRangeS1_ @ 1275 NONAME
+ _ZeqRK18QMediaTimeIntervalS1_ @ 1276 NONAME
+ _Zls6QDebugRK19QVideoSurfaceFormat @ 1277 NONAME
+ _ZmiRK15QMediaTimeRangeS1_ @ 1278 NONAME
+ _ZneRK15QMediaTimeRangeS1_ @ 1279 NONAME
+ _ZneRK18QMediaTimeIntervalS1_ @ 1280 NONAME
+ _ZplRK15QMediaTimeRangeS1_ @ 1281 NONAME
+ _ZN12QCameraFocus11qt_metacallEN11QMetaObject4CallEiPPv @ 1282 NONAME
+ _ZN12QCameraFocus11qt_metacastEPKc @ 1283 NONAME
+ _ZN12QCameraFocus12setFocusModeENS_9FocusModeE @ 1284 NONAME
+ _ZN12QCameraFocus16staticMetaObjectE @ 1285 NONAME DATA 16
+ _ZN12QCameraFocus17focusZonesChangedEv @ 1286 NONAME
+ _ZN12QCameraFocus17setFocusPointModeENS_14FocusPointModeE @ 1287 NONAME
+ _ZN12QCameraFocus18digitalZoomChangedEf @ 1288 NONAME
+ _ZN12QCameraFocus18opticalZoomChangedEf @ 1289 NONAME
+ _ZN12QCameraFocus19getStaticMetaObjectEv @ 1290 NONAME
+ _ZN12QCameraFocus19setCustomFocusPointERK7QPointF @ 1291 NONAME
+ _ZN12QCameraFocus6zoomToEff @ 1292 NONAME
+ _ZN12QCameraFocusC1EP7QCamera @ 1293 NONAME
+ _ZN12QCameraFocusC2EP7QCamera @ 1294 NONAME
+ _ZN12QCameraFocusD0Ev @ 1295 NONAME
+ _ZN12QCameraFocusD1Ev @ 1296 NONAME
+ _ZN12QCameraFocusD2Ev @ 1297 NONAME
+ _ZN12QVideoWidgetC1ER19QVideoWidgetPrivateP7QWidget @ 1298 NONAME
+ _ZN12QVideoWidgetC2ER19QVideoWidgetPrivateP7QWidget @ 1299 NONAME
+ _ZN14QCameraControl11qt_metacallEN11QMetaObject4CallEiPPv @ 1300 NONAME
+ _ZN14QCameraControl11qt_metacastEPKc @ 1301 NONAME
+ _ZN14QCameraControl12stateChangedEN7QCamera5StateE @ 1302 NONAME
+ _ZN14QCameraControl16staticMetaObjectE @ 1303 NONAME DATA 16
+ _ZN14QCameraControl18captureModeChangedEN7QCamera11CaptureModeE @ 1304 NONAME
+ _ZN14QCameraControl19getStaticMetaObjectEv @ 1305 NONAME
+ _ZN14QCameraControl5errorEiRK7QString @ 1306 NONAME
+ _ZN14QCameraControlC2EP7QObject @ 1307 NONAME
+ _ZN14QCameraControlD0Ev @ 1308 NONAME
+ _ZN14QCameraControlD1Ev @ 1309 NONAME
+ _ZN14QCameraControlD2Ev @ 1310 NONAME
+ _ZN15QCameraExposure10flashReadyEb @ 1311 NONAME
+ _ZN15QCameraExposure11qt_metacallEN11QMetaObject4CallEiPPv @ 1312 NONAME
+ _ZN15QCameraExposure11qt_metacastEPKc @ 1313 NONAME
+ _ZN15QCameraExposure12setFlashModeE6QFlagsINS_9FlashModeEE @ 1314 NONAME
+ _ZN15QCameraExposure15apertureChangedEf @ 1315 NONAME
+ _ZN15QCameraExposure15setAutoApertureEv @ 1316 NONAME
+ _ZN15QCameraExposure15setExposureModeENS_12ExposureModeE @ 1317 NONAME
+ _ZN15QCameraExposure15setMeteringModeENS_12MeteringModeE @ 1318 NONAME
+ _ZN15QCameraExposure16staticMetaObjectE @ 1319 NONAME DATA 16
+ _ZN15QCameraExposure17setManualApertureEf @ 1320 NONAME
+ _ZN15QCameraExposure19getStaticMetaObjectEv @ 1321 NONAME
+ _ZN15QCameraExposure19setAutoShutterSpeedEv @ 1322 NONAME
+ _ZN15QCameraExposure19shutterSpeedChangedEf @ 1323 NONAME
+ _ZN15QCameraExposure20apertureRangeChangedEv @ 1324 NONAME
+ _ZN15QCameraExposure21isoSensitivityChangedEi @ 1325 NONAME
+ _ZN15QCameraExposure21setAutoIsoSensitivityEv @ 1326 NONAME
+ _ZN15QCameraExposure21setManualShutterSpeedEf @ 1327 NONAME
+ _ZN15QCameraExposure23setExposureCompensationEf @ 1328 NONAME
+ _ZN15QCameraExposure23setManualIsoSensitivityEi @ 1329 NONAME
+ _ZN15QCameraExposure24shutterSpeedRangeChangedEv @ 1330 NONAME
+ _ZN15QCameraExposureC1EP7QCamera @ 1331 NONAME
+ _ZN15QCameraExposureC2EP7QCamera @ 1332 NONAME
+ _ZN15QCameraExposureD0Ev @ 1333 NONAME
+ _ZN15QCameraExposureD1Ev @ 1334 NONAME
+ _ZN15QCameraExposureD2Ev @ 1335 NONAME
+ _ZN16QCameraFocusZone9setStatusENS_15FocusZoneStatusE @ 1336 NONAME
+ _ZN16QCameraFocusZoneC1ERK6QRectFNS_15FocusZoneStatusE @ 1337 NONAME
+ _ZN16QCameraFocusZoneC1ERKS_ @ 1338 NONAME
+ _ZN16QCameraFocusZoneC1Ev @ 1339 NONAME
+ _ZN16QCameraFocusZoneC2ERK6QRectFNS_15FocusZoneStatusE @ 1340 NONAME
+ _ZN16QCameraFocusZoneC2ERKS_ @ 1341 NONAME
+ _ZN16QCameraFocusZoneC2Ev @ 1342 NONAME
+ _ZN16QCameraFocusZoneD1Ev @ 1343 NONAME
+ _ZN16QCameraFocusZoneD2Ev @ 1344 NONAME
+ _ZN16QCameraFocusZoneaSERKS_ @ 1345 NONAME
+ _ZN17QCameraViewfinder11qt_metacallEN11QMetaObject4CallEiPPv @ 1346 NONAME
+ _ZN17QCameraViewfinder11qt_metacastEPKc @ 1347 NONAME
+ _ZN17QCameraViewfinder14setMediaObjectEP12QMediaObject @ 1348 NONAME
+ _ZN17QCameraViewfinder16staticMetaObjectE @ 1349 NONAME DATA 16
+ _ZN17QCameraViewfinder19getStaticMetaObjectEv @ 1350 NONAME
+ _ZN17QCameraViewfinderC1EP7QWidget @ 1351 NONAME
+ _ZN17QCameraViewfinderC2EP7QWidget @ 1352 NONAME
+ _ZN17QCameraViewfinderD0Ev @ 1353 NONAME
+ _ZN17QCameraViewfinderD1Ev @ 1354 NONAME
+ _ZN17QCameraViewfinderD2Ev @ 1355 NONAME
+ _ZN19QCameraFocusControl11qt_metacallEN11QMetaObject4CallEiPPv @ 1356 NONAME
+ _ZN19QCameraFocusControl11qt_metacastEPKc @ 1357 NONAME
+ _ZN19QCameraFocusControl16staticMetaObjectE @ 1358 NONAME DATA 16
+ _ZN19QCameraFocusControl17focusZonesChangedEv @ 1359 NONAME
+ _ZN19QCameraFocusControl18digitalZoomChangedEf @ 1360 NONAME
+ _ZN19QCameraFocusControl18opticalZoomChangedEf @ 1361 NONAME
+ _ZN19QCameraFocusControl19getStaticMetaObjectEv @ 1362 NONAME
+ _ZN19QCameraFocusControlC2EP7QObject @ 1363 NONAME
+ _ZN19QCameraFocusControlD0Ev @ 1364 NONAME
+ _ZN19QCameraFocusControlD1Ev @ 1365 NONAME
+ _ZN19QCameraFocusControlD2Ev @ 1366 NONAME
+ _ZN19QCameraImageCapture10imageSavedEiRK7QString @ 1367 NONAME
+ _ZN19QCameraImageCapture11qt_metacallEN11QMetaObject4CallEiPPv @ 1368 NONAME
+ _ZN19QCameraImageCapture11qt_metacastEPKc @ 1369 NONAME
+ _ZN19QCameraImageCapture12imageExposedEi @ 1370 NONAME
+ _ZN19QCameraImageCapture13cancelCaptureEv @ 1371 NONAME
+ _ZN19QCameraImageCapture13imageCapturedEiRK6QImage @ 1372 NONAME
+ _ZN19QCameraImageCapture14setMediaObjectEP12QMediaObject @ 1373 NONAME
+ _ZN19QCameraImageCapture16staticMetaObjectE @ 1374 NONAME DATA 16
+ _ZN19QCameraImageCapture19getStaticMetaObjectEv @ 1375 NONAME
+ _ZN19QCameraImageCapture19setEncodingSettingsERK21QImageEncoderSettings @ 1376 NONAME
+ _ZN19QCameraImageCapture22readyForCaptureChangedEb @ 1377 NONAME
+ _ZN19QCameraImageCapture5errorEiNS_5ErrorERK7QString @ 1378 NONAME
+ _ZN19QCameraImageCapture7captureERK7QString @ 1379 NONAME
+ _ZN19QCameraImageCaptureC1EP12QMediaObjectP7QObject @ 1380 NONAME
+ _ZN19QCameraImageCaptureC2EP12QMediaObjectP7QObject @ 1381 NONAME
+ _ZN19QCameraImageCaptureD0Ev @ 1382 NONAME
+ _ZN19QCameraImageCaptureD1Ev @ 1383 NONAME
+ _ZN19QCameraImageCaptureD2Ev @ 1384 NONAME
+ _ZN19QCameraLocksControl11qt_metacallEN11QMetaObject4CallEiPPv @ 1385 NONAME
+ _ZN19QCameraLocksControl11qt_metacastEPKc @ 1386 NONAME
+ _ZN19QCameraLocksControl16staticMetaObjectE @ 1387 NONAME DATA 16
+ _ZN19QCameraLocksControl17lockStatusChangedEN7QCamera8LockTypeENS0_10LockStatusENS0_16LockChangeReasonE @ 1388 NONAME
+ _ZN19QCameraLocksControl19getStaticMetaObjectEv @ 1389 NONAME
+ _ZN19QCameraLocksControlC2EP7QObject @ 1390 NONAME
+ _ZN19QCameraLocksControlD0Ev @ 1391 NONAME
+ _ZN19QCameraLocksControlD1Ev @ 1392 NONAME
+ _ZN19QCameraLocksControlD2Ev @ 1393 NONAME
+ _ZN22QCameraExposureControl10flashReadyEb @ 1394 NONAME
+ _ZN22QCameraExposureControl11qt_metacallEN11QMetaObject4CallEiPPv @ 1395 NONAME
+ _ZN22QCameraExposureControl11qt_metacastEPKc @ 1396 NONAME
+ _ZN22QCameraExposureControl16staticMetaObjectE @ 1397 NONAME DATA 16
+ _ZN22QCameraExposureControl19getStaticMetaObjectEv @ 1398 NONAME
+ _ZN22QCameraExposureControl24exposureParameterChangedEi @ 1399 NONAME
+ _ZN22QCameraExposureControl29exposureParameterRangeChangedEi @ 1400 NONAME
+ _ZN22QCameraExposureControlC2EP7QObject @ 1401 NONAME
+ _ZN22QCameraExposureControlD0Ev @ 1402 NONAME
+ _ZN22QCameraExposureControlD1Ev @ 1403 NONAME
+ _ZN22QCameraExposureControlD2Ev @ 1404 NONAME
+ _ZN22QCameraImageProcessing11qt_metacallEN11QMetaObject4CallEiPPv @ 1405 NONAME
+ _ZN22QCameraImageProcessing11qt_metacastEPKc @ 1406 NONAME
+ _ZN22QCameraImageProcessing11setContrastEi @ 1407 NONAME
+ _ZN22QCameraImageProcessing13setSaturationEi @ 1408 NONAME
+ _ZN22QCameraImageProcessing16staticMetaObjectE @ 1409 NONAME DATA 16
+ _ZN22QCameraImageProcessing17setDenoisingLevelEi @ 1410 NONAME
+ _ZN22QCameraImageProcessing18setSharpeningLevelEi @ 1411 NONAME
+ _ZN22QCameraImageProcessing19getStaticMetaObjectEv @ 1412 NONAME
+ _ZN22QCameraImageProcessing19setWhiteBalanceModeENS_16WhiteBalanceModeE @ 1413 NONAME
+ _ZN22QCameraImageProcessing21setManualWhiteBalanceEi @ 1414 NONAME
+ _ZN22QCameraImageProcessingC1EP7QCamera @ 1415 NONAME
+ _ZN22QCameraImageProcessingC2EP7QCamera @ 1416 NONAME
+ _ZN22QCameraImageProcessingD0Ev @ 1417 NONAME
+ _ZN22QCameraImageProcessingD1Ev @ 1418 NONAME
+ _ZN22QCameraImageProcessingD2Ev @ 1419 NONAME
+ _ZN26QCameraImageCaptureControl10imageSavedEiRK7QString @ 1420 NONAME
+ _ZN26QCameraImageCaptureControl11qt_metacallEN11QMetaObject4CallEiPPv @ 1421 NONAME
+ _ZN26QCameraImageCaptureControl11qt_metacastEPKc @ 1422 NONAME
+ _ZN26QCameraImageCaptureControl12imageExposedEi @ 1423 NONAME
+ _ZN26QCameraImageCaptureControl13imageCapturedEiRK6QImage @ 1424 NONAME
+ _ZN26QCameraImageCaptureControl16staticMetaObjectE @ 1425 NONAME DATA 16
+ _ZN26QCameraImageCaptureControl19getStaticMetaObjectEv @ 1426 NONAME
+ _ZN26QCameraImageCaptureControl22readyForCaptureChangedEb @ 1427 NONAME
+ _ZN26QCameraImageCaptureControl5errorEiiRK7QString @ 1428 NONAME
+ _ZN26QCameraImageCaptureControlC2EP7QObject @ 1429 NONAME
+ _ZN26QCameraImageCaptureControlD0Ev @ 1430 NONAME
+ _ZN26QCameraImageCaptureControlD1Ev @ 1431 NONAME
+ _ZN26QCameraImageCaptureControlD2Ev @ 1432 NONAME
+ _ZN29QCameraImageProcessingControl11qt_metacallEN11QMetaObject4CallEiPPv @ 1433 NONAME
+ _ZN29QCameraImageProcessingControl11qt_metacastEPKc @ 1434 NONAME
+ _ZN29QCameraImageProcessingControl16staticMetaObjectE @ 1435 NONAME DATA 16
+ _ZN29QCameraImageProcessingControl19getStaticMetaObjectEv @ 1436 NONAME
+ _ZN29QCameraImageProcessingControlC2EP7QObject @ 1437 NONAME
+ _ZN29QCameraImageProcessingControlD0Ev @ 1438 NONAME
+ _ZN29QCameraImageProcessingControlD1Ev @ 1439 NONAME
+ _ZN29QCameraImageProcessingControlD2Ev @ 1440 NONAME
+ _ZN7QCamera10lockFailedEv @ 1441 NONAME
+ _ZN7QCamera11qt_metacallEN11QMetaObject4CallEiPPv @ 1442 NONAME
+ _ZN7QCamera11qt_metacastEPKc @ 1443 NONAME
+ _ZN7QCamera12stateChangedENS_5StateE @ 1444 NONAME
+ _ZN7QCamera13searchAndLockE6QFlagsINS_8LockTypeEE @ 1445 NONAME
+ _ZN7QCamera13searchAndLockEv @ 1446 NONAME
+ _ZN7QCamera13setViewfinderEP12QVideoWidget @ 1447 NONAME
+ _ZN7QCamera13setViewfinderEP18QGraphicsVideoItem @ 1448 NONAME
+ _ZN7QCamera14setCaptureModeENS_11CaptureModeE @ 1449 NONAME
+ _ZN7QCamera16availableDevicesEv @ 1450 NONAME
+ _ZN7QCamera16staticMetaObjectE @ 1451 NONAME DATA 16
+ _ZN7QCamera17deviceDescriptionERK10QByteArray @ 1452 NONAME
+ _ZN7QCamera17lockStatusChangedENS_10LockStatusENS_16LockChangeReasonE @ 1453 NONAME
+ _ZN7QCamera17lockStatusChangedENS_8LockTypeENS_10LockStatusENS_16LockChangeReasonE @ 1454 NONAME
+ _ZN7QCamera18captureModeChangedENS_11CaptureModeE @ 1455 NONAME
+ _ZN7QCamera19getStaticMetaObjectEv @ 1456 NONAME
+ _ZN7QCamera4stopEv @ 1457 NONAME
+ _ZN7QCamera5errorENS_5ErrorE @ 1458 NONAME
+ _ZN7QCamera5startEv @ 1459 NONAME
+ _ZN7QCamera6lockedEv @ 1460 NONAME
+ _ZN7QCamera6unlockE6QFlagsINS_8LockTypeEE @ 1461 NONAME
+ _ZN7QCamera6unlockEv @ 1462 NONAME
+ _ZN7QCameraC1EP7QObjectP21QMediaServiceProvider @ 1463 NONAME
+ _ZN7QCameraC1ERK10QByteArrayP7QObject @ 1464 NONAME
+ _ZN7QCameraC2EP7QObjectP21QMediaServiceProvider @ 1465 NONAME
+ _ZN7QCameraC2ERK10QByteArrayP7QObject @ 1466 NONAME
+ _ZN7QCameraD0Ev @ 1467 NONAME
+ _ZN7QCameraD1Ev @ 1468 NONAME
+ _ZN7QCameraD2Ev @ 1469 NONAME
+ _ZNK12QCameraFocus10focusZonesEv @ 1470 NONAME
+ _ZNK12QCameraFocus10metaObjectEv @ 1471 NONAME
+ _ZNK12QCameraFocus11digitalZoomEv @ 1472 NONAME
+ _ZNK12QCameraFocus11isAvailableEv @ 1473 NONAME
+ _ZNK12QCameraFocus11opticalZoomEv @ 1474 NONAME
+ _ZNK12QCameraFocus14focusPointModeEv @ 1475 NONAME
+ _ZNK12QCameraFocus16customFocusPointEv @ 1476 NONAME
+ _ZNK12QCameraFocus18maximumDigitalZoomEv @ 1477 NONAME
+ _ZNK12QCameraFocus18maximumOpticalZoomEv @ 1478 NONAME
+ _ZNK12QCameraFocus20isFocusModeSupportedENS_9FocusModeE @ 1479 NONAME
+ _ZNK12QCameraFocus25isFocusPointModeSupportedENS_14FocusPointModeE @ 1480 NONAME
+ _ZNK12QCameraFocus9focusModeEv @ 1481 NONAME
+ _ZNK14QCameraControl10metaObjectEv @ 1482 NONAME
+ _ZNK15QCameraExposure10metaObjectEv @ 1483 NONAME
+ _ZNK15QCameraExposure11isAvailableEv @ 1484 NONAME
+ _ZNK15QCameraExposure12exposureModeEv @ 1485 NONAME
+ _ZNK15QCameraExposure12isFlashReadyEv @ 1486 NONAME
+ _ZNK15QCameraExposure12meteringModeEv @ 1487 NONAME
+ _ZNK15QCameraExposure12shutterSpeedEv @ 1488 NONAME
+ _ZNK15QCameraExposure14isoSensitivityEv @ 1489 NONAME
+ _ZNK15QCameraExposure18supportedAperturesEPb @ 1490 NONAME
+ _ZNK15QCameraExposure20exposureCompensationEv @ 1491 NONAME
+ _ZNK15QCameraExposure20isFlashModeSupportedE6QFlagsINS_9FlashModeEE @ 1492 NONAME
+ _ZNK15QCameraExposure22supportedShutterSpeedsEPb @ 1493 NONAME
+ _ZNK15QCameraExposure23isExposureModeSupportedENS_12ExposureModeE @ 1494 NONAME
+ _ZNK15QCameraExposure23isMeteringModeSupportedENS_12MeteringModeE @ 1495 NONAME
+ _ZNK15QCameraExposure25supportedIsoSensitivitiesEPb @ 1496 NONAME
+ _ZNK15QCameraExposure8apertureEv @ 1497 NONAME
+ _ZNK15QCameraExposure9flashModeEv @ 1498 NONAME
+ _ZNK16QCameraFocusZone4areaEv @ 1499 NONAME
+ _ZNK16QCameraFocusZone6statusEv @ 1500 NONAME
+ _ZNK16QCameraFocusZone7isValidEv @ 1501 NONAME
+ _ZNK16QCameraFocusZoneeqERKS_ @ 1502 NONAME
+ _ZNK16QCameraFocusZoneneERKS_ @ 1503 NONAME
+ _ZNK17QCameraViewfinder10metaObjectEv @ 1504 NONAME
+ _ZNK17QCameraViewfinder11mediaObjectEv @ 1505 NONAME
+ _ZNK17QMediaImageViewer8playlistEv @ 1506 NONAME
+ _ZNK19QCameraFocusControl10metaObjectEv @ 1507 NONAME
+ _ZNK19QCameraImageCapture10metaObjectEv @ 1508 NONAME
+ _ZNK19QCameraImageCapture11errorStringEv @ 1509 NONAME
+ _ZNK19QCameraImageCapture11isAvailableEv @ 1510 NONAME
+ _ZNK19QCameraImageCapture11mediaObjectEv @ 1511 NONAME
+ _ZNK19QCameraImageCapture16encodingSettingsEv @ 1512 NONAME
+ _ZNK19QCameraImageCapture17availabilityErrorEv @ 1513 NONAME
+ _ZNK19QCameraImageCapture17isReadyForCaptureEv @ 1514 NONAME
+ _ZNK19QCameraImageCapture20supportedImageCodecsEv @ 1515 NONAME
+ _ZNK19QCameraImageCapture20supportedResolutionsERK21QImageEncoderSettingsPb @ 1516 NONAME
+ _ZNK19QCameraImageCapture21imageCodecDescriptionERK7QString @ 1517 NONAME
+ _ZNK19QCameraImageCapture5errorEv @ 1518 NONAME
+ _ZNK19QCameraLocksControl10metaObjectEv @ 1519 NONAME
+ _ZNK22QCameraExposureControl10metaObjectEv @ 1520 NONAME
+ _ZNK22QCameraImageProcessing10metaObjectEv @ 1521 NONAME
+ _ZNK22QCameraImageProcessing10saturationEv @ 1522 NONAME
+ _ZNK22QCameraImageProcessing11isAvailableEv @ 1523 NONAME
+ _ZNK22QCameraImageProcessing14denoisingLevelEv @ 1524 NONAME
+ _ZNK22QCameraImageProcessing15sharpeningLevelEv @ 1525 NONAME
+ _ZNK22QCameraImageProcessing16whiteBalanceModeEv @ 1526 NONAME
+ _ZNK22QCameraImageProcessing18manualWhiteBalanceEv @ 1527 NONAME
+ _ZNK22QCameraImageProcessing20isDenoisingSupportedEv @ 1528 NONAME
+ _ZNK22QCameraImageProcessing21isSharpeningSupportedEv @ 1529 NONAME
+ _ZNK22QCameraImageProcessing27isWhiteBalanceModeSupportedENS_16WhiteBalanceModeE @ 1530 NONAME
+ _ZNK22QCameraImageProcessing8contrastEv @ 1531 NONAME
+ _ZNK26QCameraImageCaptureControl10metaObjectEv @ 1532 NONAME
+ _ZNK29QCameraImageProcessingControl10metaObjectEv @ 1533 NONAME
+ _ZNK7QCamera10lockStatusENS_8LockTypeE @ 1534 NONAME
+ _ZNK7QCamera10lockStatusEv @ 1535 NONAME
+ _ZNK7QCamera10metaObjectEv @ 1536 NONAME
+ _ZNK7QCamera11captureModeEv @ 1537 NONAME
+ _ZNK7QCamera11errorStringEv @ 1538 NONAME
+ _ZNK7QCamera11isAvailableEv @ 1539 NONAME
+ _ZNK7QCamera14requestedLocksEv @ 1540 NONAME
+ _ZNK7QCamera14supportedLocksEv @ 1541 NONAME
+ _ZNK7QCamera15imageProcessingEv @ 1542 NONAME
+ _ZNK7QCamera17availabilityErrorEv @ 1543 NONAME
+ _ZNK7QCamera22isCaptureModeSupportedENS_11CaptureModeE @ 1544 NONAME
+ _ZNK7QCamera5errorEv @ 1545 NONAME
+ _ZNK7QCamera5focusEv @ 1546 NONAME
+ _ZNK7QCamera5stateEv @ 1547 NONAME
+ _ZNK7QCamera8exposureEv @ 1548 NONAME
+ _ZTI12QCameraFocus @ 1549 NONAME
+ _ZTI14QCameraControl @ 1550 NONAME
+ _ZTI15QCameraExposure @ 1551 NONAME
+ _ZTI17QCameraViewfinder @ 1552 NONAME
+ _ZTI19QCameraFocusControl @ 1553 NONAME
+ _ZTI19QCameraImageCapture @ 1554 NONAME
+ _ZTI19QCameraLocksControl @ 1555 NONAME
+ _ZTI22QCameraExposureControl @ 1556 NONAME
+ _ZTI22QCameraImageProcessing @ 1557 NONAME
+ _ZTI26QCameraImageCaptureControl @ 1558 NONAME
+ _ZTI29QCameraImageProcessingControl @ 1559 NONAME
+ _ZTI7QCamera @ 1560 NONAME
+ _ZTV12QCameraFocus @ 1561 NONAME
+ _ZTV14QCameraControl @ 1562 NONAME
+ _ZTV15QCameraExposure @ 1563 NONAME
+ _ZTV17QCameraViewfinder @ 1564 NONAME
+ _ZTV19QCameraFocusControl @ 1565 NONAME
+ _ZTV19QCameraImageCapture @ 1566 NONAME
+ _ZTV19QCameraLocksControl @ 1567 NONAME
+ _ZTV22QCameraExposureControl @ 1568 NONAME
+ _ZTV22QCameraImageProcessing @ 1569 NONAME
+ _ZTV26QCameraImageCaptureControl @ 1570 NONAME
+ _ZTV29QCameraImageProcessingControl @ 1571 NONAME
+ _ZTV7QCamera @ 1572 NONAME
+ _ZThn20_N17QCameraViewfinder14setMediaObjectEP12QMediaObject @ 1573 NONAME
+ _ZThn20_N17QCameraViewfinderD0Ev @ 1574 NONAME
+ _ZThn20_N17QCameraViewfinderD1Ev @ 1575 NONAME
+ _ZThn20_NK17QCameraViewfinder11mediaObjectEv @ 1576 NONAME
+ _ZThn8_N17QCameraViewfinderD0Ev @ 1577 NONAME
+ _ZThn8_N17QCameraViewfinderD1Ev @ 1578 NONAME
+ _ZThn8_N19QCameraImageCapture14setMediaObjectEP12QMediaObject @ 1579 NONAME
+ _ZThn8_N19QCameraImageCaptureD0Ev @ 1580 NONAME
+ _ZThn8_N19QCameraImageCaptureD1Ev @ 1581 NONAME
+ _ZThn8_NK19QCameraImageCapture11mediaObjectEv @ 1582 NONAME
+ _ZN17QMediaImageViewer14setVideoOutputEP12QVideoWidget @ 1583 NONAME
+ _ZN17QMediaImageViewer14setVideoOutputEP18QGraphicsVideoItem @ 1584 NONAME
+ _ZN21QAbstractVideoSurface19setNativeResolutionERK5QSize @ 1585 NONAME
+ _ZN21QAbstractVideoSurface23nativeResolutionChangedERK5QSize @ 1586 NONAME
+ _ZNK21QAbstractVideoSurface16nativeResolutionEv @ 1587 NONAME
+ _ZN14QCameraControl13statusChangedEN7QCamera6StatusE @ 1588 NONAME
+ _ZN15QCameraExposure27exposureCompensationChangedEf @ 1589 NONAME
+ _ZN19QCameraFlashControl10flashReadyEb @ 1590 NONAME
+ _ZN19QCameraFlashControl11qt_metacallEN11QMetaObject4CallEiPPv @ 1591 NONAME
+ _ZN19QCameraFlashControl11qt_metacastEPKc @ 1592 NONAME
+ _ZN19QCameraFlashControl16staticMetaObjectE @ 1593 NONAME DATA 16
+ _ZN19QCameraFlashControl19getStaticMetaObjectEv @ 1594 NONAME
+ _ZN19QCameraFlashControlC2EP7QObject @ 1595 NONAME
+ _ZN19QCameraFlashControlD0Ev @ 1596 NONAME
+ _ZN19QCameraFlashControlD1Ev @ 1597 NONAME
+ _ZN19QCameraFlashControlD2Ev @ 1598 NONAME
+ _ZN7QCamera13statusChangedENS_6StatusE @ 1599 NONAME
+ _ZN7QCamera4loadEv @ 1600 NONAME
+ _ZN7QCamera6unloadEv @ 1601 NONAME
+ _ZNK19QCameraFlashControl10metaObjectEv @ 1602 NONAME
+ _ZNK7QCamera6statusEv @ 1603 NONAME
+ _ZTI19QCameraFlashControl @ 1604 NONAME
+ _ZTV19QCameraFlashControl @ 1605 NONAME
+ _ZN12QCameraFocus25maximumDigitalZoomChangedEf @ 1606 NONAME
+ _ZN12QCameraFocus25maximumOpticalZoomChangedEf @ 1607 NONAME
+ _ZN12QSoundEffect12setLoopCountEi @ 1608 NONAME
+ _ZN12QSoundEffect13loadedChangedEv @ 1609 NONAME
+ _ZN12QSoundEffect16loopCountChangedEv @ 1610 NONAME
+ _ZN12QSoundEffect18supportedMimeTypesEv @ 1611 NONAME
+ _ZN12QSoundEffect4stopEv @ 1612 NONAME
+ _ZN19QCameraFocusControl25maximumDigitalZoomChangedEf @ 1613 NONAME
+ _ZN19QCameraFocusControl25maximumOpticalZoomChangedEf @ 1614 NONAME
+ _ZNK12QSoundEffect8isLoadedEv @ 1615 NONAME
+ _ZNK12QSoundEffect9loopCountEv @ 1616 NONAME
+ _ZN12QSoundEffect13statusChangedEv @ 1617 NONAME
+ _ZN12QSoundEffect14playingChangedEv @ 1618 NONAME
+ _ZNK12QSoundEffect6statusEv @ 1619 NONAME
+ _ZNK12QSoundEffect9isPlayingEv @ 1620 NONAME
+ _ZN12QMediaPlayer14setVideoOutputEP21QAbstractVideoSurface @ 1621 NONAME
+ _ZN12QMediaPlayer24setNetworkConfigurationsERK5QListI21QNetworkConfigurationE @ 1622 NONAME
+ _ZN12QMediaPlayer27networkConfigurationChangedERK21QNetworkConfiguration @ 1623 NONAME
+ _ZN17QMediaImageViewer14setVideoOutputEP21QAbstractVideoSurface @ 1624 NONAME
+ _ZN26QMediaNetworkAccessControl11qt_metacallEN11QMetaObject4CallEiPPv @ 1625 NONAME
+ _ZN26QMediaNetworkAccessControl11qt_metacastEPKc @ 1626 NONAME
+ _ZN26QMediaNetworkAccessControl16staticMetaObjectE @ 1627 NONAME DATA 16
+ _ZN26QMediaNetworkAccessControl19getStaticMetaObjectEv @ 1628 NONAME
+ _ZN26QMediaNetworkAccessControl20configurationChangedERK21QNetworkConfiguration @ 1629 NONAME
+ _ZN26QMediaNetworkAccessControlC2EP7QObject @ 1630 NONAME
+ _ZN26QMediaNetworkAccessControlD0Ev @ 1631 NONAME
+ _ZN26QMediaNetworkAccessControlD1Ev @ 1632 NONAME
+ _ZN26QMediaNetworkAccessControlD2Ev @ 1633 NONAME
+ _ZN7QCamera13setViewfinderEP21QAbstractVideoSurface @ 1634 NONAME
+ _ZNK12QMediaPlayer27currentNetworkConfigurationEv @ 1635 NONAME
+ _ZNK26QMediaNetworkAccessControl10metaObjectEv @ 1636 NONAME
+ _ZTI26QMediaNetworkAccessControl @ 1637 NONAME
+ _ZTV26QMediaNetworkAccessControl @ 1638 NONAME
+
diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro
new file mode 100644
index 000000000..3ce0af604
--- /dev/null
+++ b/src/s60installs/s60installs.pro
@@ -0,0 +1,514 @@
+TEMPLATE = subdirs
+
+isEmpty(QT_LIBINFIX):symbian {
+ include(../../staticconfig.pri)
+ load(data_caging_paths)
+ include($$QT_MOBILITY_BUILD_TREE/config.pri)
+
+ SUBDIRS =
+ TARGET = "QtMobility"
+ TARGET.UID3 = 0x2002ac89
+
+ VERSION = 1.2.0
+
+ vendorinfo = \
+ "; Localised Vendor name" \
+ "%{\"Nokia\"}" \
+ " " \
+ "; Unique Vendor name" \
+ ":\"Nokia\"" \
+ " "
+ qtmobilitydeployment.pkg_prerules += vendorinfo
+
+
+ epoc31 = $$(EPOCROOT31)
+ epoc32 = $$(EPOCROOT32)
+ epoc50 = $$(EPOCROOT50)
+ epoc51 = $$(EPOCROOT51)
+ epocS3PS1 = $$(EPOCROOT_S3PS1)
+ epocS3PS2 = $$(EPOCROOT_S3PS2)
+
+ # default to EPOCROOT if EPOCROOTxy not defined
+ isEmpty(epoc31) {
+ EPOCROOT31 = $${EPOCROOT}
+ } else {
+ EPOCROOT31 = $$(EPOCROOT31)
+ }
+ isEmpty(epoc32) {
+ EPOCROOT32 = $${EPOCROOT}
+ }else {
+ EPOCROOT32 = $$(EPOCROOT32)
+ }
+ isEmpty(epoc50) {
+ EPOCROOT50 = $${EPOCROOT}
+ } else {
+ EPOCROOT50 = $$(EPOCROOT50)
+ }
+ #Epocroot 51 is based on a N97 sdk
+ isEmpty(epoc51) {
+ EPOCROOT51 = $${EPOCROOT}
+ } else {
+ EPOCROOT51 = $$(EPOCROOT51)
+ }
+ isEmpty(epocS3PS1) {
+ EPOCROOT_S3PS1 = $${EPOCROOT}
+ } else {
+ EPOCROOT_S3PS1 = $$(EPOCROOT_S3PS1)
+ }
+ isEmpty(epocS3PS2) {
+ EPOCROOT_S3PS2 = $${EPOCROOT}
+ } else {
+ EPOCROOT_S3PS2 = $$(EPOCROOT_S3PS2)
+ }
+
+ #Symbian^3 and beyond requires special package flags
+ #we cannot use S60_VERSION == 5.2 as Qt 4.6.x does not define it yet
+ #see $QTDIR/mkspecs/common/symbian/symbian.conf for details
+ exists($${EPOCROOT}epoc32/release/winscw/udeb/z/system/install/series60v5.2.sis)|exists($${EPOCROOT}epoc32/data/z/system/install/series60v5.2.sis)|exists($${EPOCROOT}epoc32/release/armv5/lib/libstdcppv5.dso) {
+ pkg_version = $$replace(VERSION,"\\.",",")
+ qtmobilitydeployment.pkg_prerules += "$${LITERAL_HASH}{\"QtMobility\"},(0x2002AC89),$${pkg_version},TYPE=SA,RU,NR"
+ }
+
+ contains(mobility_modules, messaging) {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtMessaging.dll
+
+ contains(QT_CONFIG, declarative): {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/declarative_messaging.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\messaging\\qmakepluginstubs\\declarative_messaging.qtplugin\" - \"!:\\resource\\qt\\imports\\QtMobility\\messaging\\declarative_messaging.qtplugin\""
+ qmldirs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\messaging\\qmldir\" - \"!:\\resource\\qt\\imports\\QtMobility\\messaging\\qmldir\""
+ }
+ }
+
+ contains(mobility_modules, connectivity) {
+ # QtConnectivity needs to be built and deployed to each Symbian version differently. This
+ # is because NFC support is only available from Symbian^3 PS2 onwards. There are also some
+ # differences with Bluetooth, hence the Symbian^1 variants.
+ #
+ # - PS2 build has NFC and Bluetooth support, requires Symbian^3 device with PS2 firmware
+ # - PS1 build has Bluetooth support only (NFC is a stub), requires Symbian^3 device with
+ # PS1 firmware
+ # Installing Qt Mobility on a Symbian^3 PS1 device then upgrading device firmware to PS2
+ # will leave Qt Mobility NFC support disabled until Qt Mobility is reinstalled/upgraded.
+ # - S60 5.0 build has Bluetooth support only (NFC is a stub)
+ # - S60 3.1 and 3.2 build only produces a stub library.
+ connectivity = \
+ "IF package(0x20022E6D) AND exists(\"z:\\sys\\bin\\nfc.dll\")" \
+ " \"$${EPOCROOT_S3PS2}epoc32/release/$(PLATFORM)/$(TARGET)/QtConnectivity.dll\" - \"!:\\sys\\bin\\QtConnectivity.dll\"" \
+ "ELSEIF package(0x20022E6D)" \
+ " \"$${EPOCROOT_S3PS1}epoc32/release/$(PLATFORM)/$(TARGET)/QtConnectivity.dll\" - \"!:\\sys\\bin\\QtConnectivity.dll\"" \
+ "ELSEIF package(0x1028315F)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtConnectivity.dll\" - \"!:\\sys\\bin\\QtConnectivity.dll\"" \
+ "ELSEIF package(0x102752AE) OR package(0x102032BE)" \
+ " \"$${EPOCROOT32}epoc32/release/$(PLATFORM)/$(TARGET)/QtConnectivity.dll\" - \"!:\\sys\\bin\\QtConnectivity.dll\"" \
+ "ELSE" \
+ " \"$${EPOCROOT}epoc32/release/$(PLATFORM)/$(TARGET)/QtConnectivity.dll\" - \"!:\\sys\\bin\\QtConnectivity.dll\"" \
+ "ENDIF"
+
+ contains(QT_CONFIG, declarative): {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/declarative_connectivity.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\connectivity\\qmakepluginstubs\\declarative_connectivity.qtplugin\" - \"!:\\resource\\qt\\imports\\QtMobility\\connectivity\\declarative_connectivity.qtplugin\""
+ qmldirs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\connectivity\\qmldir\" - \"!:\\resource\\qt\\imports\\QtMobility\\connectivity\\qmldir\""
+ }
+
+
+ qtmobilitydeployment.pkg_postrules += connectivity
+ }
+
+ contains(mobility_modules, serviceframework) {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtServiceFramework.dll \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qsfwdatabasemanagerserver.exe
+ contains(QT_CONFIG, declarative): {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/declarative_serviceframework.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\serviceframework\\qmakepluginstubs\\declarative_serviceframework.qtplugin\" - \"!:\\resource\\qt\\imports\\QtMobility\\serviceframework\\declarative_serviceframework.qtplugin\""
+ qmldirs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\serviceframework\\qmldir\" - \"!:\\resource\\qt\\imports\\QtMobility\\serviceframework\\qmldir\""
+ }
+ }
+
+ contains(mobility_modules, location) {
+ qtmobilitydeployment.sources += $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtLocation.dll
+ qtmobilitydeployment.sources += $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtgeoservices_nokia.dll
+ qtmobilitydeployment.sources += $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtlandmarks_symbian.dll
+ pluginstubs += "\"$$QT_MOBILITY_BUILD_TREE/plugins/geoservices/nokia/qmakepluginstubs/qtgeoservices_nokia.qtplugin\" - \"!:\\resource\\qt\\plugins\\geoservices\\qtgeoservices_nokia.qtplugin\""
+ pluginstubs += "\"$$QT_MOBILITY_BUILD_TREE/plugins/landmarks/symbian_landmarks/qmakepluginstubs/qtlandmarks_symbian.qtplugin\" - \"!:\\resource\\qt\\plugins\\landmarks\\qtlandmarks_symbian.qtplugin\""
+ contains(QT_CONFIG, declarative): {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/declarative_location.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\location\\qmakepluginstubs\\declarative_location.qtplugin\" - \"!:\\resource\\qt\\imports\\QtMobility\\location\\declarative_location.qtplugin\""
+ qmldirs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\location\\qmldir\" - \"!:\\resource\\qt\\imports\\QtMobility\\location\\qmldir\""
+ }
+ }
+
+ contains(mobility_modules, systeminfo) {
+ sysinfo = \
+ "IF package(0x1028315F)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtSystemInfo.dll\" - \"!:\\sys\\bin\\QtSystemInfo.dll\"" \
+ "ELSEIF package(0x102032BE)" \
+ " \"$${EPOCROOT31}epoc32/release/$(PLATFORM)/$(TARGET)/QtSystemInfo.dll\" - \"!:\\sys\\bin\\QtSystemInfo.dll\"" \
+ "ELSEIF package(0x102752AE)" \
+ " \"$${EPOCROOT32}epoc32/release/$(PLATFORM)/$(TARGET)/QtSystemInfo.dll\" - \"!:\\sys\\bin\\QtSystemInfo.dll\"" \
+ "ELSE" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtSystemInfo.dll\" - \"!:\\sys\\bin\\QtSystemInfo.dll\"" \
+ "ENDIF"
+
+ qtmobilitydeployment.pkg_postrules += sysinfo
+ contains(QT_CONFIG, declarative): {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/declarative_systeminfo.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\systeminfo\\qmakepluginstubs\\declarative_systeminfo.qtplugin\" - \"!:\\resource\\qt\\imports\\QtMobility\\systeminfo\\declarative_systeminfo.qtplugin\""
+ qmldirs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\systeminfo\\qmldir\" - \"!:\\resource\\qt\\imports\\QtMobility\\systeminfo\\qmldir\""
+ }
+ }
+
+ contains(mobility_modules, publishsubscribe) {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtPublishSubscribe.dll \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qpspathmapperserver.exe
+ contains(QT_CONFIG, declarative) {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/declarative_publishsubscribe.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\publishsubscribe\\qmakepluginstubs\\declarative_publishsubscribe.qtplugin\" - \"!:\\resource\\qt\\imports\\QtMobility\\publishsubscribe\\declarative_publishsubscribe.qtplugin\""
+ qmldirs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\publishsubscribe\\qmldir\" - \"!:\\resource\\qt\\imports\\QtMobility\\publishsubscribe\\qmldir\""
+ }
+ }
+
+ contains(mobility_modules, versit) {
+ qtmobilitydeployment.sources += $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtVersit.dll
+ qtmobilitydeployment.sources += $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtversit_backuphandler.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\versit\\backuphandler\\qmakepluginstubs\\qtversit_backuphandler.qtplugin\" - \"!:\\resource\\qt\\plugins\\versit\\qtversit_backuphandler.qtplugin\""
+
+ ## now the versit organizer module - depends on versit and organizer.
+ contains(mobility_modules, organizer) {
+ qtmobilitydeployment.sources += $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtVersitOrganizer.dll
+ }
+ }
+
+ contains(mobility_modules, feedback) {
+ qtmobilitydeployment.sources += $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtFeedback.dll
+ contains(immersion_enabled, yes) {
+ qtmobilitydeployment.sources += $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtfeedback_immersion.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\feedback\\immersion\\qmakepluginstubs\\qtfeedback_immersion.qtplugin\" - \"!:\\resource\\qt\\plugins\\feedback\\qtfeedback_immersion.qtplugin\""
+ }
+
+ equals(QT_MAJOR_VERSION, 4) : greaterThan(QT_MINOR_VERSION, 6):contains(mobility_modules,multimedia) {
+ qtmobilitydeployment.sources += $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtfeedback_mmk.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\feedback\\mmk\\qmakepluginstubs\\qtfeedback_mmk.qtplugin\" - \"!:\\resource\\qt\\plugins\\feedback\\qtfeedback_mmk.qtplugin\""
+ }
+
+ feedback = \
+ "IF package(0x1028315F)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtfeedback_symbian.dll\" - \"!:\\sys\\bin\\qtfeedback_symbian.dll\"" \
+ "ELSEIF package(0x102752AE)" \
+ " \"$${EPOCROOT32}epoc32/release/$(PLATFORM)/$(TARGET)/qtfeedback_symbian.dll\" - \"!:\\sys\\bin\\qtfeedback_symbian.dll\"" \
+ "ELSEIF package(0x102032BE)" \
+ " \"$${EPOCROOT31}epoc32/release/$(PLATFORM)/$(TARGET)/qtfeedback_symbian.dll\" - \"!:\\sys\\bin\\qtfeedback_symbian.dll\"" \
+ "ELSE" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtfeedback_symbian.dll\" - \"!:\\sys\\bin\\qtfeedback_symbian.dll\"" \
+ "ENDIF"
+
+ qtmobilitydeployment.pkg_postrules += feedback
+
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\feedback\\symbian\\qmakepluginstubs\\qtfeedback_symbian.qtplugin\" - \"!:\\resource\\qt\\plugins\\feedback\\qtfeedback_symbian.qtplugin\""
+
+ contains(QT_CONFIG, declarative): {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/declarative_feedback.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\feedback\\qmakepluginstubs\\declarative_feedback.qtplugin\" - \"!:\\resource\\qt\\imports\\QtMobility\\feedback\\declarative_feedback.qtplugin\""
+ qmldirs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\feedback\\qmldir\" - \"!:\\resource\\qt\\imports\\QtMobility\\feedback\\qmldir\""
+ }
+ }
+
+ contains(mobility_modules, organizer) {
+ qtmobilitydeployment.sources += $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtOrganizer.dll
+ organizer = \
+ "IF package(0x1028315F)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtorganizer_symbian.dll\" - \"!:\\sys\\bin\\qtorganizer_symbian.dll\"" \
+ "ELSEIF package(0x102752AE)" \
+ " \"$${EPOCROOT32}epoc32/release/$(PLATFORM)/$(TARGET)/qtorganizer_symbian.dll\" - \"!:\\sys\\bin\\qtorganizer_symbian.dll\"" \
+ "ELSEIF package(0x102032BE)" \
+ " \"$${EPOCROOT31}epoc32/release/$(PLATFORM)/$(TARGET)/qtorganizer_symbian.dll\" - \"!:\\sys\\bin\\qtorganizer_symbian.dll\"" \
+ "ELSE" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtorganizer_symbian.dll\" - \"!:\\sys\\bin\\qtorganizer_symbian.dll\"" \
+ "ENDIF"
+
+ qtmobilitydeployment.pkg_postrules += organizer
+
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\organizer\\symbian\\qmakepluginstubs\\qtorganizer_symbian.qtplugin\" - \"!:\\resource\\qt\\plugins\\organizer\\qtorganizer_symbian.qtplugin\""
+ contains(QT_CONFIG, declarative):contains(mobility_modules,versit) {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/declarative_organizer.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\organizer\\qmakepluginstubs\\declarative_organizer.qtplugin\" - \"!:\\resource\\qt\\imports\\QtMobility\\organizer\\declarative_organizer.qtplugin\""
+ qmldirs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\organizer\\qmldir\" - \"!:\\resource\\qt\\imports\\QtMobility\\organizer\\qmldir\""
+ }
+ }
+
+ contains(mobility_modules, gallery) {
+ #QDocumentGallery on S60/Symbian relies on MetaDataSystem. There exists few different versions of it and we must
+ #check what version is currently installed on devices. Check is made a with known dlls.
+ #Installation has these preconditions:
+ # QDocumentGallery built against EPOCROOT50 has mds 2.0 libs in place (3.1/3.2/5.0)
+ # QDocumentGallery built against EPOCROOT51 has mds 2.5 libs in place (Symbian^3 and N97)
+ # QDocumentGallery built against EPOCROOT32 has no mds libs at all (stub implementation, api only)
+ # Also if checked mds library is present on c-drive then also check whether mds is installed
+ gallerymdscheck = \
+ "if exists(\"z:\sys\bin\locationutility.dll\")" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtGallery.dll\" - \"!:\\sys\\bin\\QtGallery.dll\"" \
+ "elseif exists(\"c:\sys\bin\locationutility.dll\") AND package(0x200009F5)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtGallery.dll\" - \"!:\\sys\\bin\\QtGallery.dll\"" \
+ "elseif exists(\"z:\sys\bin\locationmanagerserver.exe\")" \
+ " \"$${EPOCROOT51}epoc32/release/$(PLATFORM)/$(TARGET)/QtGallery.dll\" - \"!:\\sys\\bin\\QtGallery.dll\"" \
+ "elseif exists(\"c:\sys\bin\locationmanagerserver.exe\") AND package(0x200009F5)" \
+ " \"$${EPOCROOT51}epoc32/release/$(PLATFORM)/$(TARGET)/QtGallery.dll\" - \"!:\\sys\\bin\\QtGallery.dll\"" \
+ "else" \
+ " \"$${EPOCROOT32}epoc32/release/$(PLATFORM)/$(TARGET)/QtGallery.dll\" - \"!:\\sys\\bin\\QtGallery.dll\"" \
+ "endif"
+
+ qtmobilitydeployment.pkg_postrules += gallerymdscheck
+
+ # QDocumentGallery QML plugin
+ contains(QT_CONFIG, declarative): {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/declarative_gallery.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\gallery\\qmakepluginstubs\\declarative_gallery.qtplugin\" - \"!:\\resource\\qt\\imports\\QtMobility\\gallery\\declarative_gallery.qtplugin\""
+ qmldirs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\gallery\\qmldir\" - \"!:\\resource\\qt\\imports\\QtMobility\\gallery\\qmldir\""
+ }
+ }
+
+ contains(mobility_modules, bearer) {
+ bearer = \
+ "IF package(0x1028315F)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtBearer.dll\" - \"!:\\sys\\bin\\QtBearer.dll\"" \
+ "ELSEIF package(0x102752AE)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtBearer.dll\" - \"!:\\sys\\bin\\QtBearer.dll\"" \
+ "ELSEIF package(0x102032BE)" \
+ " \"$${EPOCROOT31}epoc32/release/$(PLATFORM)/$(TARGET)/QtBearer.dll\" - \"!:\\sys\\bin\\QtBearer.dll\"" \
+ "ELSE" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtBearer.dll\" - \"!:\\sys\\bin\\QtBearer.dll\"" \
+ "ENDIF"
+
+ qtmobilitydeployment.pkg_postrules += bearer
+ }
+
+ contains(mobility_modules, bearer) {
+ !contains(MOBILITY_SD_MCL_BUILD, yes):exists($${EPOCROOT}epoc32/release/winscw/udeb/z/system/install/series60v5.2.sis)|exists($${EPOCROOT}epoc32/data/z/system/install/series60v5.2.sis)|exists($${EPOCROOT}epoc32/release/armv5/lib/libstdcppv5.dso) {
+ bearer10_0 = \
+ "IF package(0x1028315F)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtBearer{000a0000}.dll\" - \"!:\\sys\\bin\\QtBearer{000a0000}.dll\"" \
+ "ELSEIF package(0x102752AE)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtBearer{000a0000}.dll\" - \"!:\\sys\\bin\\QtBearer{000a0000}.dll\"" \
+ "ELSEIF package(0x102032BE)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtBearer{000a0000}.dll\" - \"!:\\sys\\bin\\QtBearer{000a0000}.dll\"" \
+ "ELSE" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtBearer{000a0000}.dll\" - \"!:\\sys\\bin\\QtBearer{000a0000}.dll\"" \
+ "ENDIF"
+ qtmobilitydeployment.pkg_postrules += bearer10_0
+ }
+ }
+
+ contains(mobility_modules, contacts) {
+
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtContacts.dll
+ contains(mobility_modules,serviceframework):qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtcontacts_serviceactionmanager.dll
+
+ contacts = \
+ "IF package(0x1028315F)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtcontacts_symbian.dll\" - \"!:\\sys\\bin\\qtcontacts_symbian.dll\"" \
+ "ELSEIF package(0x102752AE)" \
+ " \"$${EPOCROOT32}epoc32/release/$(PLATFORM)/$(TARGET)/qtcontacts_symbian.dll\" - \"!:\\sys\\bin\\qtcontacts_symbian.dll\"" \
+ "ELSEIF package(0x102032BE)" \
+ " \"$${EPOCROOT31}epoc32/release/$(PLATFORM)/$(TARGET)/qtcontacts_symbian.dll\" - \"!:\\sys\\bin\\qtcontacts_symbian.dll\"" \
+ "ELSE" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtcontacts_symbian.dll\" - \"!:\\sys\\bin\\qtcontacts_symbian.dll\"" \
+ "ENDIF"
+
+ qtmobilitydeployment.pkg_postrules += contacts
+
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE/plugins/contacts/symbian/plugin/qmakepluginstubs/qtcontacts_symbian.qtplugin\" - \"!:\\resource\\qt\\plugins\\contacts\\qtcontacts_symbian.qtplugin\""
+ contains(mobility_modules,serviceframework):pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE/plugins/contacts/serviceactionmanager/qmakepluginstubs/qtcontacts_serviceactionmanager.qtplugin\" - \"!:\\resource\\qt\\plugins\\contacts\\qtcontacts_serviceactionmanager.qtplugin\""
+
+ contains(symbiancntsim_enabled, yes) {
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE/plugins/contacts/symbiansim/qmakepluginstubs/qtcontacts_symbiansim.qtplugin\" - \"!:\\resource\\qt\\plugins\\contacts\\qtcontacts_symbiansim.qtplugin\""
+
+ symbiancntsim = \
+ "IF package(0x1028315F)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtcontacts_symbiansim.dll\" - \"!:\\sys\\bin\\qtcontacts_symbiansim.dll\"" \
+ "ELSEIF package(0x102752AE)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtcontacts_symbiansim.dll\" - \"!:\\sys\\bin\\qtcontacts_symbiansim.dll\"" \
+ "ELSEIF package(0x102032BE)" \
+ " \"$${EPOCROOT31}epoc32/release/$(PLATFORM)/$(TARGET)/qtcontacts_symbiansim.dll\" - \"!:\\sys\\bin\\qtcontacts_symbiansim.dll\"" \
+ "ELSE" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtcontacts_symbiansim.dll\" - \"!:\\sys\\bin\\qtcontacts_symbiansim.dll\"" \
+ "ENDIF"
+
+ qtmobilitydeployment.pkg_postrules += symbiancntsim
+ }
+ contains(QT_CONFIG, declarative):contains(mobility_modules,versit) {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/declarative_contacts.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\contacts\\qmakepluginstubs\\declarative_contacts.qtplugin\" - \"!:\\resource\\qt\\imports\\QtMobility\\contacts\\declarative_contacts.qtplugin\""
+ qmldirs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\contacts\\qmldir\" - \"!:\\resource\\qt\\imports\\QtMobility\\contacts\\qmldir\""
+ }
+ }
+
+ contains(mobility_modules, multimedia) {
+
+ qtmobilitydeployment.sources += \
+ $$(EPOCROOT50)epoc32/release/$(PLATFORM)/$(TARGET)/QtMultimediaKit.dll \
+ $$(EPOCROOT50)epoc32/release/$(PLATFORM)/$(TARGET)/qtmultimediakit_m3u.dll
+
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE/plugins/multimedia/m3u/qmakepluginstubs/qtmultimediakit_m3u.qtplugin\" - \"!:\\resource\\qt\\plugins\\playlistformats\\qtmultimediakit_m3u.qtplugin\""
+
+ contains(openmaxal_symbian_enabled, yes) {
+ openmax = \
+ "\"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtmultimediakit_openmaxalengine.dll\" - \"!:\\sys\\bin\\qtmultimediakit_openmaxalengine.dll\""
+
+ qtmobilitydeployment.pkg_postrules += openmax
+
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE/plugins/multimedia/symbian/openmaxal/qmakepluginstubs/qtmultimediakit_openmaxalengine.qtplugin\" - \"!:\\resource\\qt\\plugins\\mediaservice\\qtmultimediakit_openmaxalengine.qtplugin\""
+ } else {
+
+ multimedia = \
+ "IF package(0x1028315F)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtmultimediakit_mmfengine.dll\" - \"!:\\sys\\bin\\qtmultimediakit_mmfengine.dll\"" \
+ "ELSEIF package(0x102752AE)" \
+ " \"$${EPOCROOT32}epoc32/release/$(PLATFORM)/$(TARGET)/qtmultimediakit_mmfengine.dll\" - \"!:\\sys\\bin\\qtmultimediakit_mmfengine.dll\"" \
+ "ELSEIF package(0x102032BE)" \
+ " \"$${EPOCROOT31}epoc32/release/$(PLATFORM)/$(TARGET)/qtmultimediakit_mmfengine.dll\" - \"!:\\sys\\bin\\qtmultimediakit_mmfengine.dll\"" \
+ "ELSEIF package(0x20022E6D)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtmultimediakit_mmfengine.dll\" - \"!:\\sys\\bin\\qtmultimediakit_mmfengine.dll\"" \
+ "ENDIF"
+
+ qtmobilitydeployment.pkg_postrules += multimedia
+
+ pluginstubs += \
+ "IF package(0x1028315F)" \
+ "\"$$QT_MOBILITY_BUILD_TREE/plugins/multimedia/symbian/mmf/qmakepluginstubs/qtmultimediakit_mmfengine.qtplugin\" - \"!:\\resource\\qt\\plugins\\mediaservice\\qtmultimediakit_mmfengine.qtplugin\"" \
+ "ELSEIF package(0x102752AE)" \
+ "\"$$QT_MOBILITY_BUILD_TREE/plugins/multimedia/symbian/mmf/qmakepluginstubs/qtmultimediakit_mmfengine.qtplugin\" - \"!:\\resource\\qt\\plugins\\mediaservice\\qtmultimediakit_mmfengine.qtplugin\"" \
+ "ELSEIF package(0x102032BE)" \
+ "\"$$QT_MOBILITY_BUILD_TREE/plugins/multimedia/symbian/mmf/qmakepluginstubs/qtmultimediakit_mmfengine.qtplugin\" - \"!:\\resource\\qt\\plugins\\mediaservice\\qtmultimediakit_mmfengine.qtplugin\"" \
+ "ELSEIF package(0x20022E6D)" \
+ "\"$$QT_MOBILITY_BUILD_TREE/plugins/multimedia/symbian/mmf/qmakepluginstubs/qtmultimediakit_mmfengine.qtplugin\" - \"!:\\resource\\qt\\plugins\\mediaservice\\qtmultimediakit_mmfengine.qtplugin\"" \
+ "ENDIF"
+ }
+
+ camera = \
+ "IF package(0x1028315F)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtmultimediakit_ecamengine.dll\" - \"!:\\sys\\bin\\qtmultimediakit_ecamengine.dll\"" \
+ "ELSEIF package(0x102752AE)" \
+ " \"$${EPOCROOT32}epoc32/release/$(PLATFORM)/$(TARGET)/qtmultimediakit_ecamengine.dll\" - \"!:\\sys\\bin\\qtmultimediakit_ecamengine.dll\"" \
+ "ELSEIF package(0x102032BE)" \
+ " \"$${EPOCROOT31}epoc32/release/$(PLATFORM)/$(TARGET)/qtmultimediakit_ecamengine.dll\" - \"!:\\sys\\bin\\qtmultimediakit_ecamengine.dll\"" \
+ "ELSEIF package(0x20022E6D)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtmultimediakit_ecamengine.dll\" - \"!:\\sys\\bin\\qtmultimediakit_ecamengine.dll\"" \
+ "ENDIF"
+
+ qtmobilitydeployment.pkg_postrules += camera
+
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE/plugins/multimedia/symbian/ecam/qmakepluginstubs/qtmultimediakit_ecamengine.qtplugin\" - \"!:\\resource\\qt\\plugins\\mediaservice\\qtmultimediakit_ecamengine.qtplugin\""
+
+
+ contains(QT_CONFIG, declarative): {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/declarative_multimedia.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\multimedia\\qmakepluginstubs\\declarative_multimedia.qtplugin\" - \"!:\\resource\\qt\\imports\\QtMultimediaKit\\declarative_multimedia.qtplugin\""
+ qmldirs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\multimedia\\qmldir\" - \"!:\\resource\\qt\\imports\\QtMultimediaKit\\qmldir\""
+ }
+ }
+
+ contains(mobility_modules, sensors) {
+
+ equals(sensors_symbian_enabled,yes) {
+ sensorplugin=symbian
+ } else:equals(sensors_s60_31_enabled,yes) {
+ sensorplugin=s60_sensor_api
+ } else {
+ error("Must have a Symbian sensor backend available")
+ }
+
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/QtSensors.dll
+
+ sensors = \
+ "IF package(0x1028315F)" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtsensors_sym.dll\" - \"!:\\sys\\bin\\qtsensors_sym.dll\"" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtsensors_generic.dll\" - \"!:\\sys\\bin\\qtsensors_generic.dll\"" \
+ "ELSEIF package(0x102752AE)" \
+ " \"$${EPOCROOT32}epoc32/release/$(PLATFORM)/$(TARGET)/qtsensors_sym.dll\" - \"!:\\sys\\bin\\qtsensors_sym.dll\"" \
+ " \"$${EPOCROOT32}epoc32/release/$(PLATFORM)/$(TARGET)/qtsensors_generic.dll\" - \"!:\\sys\\bin\\qtsensors_generic.dll\"" \
+ "ELSEIF package(0x102032BE)" \
+ " \"$${EPOCROOT31}epoc32/release/$(PLATFORM)/$(TARGET)/qtsensors_sym.dll\" - \"!:\\sys\\bin\\qtsensors_sym.dll\"" \
+ " \"$${EPOCROOT31}epoc32/release/$(PLATFORM)/$(TARGET)/qtsensors_generic.dll\" - \"!:\\sys\\bin\\qtsensors_generic.dll\"" \
+ "ELSE" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtsensors_sym.dll\" - \"!:\\sys\\bin\\qtsensors_sym.dll\"" \
+ " \"$${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/qtsensors_generic.dll\" - \"!:\\sys\\bin\\qtsensors_generic.dll\"" \
+ "ENDIF"
+
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE/plugins/sensors/$$sensorplugin/qmakepluginstubs/qtsensors_sym.qtplugin\" - \"!:\\resource\\qt\\plugins\\sensors\\qtsensors_sym.qtplugin\"" \
+ "\"$$QT_MOBILITY_BUILD_TREE/plugins/sensors/generic/qmakepluginstubs/qtsensors_generic.qtplugin\" - \"!:\\resource\\qt\\plugins\\sensors\\qtsensors_generic.qtplugin\""
+
+ !isEmpty(sensors):qtmobilitydeployment.pkg_postrules += sensors
+ contains(QT_CONFIG, declarative): {
+ qtmobilitydeployment.sources += \
+ $${EPOCROOT50}epoc32/release/$(PLATFORM)/$(TARGET)/declarative_sensors.dll
+ pluginstubs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\sensors\\qmakepluginstubs\\declarative_sensors.qtplugin\" - \"!:\\resource\\qt\\imports\\QtMobility\\sensors\\declarative_sensors.qtplugin\""
+ qmldirs += \
+ "\"$$QT_MOBILITY_BUILD_TREE\\plugins\\declarative\\sensors\\qmldir\" - \"!:\\resource\\qt\\imports\\QtMobility\\sensors\\qmldir\""
+ }
+ }
+
+ !isEmpty(pluginstubs):qtmobilitydeployment.pkg_postrules += pluginstubs
+ !isEmpty(qmldirs):qtmobilitydeployment.pkg_postrules += qmldirs
+
+ qtmobilitydeployment.path = /sys/bin
+
+ # Support backup and restore for QtMobility libraries and applications
+ mobilitybackup.sources = backup_registration.xml
+ mobilitybackup.path = c:/private/10202d56/import/packages/$$replace(TARGET.UID3, 0x,)
+
+ DEPLOYMENT += qtmobilitydeployment\
+ mobilitybackup
+} else {
+ message(Deployment of infixed library names not supported)
+}
diff --git a/src/src.pro b/src/src.pro
new file mode 100644
index 000000000..282c1b38a
--- /dev/null
+++ b/src/src.pro
@@ -0,0 +1,12 @@
+
+TEMPLATE = subdirs
+CONFIG += ordered
+
+SUBDIRS += multimediakit
+SUBDIRS += imports
+SUBDIRS += plugins
+
+symbian {
+ SUBDIRS += s60installs
+}
+
diff --git a/sync.profile b/sync.profile
new file mode 100644
index 000000000..a354c91df
--- /dev/null
+++ b/sync.profile
@@ -0,0 +1,35 @@
+%modules = ( # path to module name map
+ "QtMultimediaKit" => "$basedir/src/multimediakit",
+);
+
+%moduleheaders = ( # restrict the module headers to those found in relative path
+);
+
+%classnames = (
+ "qtmultimediakitversion.h" => "QtMultimediaKitVersion",
+);
+
+%mastercontent = (
+ "gui" => "#include <QtGui/QtGui>\n",
+ "network" => "#include <QtNetwork/QtNetwork>\n",
+ "core" => "#include <QtCore/QtCore>\n",
+);
+
+%modulepris = (
+ "QtMultimediaKit" => "$basedir/modules/qt_multimediakit.pri",
+);
+
+# Modules and programs, and their dependencies.
+# Each of the module version specifiers can take one of the following values:
+# - A specific Git revision.
+# - "LATEST_REVISION", to always test against the latest revision.
+# - "LATEST_RELEASE", to always test against the latest public release.
+# - "THIS_REPOSITORY", to indicate that the module is in this repository.
+%dependencies = (
+ "QtMultimediaKit" => {
+ "QtGui" => "0c637cb07ba3c9b353e7e483a209537485cc4e2a",
+ "QtNetwork" => "0c637cb07ba3c9b353e7e483a209537485cc4e2a",
+ "QtCore" => "0c637cb07ba3c9b353e7e483a209537485cc4e2a",
+ },
+);
+
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
new file mode 100644
index 000000000..b3a5771a2
--- /dev/null
+++ b/tests/auto/auto.pro
@@ -0,0 +1,11 @@
+TEMPLATE = subdirs
+
+SUBDIRS+=multimedia.pro
+
+# These autotests consist of things such as static code checks
+# which require that the autotest is run on the same machine
+# doing the build - i.e. cross-compilation is not allowed.
+win32|mac|linux-g++* {
+ # NOTE: Disabled until we have established which tests fall into this category
+ # !contains(QT_CONFIG,embedded):!maemo5:!maemo6:SUBDIRS+=host.pro
+}
diff --git a/tests/auto/multimedia.pro b/tests/auto/multimedia.pro
new file mode 100644
index 000000000..cb6094388
--- /dev/null
+++ b/tests/auto/multimedia.pro
@@ -0,0 +1,41 @@
+# How do we require a module?
+# requires(contains(mobility_modules,multimedia))
+
+TEMPLATE = subdirs
+SUBDIRS += \
+ qabstractvideobuffer \
+ qabstractvideosurface \
+ qaudiocapturesource \
+ qgraphicsvideoitem \
+ qmediaimageviewer \
+ qmediaobject \
+ qmediaplayer \
+ qmediaplayerbackend \
+ qmediaplaylist \
+ qmediaplaylistnavigator \
+ qmediapluginloader \
+ qmediarecorder \
+ qmediaresource \
+ qmediaservice \
+ qmediaserviceprovider \
+ qmediacontent \
+ qradiotuner \
+ qcamera \
+ qpaintervideosurface \
+ qvideowidget \
+ qmediatimerange \
+ qaudiodeviceinfo \
+ qaudiooutput \
+ qaudioinput \
+ qaudioformat \
+ qvideoframe \
+ qvideosurfaceformat \
+ qcamerabackend
+
+contains (QT_CONFIG, declarative) {
+ SUBDIRS += \
+# qsoundeffect \
+ qdeclarativeaudio \
+ qdeclarativevideo
+}
+
diff --git a/tests/auto/qabstractvideobuffer/qabstractvideobuffer.pro b/tests/auto/qabstractvideobuffer/qabstractvideobuffer.pro
new file mode 100644
index 000000000..e1fa50355
--- /dev/null
+++ b/tests/auto/qabstractvideobuffer/qabstractvideobuffer.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += core multimediakit-private
+
+# TARGET = tst_qabstractvideobuffer
+#CONFIG += testcase
+
+SOURCES += tst_qabstractvideobuffer.cpp
+
diff --git a/tests/auto/qabstractvideobuffer/tst_qabstractvideobuffer.cpp b/tests/auto/qabstractvideobuffer/tst_qabstractvideobuffer.cpp
new file mode 100644
index 000000000..7e339eefb
--- /dev/null
+++ b/tests/auto/qabstractvideobuffer/tst_qabstractvideobuffer.cpp
@@ -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 test suite 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <QtTest/QtTest>
+
+#include <qabstractvideobuffer.h>
+
+class tst_QAbstractVideoBuffer : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QAbstractVideoBuffer();
+ ~tst_QAbstractVideoBuffer();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void handleType_data();
+ void handleType();
+ void handle();
+};
+
+class QtTestVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ QtTestVideoBuffer(QAbstractVideoBuffer::HandleType type) : QAbstractVideoBuffer(type) {}
+
+ MapMode mapMode() const { return NotMapped; }
+
+ uchar *map(MapMode, int *, int *) { return 0; }
+ void unmap() {}
+};
+
+tst_QAbstractVideoBuffer::tst_QAbstractVideoBuffer()
+{
+}
+
+tst_QAbstractVideoBuffer::~tst_QAbstractVideoBuffer()
+{
+}
+
+void tst_QAbstractVideoBuffer::initTestCase()
+{
+}
+
+void tst_QAbstractVideoBuffer::cleanupTestCase()
+{
+}
+
+void tst_QAbstractVideoBuffer::init()
+{
+}
+
+void tst_QAbstractVideoBuffer::cleanup()
+{
+}
+
+void tst_QAbstractVideoBuffer::handleType_data()
+{
+ QTest::addColumn<QAbstractVideoBuffer::HandleType>("type");
+
+ QTest::newRow("none")
+ << QAbstractVideoBuffer::NoHandle;
+ QTest::newRow("opengl")
+ << QAbstractVideoBuffer::GLTextureHandle;
+ QTest::newRow("user1")
+ << QAbstractVideoBuffer::UserHandle;
+ QTest::newRow("user2")
+ << QAbstractVideoBuffer::HandleType(QAbstractVideoBuffer::UserHandle + 1);
+}
+
+void tst_QAbstractVideoBuffer::handleType()
+{
+ QFETCH(QAbstractVideoBuffer::HandleType, type);
+
+ QtTestVideoBuffer buffer(type);
+
+ QCOMPARE(buffer.handleType(), type);
+}
+
+void tst_QAbstractVideoBuffer::handle()
+{
+ QtTestVideoBuffer buffer(QAbstractVideoBuffer::NoHandle);
+
+ QVERIFY(buffer.handle().isNull());
+}
+
+QTEST_MAIN(tst_QAbstractVideoBuffer)
+
+#include "tst_qabstractvideobuffer.moc"
diff --git a/tests/auto/qabstractvideosurface/qabstractvideosurface.pro b/tests/auto/qabstractvideosurface/qabstractvideosurface.pro
new file mode 100644
index 000000000..1778b566b
--- /dev/null
+++ b/tests/auto/qabstractvideosurface/qabstractvideosurface.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += core multimediakit-private
+
+# TARGET = tst_qabstractvideosurface
+#CONFIG += testcase
+
+SOURCES += tst_qabstractvideosurface.cpp
+
diff --git a/tests/auto/qabstractvideosurface/tst_qabstractvideosurface.cpp b/tests/auto/qabstractvideosurface/tst_qabstractvideosurface.cpp
new file mode 100644
index 000000000..bef9c7f38
--- /dev/null
+++ b/tests/auto/qabstractvideosurface/tst_qabstractvideosurface.cpp
@@ -0,0 +1,312 @@
+/****************************************************************************
+**
+** 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 test suite 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <QtTest/QtTest>
+
+#include <qabstractvideosurface.h>
+#include <qvideosurfaceformat.h>
+
+class tst_QAbstractVideoSurface : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QAbstractVideoSurface();
+ ~tst_QAbstractVideoSurface();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void setError();
+ void isFormatSupported_data();
+ void isFormatSupported();
+ void nearestFormat_data();
+ void nearestFormat();
+ void start_data();
+ void start();
+};
+
+typedef QMap<QAbstractVideoBuffer::HandleType, QVideoFrame::PixelFormat> SupportedFormatMap;
+
+Q_DECLARE_METATYPE(SupportedFormatMap)
+Q_DECLARE_METATYPE(QVideoSurfaceFormat)
+Q_DECLARE_METATYPE(QAbstractVideoSurface::Error);
+
+class QtTestVideoSurface : public QAbstractVideoSurface
+{
+ Q_OBJECT
+public:
+ explicit QtTestVideoSurface(QObject *parent = 0) : QAbstractVideoSurface(parent) {}
+ explicit QtTestVideoSurface(SupportedFormatMap formats, QObject *parent = 0)
+ : QAbstractVideoSurface(parent), supportedFormats(formats) {}
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const
+ {
+ return supportedFormats.values(handleType);
+ }
+
+ bool present(const QVideoFrame &) { return false; }
+
+ using QAbstractVideoSurface::setError;
+
+private:
+ SupportedFormatMap supportedFormats;
+};
+
+tst_QAbstractVideoSurface::tst_QAbstractVideoSurface()
+{
+}
+
+tst_QAbstractVideoSurface::~tst_QAbstractVideoSurface()
+{
+}
+
+void tst_QAbstractVideoSurface::initTestCase()
+{
+}
+
+void tst_QAbstractVideoSurface::cleanupTestCase()
+{
+}
+
+void tst_QAbstractVideoSurface::init()
+{
+}
+
+void tst_QAbstractVideoSurface::cleanup()
+{
+}
+
+void tst_QAbstractVideoSurface::setError()
+{
+ qRegisterMetaType<QAbstractVideoSurface::Error>();
+
+ QtTestVideoSurface surface;
+
+ QCOMPARE(surface.error(), QAbstractVideoSurface::NoError);
+
+ surface.setError(QAbstractVideoSurface::StoppedError);
+ QCOMPARE(surface.error(), QAbstractVideoSurface::StoppedError);
+
+ surface.setError(QAbstractVideoSurface::ResourceError);
+ QCOMPARE(surface.error(), QAbstractVideoSurface::ResourceError);
+
+ surface.setError(QAbstractVideoSurface::NoError);
+ QCOMPARE(surface.error(), QAbstractVideoSurface::NoError);
+}
+
+void tst_QAbstractVideoSurface::isFormatSupported_data()
+{
+ QTest::addColumn<SupportedFormatMap>("supportedFormats");
+ QTest::addColumn<QVideoSurfaceFormat>("format");
+ QTest::addColumn<bool>("supported");
+
+ SupportedFormatMap formats;
+
+ QTest::newRow("no formats: rgb32")
+ << formats
+ << QVideoSurfaceFormat(QSize(800, 600), QVideoFrame::Format_RGB32)
+ << false;
+ QTest::newRow("no formats: yv12")
+ << formats
+ << QVideoSurfaceFormat(QSize(800, 600), QVideoFrame::Format_YV12)
+ << false;
+ QTest::newRow("no formats: rgb32 gl")
+ << formats
+ << QVideoSurfaceFormat(
+ QSize(800, 600),
+ QVideoFrame::Format_RGB32,
+ QAbstractVideoBuffer::GLTextureHandle)
+ << false;
+ QTest::newRow("no formats: rgb24 gl")
+ << formats
+ << QVideoSurfaceFormat(
+ QSize(800, 600),
+ QVideoFrame::Format_RGB24,
+ QAbstractVideoBuffer::GLTextureHandle)
+ << false;
+
+ formats.insertMulti(QAbstractVideoBuffer::NoHandle, QVideoFrame::Format_RGB32);
+ formats.insertMulti(QAbstractVideoBuffer::NoHandle, QVideoFrame::Format_RGB24);
+ formats.insertMulti(QAbstractVideoBuffer::NoHandle, QVideoFrame::Format_YUV444);
+ formats.insertMulti(QAbstractVideoBuffer::GLTextureHandle, QVideoFrame::Format_RGB32);
+
+ QTest::newRow("supported: rgb32")
+ << formats
+ << QVideoSurfaceFormat(QSize(800, 600), QVideoFrame::Format_RGB32)
+ << true;
+ QTest::newRow("supported: rgb24")
+ << formats
+ << QVideoSurfaceFormat(QSize(800, 600), QVideoFrame::Format_RGB24)
+ << true;
+ QTest::newRow("unsupported: yv12")
+ << formats
+ << QVideoSurfaceFormat(QSize(800, 600), QVideoFrame::Format_YV12)
+ << false;
+ QTest::newRow("supported: rgb32 gl")
+ << formats
+ << QVideoSurfaceFormat(
+ QSize(800, 600),
+ QVideoFrame::Format_RGB32,
+ QAbstractVideoBuffer::GLTextureHandle)
+ << true;
+ QTest::newRow("unsupported: rgb24 gl")
+ << formats
+ << QVideoSurfaceFormat(
+ QSize(800, 600),
+ QVideoFrame::Format_RGB24,
+ QAbstractVideoBuffer::GLTextureHandle)
+ << false;
+ QTest::newRow("unsupported: yv12 gl")
+ << formats
+ << QVideoSurfaceFormat(
+ QSize(800, 600),
+ QVideoFrame::Format_YV12,
+ QAbstractVideoBuffer::GLTextureHandle)
+ << false;
+
+ formats.insertMulti(QAbstractVideoBuffer::NoHandle, QVideoFrame::Format_YV12);
+ formats.insertMulti(QAbstractVideoBuffer::GLTextureHandle, QVideoFrame::Format_RGB24);
+
+ QTest::newRow("supported: yv12")
+ << formats
+ << QVideoSurfaceFormat(QSize(800, 600), QVideoFrame::Format_YV12)
+ << true;
+ QTest::newRow("supported: rgb24 gl")
+ << formats
+ << QVideoSurfaceFormat(
+ QSize(800, 600),
+ QVideoFrame::Format_RGB24,
+ QAbstractVideoBuffer::GLTextureHandle)
+ << true;
+}
+
+void tst_QAbstractVideoSurface::isFormatSupported()
+{
+ QFETCH(SupportedFormatMap, supportedFormats);
+ QFETCH(QVideoSurfaceFormat, format);
+ QFETCH(bool, supported);
+
+ QtTestVideoSurface surface(supportedFormats);
+
+ QCOMPARE(surface.isFormatSupported(format), supported);
+}
+
+void tst_QAbstractVideoSurface::nearestFormat_data()
+{
+ isFormatSupported_data();
+}
+
+void tst_QAbstractVideoSurface::nearestFormat()
+{
+ QFETCH(SupportedFormatMap, supportedFormats);
+ QFETCH(QVideoSurfaceFormat, format);
+ QFETCH(bool, supported);
+
+ QtTestVideoSurface surface(supportedFormats);
+
+ QCOMPARE(surface.nearestFormat(format) == format, supported);
+}
+
+void tst_QAbstractVideoSurface::start_data()
+{
+ QTest::addColumn<QVideoSurfaceFormat>("format");
+
+ QTest::newRow("rgb32") << QVideoSurfaceFormat(
+ QSize(800, 600),
+ QVideoFrame::Format_RGB32);
+ QTest::newRow("yv12") << QVideoSurfaceFormat(
+ QSize(800, 600),
+ QVideoFrame::Format_YV12);
+ QTest::newRow("rgb32 gl") << QVideoSurfaceFormat(
+ QSize(800, 600),
+ QVideoFrame::Format_RGB32,
+ QAbstractVideoBuffer::GLTextureHandle);
+}
+
+void tst_QAbstractVideoSurface::start()
+{
+ QFETCH(QVideoSurfaceFormat, format);
+
+ QtTestVideoSurface surface;
+ surface.setError(QAbstractVideoSurface::ResourceError);
+
+ QSignalSpy formatSpy(&surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)));
+ QSignalSpy activeSpy(&surface, SIGNAL(activeChanged(bool)));
+
+ QVERIFY(!surface.isActive());
+ QCOMPARE(surface.surfaceFormat(), QVideoSurfaceFormat());
+
+ QVERIFY(surface.start(format));
+
+ QVERIFY(surface.isActive());
+ QCOMPARE(surface.surfaceFormat(), format);
+
+ QCOMPARE(formatSpy.count(), 1);
+ QCOMPARE(qvariant_cast<QVideoSurfaceFormat>(formatSpy.last().at(0)), format);
+
+ QCOMPARE(activeSpy.count(), 1);
+ QCOMPARE(activeSpy.last().at(0).toBool(), true);
+
+ // error() is reset on a successful start.
+ QCOMPARE(surface.error(), QAbstractVideoSurface::NoError);
+
+ surface.stop();
+
+ QVERIFY(!surface.isActive());
+ QCOMPARE(surface.surfaceFormat(), QVideoSurfaceFormat());
+
+ QCOMPARE(formatSpy.count(), 2);
+ QCOMPARE(qvariant_cast<QVideoSurfaceFormat>(formatSpy.last().at(0)), QVideoSurfaceFormat());
+
+ QCOMPARE(activeSpy.count(), 2);
+ QCOMPARE(activeSpy.last().at(0).toBool(), false);
+}
+
+QTEST_MAIN(tst_QAbstractVideoSurface)
+
+#include "tst_qabstractvideosurface.moc"
diff --git a/tests/auto/qaudiocapturesource/qaudiocapturesource.pro b/tests/auto/qaudiocapturesource/qaudiocapturesource.pro
new file mode 100644
index 000000000..df9c70eaf
--- /dev/null
+++ b/tests/auto/qaudiocapturesource/qaudiocapturesource.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qaudiocapturesource
+# CONFIG += testcase
+
+SOURCES += tst_qaudiocapturesource.cpp
+
diff --git a/tests/auto/qaudiocapturesource/tst_qaudiocapturesource.cpp b/tests/auto/qaudiocapturesource/tst_qaudiocapturesource.cpp
new file mode 100644
index 000000000..c8d9d3d7d
--- /dev/null
+++ b/tests/auto/qaudiocapturesource/tst_qaudiocapturesource.cpp
@@ -0,0 +1,360 @@
+/****************************************************************************
+**
+** 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 <QtTest/QtTest>
+#include <QDebug>
+
+#include <qaudioformat.h>
+
+#include <qaudiocapturesource.h>
+#include <qaudioencodercontrol.h>
+#include <qmediarecordercontrol.h>
+#include <qaudioendpointselector.h>
+
+//TESTED_COMPONENT=src/multimedia
+
+QT_USE_NAMESPACE
+class MockAudioEncoderControl : public QAudioEncoderControl
+{
+ Q_OBJECT
+public:
+ MockAudioEncoderControl(QObject *parent = 0):
+ QAudioEncoderControl(parent)
+ {
+ m_codecs << "audio/pcm" << "audio/mpeg";
+ m_descriptions << "Pulse Code Modulation" << "mp3 format";
+ m_audioSettings.setCodec("audio/pcm");
+ m_audioSettings.setSampleRate(8000);
+ m_freqs << 8000 << 11025 << 22050 << 44100;
+ }
+
+ ~MockAudioEncoderControl() {}
+
+ QStringList supportedAudioCodecs() const { return m_codecs; }
+ QString codecDescription(const QString &codecName) const { return m_descriptions.at(m_codecs.indexOf(codecName)); }
+
+ QStringList supportedEncodingOptions(const QString &) const { return QStringList() << "bitrate"; }
+ QVariant encodingOption(const QString &, const QString &) const { return m_optionValue; }
+ void setEncodingOption(const QString &, const QString &, const QVariant &value) { m_optionValue = value; }
+
+ QList<int> supportedSampleRates(const QAudioEncoderSettings & = QAudioEncoderSettings(),
+ bool *continuous = 0) const
+ {
+ if (continuous)
+ *continuous = false;
+ return m_freqs;
+ }
+ QList<int> supportedChannelCounts(const QAudioEncoderSettings & = QAudioEncoderSettings()) const { QList<int> list; list << 1 << 2; return list; }
+
+ QAudioEncoderSettings audioSettings() const { return m_audioSettings; }
+ void setAudioSettings(const QAudioEncoderSettings &settings) { m_audioSettings = settings;}
+
+ QStringList m_codecs;
+ QStringList m_descriptions;
+
+ QAudioEncoderSettings m_audioSettings;
+
+ QList<int> m_freqs;
+ QVariant m_optionValue;
+};
+
+class MockMediaRecorderControl : public QMediaRecorderControl
+{
+ Q_OBJECT
+public:
+ MockMediaRecorderControl(QObject *parent = 0):
+ QMediaRecorderControl(parent),
+ m_state(QMediaRecorder::StoppedState),
+ m_position(0),
+ m_muted(false) {}
+
+ ~MockMediaRecorderControl() {}
+
+ QUrl outputLocation() const { return m_sink; }
+ bool setOutputLocation(const QUrl &sink) { m_sink = sink; return true; }
+ QMediaRecorder::State state() const { return m_state; }
+ qint64 duration() const { return m_position; }
+ void applySettings() {}
+ bool isMuted() const { return m_muted; }
+
+public slots:
+ void record()
+ {
+ m_state = QMediaRecorder::RecordingState;
+ m_position=1;
+ emit stateChanged(m_state);
+ emit durationChanged(m_position);
+ }
+ void pause()
+ {
+ m_state = QMediaRecorder::PausedState;
+ emit stateChanged(m_state);
+ }
+
+ void stop()
+ {
+ m_position=0;
+ m_state = QMediaRecorder::StoppedState;
+ emit stateChanged(m_state);
+ }
+
+ void setMuted(bool muted)
+ {
+ if (m_muted != muted)
+ emit mutedChanged(m_muted = muted);
+ }
+
+public:
+ QUrl m_sink;
+ QMediaRecorder::State m_state;
+ qint64 m_position;
+ bool m_muted;
+};
+
+class MockAudioEndpointSelector : public QAudioEndpointSelector
+{
+ Q_OBJECT
+public:
+ MockAudioEndpointSelector(QObject *parent):
+ QAudioEndpointSelector(parent)
+ {
+ m_names << "device1" << "device2" << "device3";
+ m_descriptions << "dev1 comment" << "dev2 comment" << "dev3 comment";
+ m_audioInput = "device1";
+ emit availableEndpointsChanged();
+ }
+ ~MockAudioEndpointSelector() {};
+
+ QList<QString> availableEndpoints() const
+ {
+ return m_names;
+ }
+
+ QString endpointDescription(const QString& name) const
+ {
+ QString desc;
+
+ for(int i = 0; i < m_names.count(); i++) {
+ if (m_names.at(i).compare(name) == 0) {
+ desc = m_descriptions.at(i);
+ break;
+ }
+ }
+ return desc;
+ }
+
+ QString defaultEndpoint() const
+ {
+ return m_names.at(0);
+ }
+
+ QString activeEndpoint() const
+ {
+ return m_audioInput;
+ }
+
+public Q_SLOTS:
+ void setActiveEndpoint(const QString& name)
+ {
+ m_audioInput = name;
+ emit activeEndpointChanged(name);
+ }
+
+private:
+ QString m_audioInput;
+ QList<QString> m_names;
+ QList<QString> m_descriptions;
+};
+
+
+class MockAudioSourceService : public QMediaService
+{
+ Q_OBJECT
+
+public:
+ MockAudioSourceService(): QMediaService(0), hasAudioDeviceControl(true)
+ {
+ mockAudioEncoderControl = new MockAudioEncoderControl(this);
+ mockMediaRecorderControl = new MockMediaRecorderControl(this);
+ mockAudioEndpointSelector = new MockAudioEndpointSelector(this);
+ }
+
+ ~MockAudioSourceService()
+ {
+ delete mockAudioEncoderControl;
+ delete mockMediaRecorderControl;
+ delete mockAudioEndpointSelector;
+ }
+
+ QMediaControl* requestControl(const char *iid)
+ {
+ if (qstrcmp(iid, QAudioEncoderControl_iid) == 0)
+ return mockAudioEncoderControl;
+
+ if (qstrcmp(iid, QMediaRecorderControl_iid) == 0)
+ return mockMediaRecorderControl;
+
+ if (hasAudioDeviceControl && qstrcmp(iid, QAudioEndpointSelector_iid) == 0)
+ return mockAudioEndpointSelector;
+
+ return 0;
+ }
+
+ void releaseControl(QMediaControl*) {}
+
+ MockAudioEncoderControl *mockAudioEncoderControl;
+ MockMediaRecorderControl *mockMediaRecorderControl;
+ MockAudioEndpointSelector *mockAudioEndpointSelector;
+ bool hasAudioDeviceControl;
+};
+
+class MockProvider : public QMediaServiceProvider
+{
+public:
+ MockProvider(MockAudioSourceService *service):mockService(service) {}
+ QMediaService *requestService(const QByteArray&, const QMediaServiceProviderHint &)
+ {
+ return mockService;
+ }
+
+ void releaseService(QMediaService *) {}
+
+ MockAudioSourceService *mockService;
+};
+
+
+class tst_QAudioCaptureSource: public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ //void testNullService();
+ //void testNullControl();
+ void testAudioSource();
+ void testOptions();
+ void testDevices();
+
+private:
+ QAudioCaptureSource *audiosource;
+ MockAudioSourceService *mockAudioSourceService;
+ MockProvider *mockProvider;
+};
+
+void tst_QAudioCaptureSource::initTestCase()
+{
+ mockAudioSourceService = new MockAudioSourceService;
+ mockProvider = new MockProvider(mockAudioSourceService);
+}
+
+void tst_QAudioCaptureSource::cleanupTestCase()
+{
+ delete audiosource;
+ delete mockProvider;
+}
+/*
+void tst_QAudioCaptureSource::testNullService()
+{
+ MockProvider provider(0);
+ QAudioCaptureSource source(0, &provider);
+
+ QCOMPARE(source.audioInputs().size(), 0);
+ QCOMPARE(source.defaultAudioInput(), QString());
+ QCOMPARE(source.activeAudioInput(), QString());
+}
+*/
+/*
+void tst_QAudioCaptureSource::testNullControl()
+{
+ MockAudioSourceService service;
+ service.hasAudioDeviceControl = false;
+ MockProvider provider(&service);
+ QAudioCaptureSource source(0, &provider);
+
+ QCOMPARE(source.audioInputs().size(), 0);
+ QCOMPARE(source.defaultAudioInput(), QString());
+ QCOMPARE(source.activeAudioInput(), QString());
+
+ QCOMPARE(source.audioDescription("blah"), QString());
+
+ QSignalSpy deviceNameSpy(&source, SIGNAL(activeAudioInputChanged(QString)));
+
+ source.setAudioInput("blah");
+ QCOMPARE(deviceNameSpy.count(), 0);
+}
+*/
+void tst_QAudioCaptureSource::testAudioSource()
+{
+ audiosource = new QAudioCaptureSource(0, mockProvider);
+
+ QCOMPARE(audiosource->service(),(QMediaService *) mockAudioSourceService);
+}
+
+void tst_QAudioCaptureSource::testOptions()
+{
+ const QString codec(QLatin1String("mp3"));
+
+ QStringList options = mockAudioSourceService->mockAudioEncoderControl->supportedEncodingOptions(codec);
+ QVERIFY(options.count() == 1);
+ mockAudioSourceService->mockAudioEncoderControl->setEncodingOption(codec, options.first(),8000);
+ QVERIFY(mockAudioSourceService->mockAudioEncoderControl->encodingOption(codec, options.first()).toInt() == 8000);
+}
+
+void tst_QAudioCaptureSource::testDevices()
+{
+ QList<QString> devices = audiosource->audioInputs();
+ QVERIFY(devices.size() > 0);
+ QVERIFY(devices.at(0).compare("device1") == 0);
+ QVERIFY(audiosource->audioDescription("device1").compare("dev1 comment") == 0);
+ QVERIFY(audiosource->defaultAudioInput() == "device1");
+
+ QSignalSpy checkSignal(audiosource, SIGNAL(activeAudioInputChanged(QString)));
+ audiosource->setAudioInput("device2");
+ QVERIFY(audiosource->activeAudioInput().compare("device2") == 0);
+ QVERIFY(checkSignal.count() == 1);
+}
+
+QTEST_MAIN(tst_QAudioCaptureSource)
+
+#include "tst_qaudiocapturesource.moc"
diff --git a/tests/auto/qaudiodeviceinfo/qaudiodeviceinfo.pro b/tests/auto/qaudiodeviceinfo/qaudiodeviceinfo.pro
new file mode 100644
index 000000000..1b2452419
--- /dev/null
+++ b/tests/auto/qaudiodeviceinfo/qaudiodeviceinfo.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += core multimediakit-private
+
+# TARGET = tst_qaudiodeviceinfo
+# CONFIG += testcase
+
+SOURCES += tst_qaudiodeviceinfo.cpp
+
diff --git a/tests/auto/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp b/tests/auto/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp
new file mode 100644
index 000000000..29225bc62
--- /dev/null
+++ b/tests/auto/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** 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 test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtCore/qlocale.h>
+#include <qaudiodeviceinfo.h>
+
+#include <QStringList>
+#include <QList>
+
+//TESTED_COMPONENT=src/multimedia
+
+class tst_QAudioDeviceInfo : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QAudioDeviceInfo(QObject* parent=0) : QObject(parent) {}
+
+private slots:
+ void initTestCase();
+ void checkAvailableDefaultInput();
+ void checkAvailableDefaultOutput();
+ void outputList();
+ void codecs();
+ void channels();
+ void sampleSizes();
+ void byteOrders();
+ void sampleTypes();
+ void frequencies();
+ void isformat();
+ void preferred();
+ void nearest();
+
+private:
+ bool available;
+ QAudioDeviceInfo* device;
+};
+
+void tst_QAudioDeviceInfo::initTestCase()
+{
+ // Only perform tests if audio output device exists!
+ QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
+ if(devices.size() > 0)
+ available = true;
+ else {
+ qWarning()<<"NOTE: no audio output device found, no test will be performed";
+ available = false;
+ }
+}
+
+void tst_QAudioDeviceInfo::checkAvailableDefaultInput()
+{
+ // Only perform tests if audio input device exists!
+ bool storeAvailable = available;
+ QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
+ if(devices.size() > 0)
+ available = true;
+ else {
+ qWarning()<<"NOTE: no audio input device found, no test will be performed";
+ available = false;
+ }
+ if(available)
+ QVERIFY(!QAudioDeviceInfo::defaultInputDevice().isNull());
+ available = storeAvailable;
+}
+
+void tst_QAudioDeviceInfo::checkAvailableDefaultOutput()
+{
+ if(available)
+ QVERIFY(!QAudioDeviceInfo::defaultOutputDevice().isNull());
+}
+
+void tst_QAudioDeviceInfo::outputList()
+{
+ if(available) {
+ QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
+ QVERIFY(devices.size() > 0);
+ device = new QAudioDeviceInfo(devices.at(0));
+ }
+}
+
+void tst_QAudioDeviceInfo::codecs()
+{
+ if(available) {
+ QStringList avail = device->supportedCodecs();
+ QVERIFY(avail.size() > 0);
+ }
+}
+
+void tst_QAudioDeviceInfo::channels()
+{
+ if(available) {
+ QList<int> avail = device->supportedChannels();
+ QVERIFY(avail.size() > 0);
+ }
+}
+
+void tst_QAudioDeviceInfo::sampleSizes()
+{
+ if(available) {
+ QList<int> avail = device->supportedSampleSizes();
+ QVERIFY(avail.size() > 0);
+ }
+}
+
+void tst_QAudioDeviceInfo::byteOrders()
+{
+ if(available) {
+ QList<QAudioFormat::Endian> avail = device->supportedByteOrders();
+ QVERIFY(avail.size() > 0);
+ }
+}
+
+void tst_QAudioDeviceInfo::sampleTypes()
+{
+ if(available) {
+ QList<QAudioFormat::SampleType> avail = device->supportedSampleTypes();
+ QVERIFY(avail.size() > 0);
+ }
+}
+
+void tst_QAudioDeviceInfo::frequencies()
+{
+ if(available) {
+ QList<int> avail = device->supportedFrequencies();
+ QVERIFY(avail.size() > 0);
+ }
+}
+
+void tst_QAudioDeviceInfo::isformat()
+{
+ if(available) {
+ QAudioFormat format;
+ format.setFrequency(44100);
+ format.setChannels(2);
+ format.setSampleType(QAudioFormat::SignedInt);
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleSize(16);
+ format.setCodec("audio/pcm");
+
+ // Should always be true for these format
+ QVERIFY(device->isFormatSupported(format));
+ }
+}
+
+void tst_QAudioDeviceInfo::preferred()
+{
+ if(available) {
+ QAudioFormat format = device->preferredFormat();
+ QVERIFY(format.isValid());
+ }
+}
+
+void tst_QAudioDeviceInfo::nearest()
+{
+ if(available) {
+ /*
+ QAudioFormat format1, format2;
+ format1.setFrequency(8000);
+ format2 = device->nearestFormat(format1);
+ QVERIFY(format2.frequency() == 44100);
+ */
+ }
+}
+
+QTEST_MAIN(tst_QAudioDeviceInfo)
+
+#include "tst_qaudiodeviceinfo.moc"
diff --git a/tests/auto/qaudioformat/qaudioformat.pro b/tests/auto/qaudioformat/qaudioformat.pro
new file mode 100644
index 000000000..568cad09a
--- /dev/null
+++ b/tests/auto/qaudioformat/qaudioformat.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += core multimediakit-private
+
+# TARGET = tst_qaudioformat
+# CONFIG += testcase
+
+SOURCES += tst_qaudioformat.cpp
+
diff --git a/tests/auto/qaudioformat/tst_qaudioformat.cpp b/tests/auto/qaudioformat/tst_qaudioformat.cpp
new file mode 100644
index 000000000..d543708ae
--- /dev/null
+++ b/tests/auto/qaudioformat/tst_qaudioformat.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** 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 test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtCore/qlocale.h>
+#include <qaudioformat.h>
+
+#include <QStringList>
+#include <QList>
+
+//TESTED_COMPONENT=src/multimedia
+
+class tst_QAudioFormat : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QAudioFormat(QObject* parent=0) : QObject(parent) {}
+
+private slots:
+ void checkNull();
+ void checkFrequency();
+ void checkChannels();
+ void checkSampleSize();
+ void checkCodec();
+ void checkByteOrder();
+ void checkSampleType();
+ void checkEquality();
+ void checkAssignment();
+};
+
+void tst_QAudioFormat::checkNull()
+{
+ // Default constructed QAudioFormat is invalid.
+ QAudioFormat audioFormat0;
+ QVERIFY(!audioFormat0.isValid());
+
+ // validity is transferred
+ QAudioFormat audioFormat1(audioFormat0);
+ QVERIFY(!audioFormat1.isValid());
+
+ audioFormat0.setFrequency(44100);
+ audioFormat0.setChannels(2);
+ audioFormat0.setSampleSize(16);
+ audioFormat0.setCodec("audio/pcm");
+ audioFormat0.setSampleType(QAudioFormat::SignedInt);
+ QVERIFY(audioFormat0.isValid());
+}
+
+void tst_QAudioFormat::checkFrequency()
+{
+ QAudioFormat audioFormat;
+ audioFormat.setFrequency(44100);
+ QVERIFY(audioFormat.frequency() == 44100);
+}
+
+void tst_QAudioFormat::checkChannels()
+{
+ QAudioFormat audioFormat;
+ audioFormat.setChannels(2);
+ QVERIFY(audioFormat.channels() == 2);
+}
+
+void tst_QAudioFormat::checkSampleSize()
+{
+ QAudioFormat audioFormat;
+ audioFormat.setSampleSize(16);
+ QVERIFY(audioFormat.sampleSize() == 16);
+}
+
+void tst_QAudioFormat::checkCodec()
+{
+ QAudioFormat audioFormat;
+ audioFormat.setCodec(QString::fromLatin1("audio/pcm"));
+ QVERIFY(audioFormat.codec() == QString::fromLatin1("audio/pcm"));
+}
+
+void tst_QAudioFormat::checkByteOrder()
+{
+ QAudioFormat audioFormat;
+ audioFormat.setByteOrder(QAudioFormat::LittleEndian);
+ QVERIFY(audioFormat.byteOrder() == QAudioFormat::LittleEndian);
+}
+
+void tst_QAudioFormat::checkSampleType()
+{
+ QAudioFormat audioFormat;
+ audioFormat.setSampleType(QAudioFormat::SignedInt);
+ QVERIFY(audioFormat.sampleType() == QAudioFormat::SignedInt);
+}
+
+void tst_QAudioFormat::checkEquality()
+{
+ QAudioFormat audioFormat0;
+ QAudioFormat audioFormat1;
+
+ // Null formats are equivalent
+ QVERIFY(audioFormat0 == audioFormat1);
+ QVERIFY(!(audioFormat0 != audioFormat1));
+
+ // on filled formats
+ audioFormat0.setFrequency(8000);
+ audioFormat0.setChannels(1);
+ audioFormat0.setSampleSize(8);
+ audioFormat0.setCodec("audio/pcm");
+ audioFormat0.setByteOrder(QAudioFormat::LittleEndian);
+ audioFormat0.setSampleType(QAudioFormat::UnSignedInt);
+
+ audioFormat1.setFrequency(8000);
+ audioFormat1.setChannels(1);
+ audioFormat1.setSampleSize(8);
+ audioFormat1.setCodec("audio/pcm");
+ audioFormat1.setByteOrder(QAudioFormat::LittleEndian);
+ audioFormat1.setSampleType(QAudioFormat::UnSignedInt);
+
+ QVERIFY(audioFormat0 == audioFormat1);
+ QVERIFY(!(audioFormat0 != audioFormat1));
+
+ audioFormat0.setFrequency(44100);
+ QVERIFY(audioFormat0 != audioFormat1);
+ QVERIFY(!(audioFormat0 == audioFormat1));
+}
+
+void tst_QAudioFormat::checkAssignment()
+{
+ QAudioFormat audioFormat0;
+ QAudioFormat audioFormat1;
+
+ audioFormat0.setFrequency(8000);
+ audioFormat0.setChannels(1);
+ audioFormat0.setSampleSize(8);
+ audioFormat0.setCodec("audio/pcm");
+ audioFormat0.setByteOrder(QAudioFormat::LittleEndian);
+ audioFormat0.setSampleType(QAudioFormat::UnSignedInt);
+
+ audioFormat1 = audioFormat0;
+ QVERIFY(audioFormat1 == audioFormat0);
+
+ QAudioFormat audioFormat2(audioFormat0);
+ QVERIFY(audioFormat2 == audioFormat0);
+}
+
+QTEST_MAIN(tst_QAudioFormat)
+
+#include "tst_qaudioformat.moc"
diff --git a/tests/auto/qaudioinput/qaudioinput.pro b/tests/auto/qaudioinput/qaudioinput.pro
new file mode 100644
index 000000000..96aca17c7
--- /dev/null
+++ b/tests/auto/qaudioinput/qaudioinput.pro
@@ -0,0 +1,18 @@
+load(qttest_p4)
+
+QT += core multimediakit-private
+
+# TARGET = tst_qaudioinput
+# CONFIG += testcase
+
+wince*{
+ DEFINES += SRCDIR=\\\"\\\"
+ QT += gui
+} else {
+ !symbian:DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
+
+HEADERS += wavheader.h
+SOURCES += wavheader.cpp tst_qaudioinput.cpp
+
+maemo*:CONFIG += insignificant_test
diff --git a/tests/auto/qaudioinput/tst_qaudioinput.cpp b/tests/auto/qaudioinput/tst_qaudioinput.cpp
new file mode 100755
index 000000000..fb5f2e229
--- /dev/null
+++ b/tests/auto/qaudioinput/tst_qaudioinput.cpp
@@ -0,0 +1,814 @@
+/****************************************************************************
+**
+** 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 test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/qlocale.h>
+
+#include <qaudioinput.h>
+#include <qaudiodeviceinfo.h>
+#include <qaudioformat.h>
+#include <qaudio.h>
+
+#include "wavheader.h"
+
+//TESTED_COMPONENT=src/multimedia
+
+#define AUDIO_BUFFER 192000
+
+#if defined(Q_OS_SYMBIAN)
+#define SRCDIR ""
+#endif
+
+#ifndef QTRY_VERIFY2
+#define QTRY_VERIFY2(__expr,__msg) \
+ do { \
+ const int __step = 50; \
+ const int __timeout = 5000; \
+ if (!(__expr)) { \
+ QTest::qWait(0); \
+ } \
+ for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \
+ QTest::qWait(__step); \
+ } \
+ QVERIFY2(__expr,__msg); \
+ } while(0)
+#endif
+
+Q_DECLARE_METATYPE(QAudioFormat)
+
+class tst_QAudioInput : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QAudioInput(QObject* parent=0) : QObject(parent) {}
+
+private slots:
+ void initTestCase();
+
+ void format();
+ void invalidFormat_data();
+ void invalidFormat();
+
+ void bufferSize();
+
+ void notifyInterval();
+ void disableNotifyInterval();
+
+ void stopWhileStopped();
+ void suspendWhileStopped();
+ void resumeWhileStopped();
+
+ void pull();
+ void pullSuspendResume();
+
+ void push();
+ void pushSuspendResume();
+
+ void reset();
+
+ void cleanupTestCase();
+
+private:
+ QString formatToFileName(const QAudioFormat &format);
+ QString workingDir();
+
+ QAudioDeviceInfo audioDevice;
+ QList<QAudioFormat> testFormats;
+ QList<QFile*> audioFiles;
+
+ QScopedPointer<QByteArray> m_byteArray;
+ QScopedPointer<QBuffer> m_buffer;
+};
+
+QString tst_QAudioInput::formatToFileName(const QAudioFormat &format)
+{
+ const QString formatEndian = (format.byteOrder() == QAudioFormat::LittleEndian)
+ ? QString("LE") : QString("BE");
+
+ const QString formatSigned = (format.sampleType() == QAudioFormat::SignedInt)
+ ? QString("signed") : QString("unsigned");
+
+ return QString("%1_%2_%3_%4_%5")
+ .arg(format.frequency())
+ .arg(format.sampleSize())
+ .arg(formatSigned)
+ .arg(formatEndian)
+ .arg(format.channels());
+}
+
+
+QString tst_QAudioInput::workingDir()
+{
+ QDir working(QString(SRCDIR));
+
+ if (working.exists())
+ return QString(SRCDIR);
+
+ return QDir::currentPath();
+}
+
+void tst_QAudioInput::initTestCase()
+{
+ qRegisterMetaType<QAudioFormat>();
+
+ // Only perform tests if audio output device exists
+ const QList<QAudioDeviceInfo> devices =
+ QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
+
+ if (devices.size() <= 0)
+ QSKIP("No audio backend", SkipAll);
+
+ audioDevice = QAudioDeviceInfo::defaultInputDevice();
+
+
+ QAudioFormat format;
+
+ format.setCodec("audio/pcm");
+
+ if (audioDevice.isFormatSupported(audioDevice.preferredFormat()))
+ testFormats.append(audioDevice.preferredFormat());
+
+ // PCM 8000 mono S8
+ format.setFrequency(8000);
+ format.setSampleSize(8);
+ format.setSampleType(QAudioFormat::SignedInt);
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setChannels(1);
+ if (audioDevice.isFormatSupported(format))
+ testFormats.append(format);
+
+ // PCM 11025 mono S16LE
+ format.setFrequency(11025);
+ format.setSampleSize(16);
+ if (audioDevice.isFormatSupported(format))
+ testFormats.append(format);
+
+ // PCM 22050 mono S16LE
+ format.setFrequency(22050);
+ if (audioDevice.isFormatSupported(format))
+ testFormats.append(format);
+
+ // PCM 22050 stereo S16LE
+ format.setChannels(2);
+ if (audioDevice.isFormatSupported(format))
+ testFormats.append(format);
+
+ // PCM 44100 stereo S16LE
+ format.setFrequency(44100);
+ if (audioDevice.isFormatSupported(format))
+ testFormats.append(format);
+
+ // PCM 48000 stereo S16LE
+ format.setFrequency(48000);
+ if (audioDevice.isFormatSupported(format))
+ testFormats.append(format);
+
+ QVERIFY(testFormats.size());
+
+ foreach (format, testFormats) {
+ QFile* file = new QFile(workingDir() + formatToFileName(format) + QString(".wav"));
+ audioFiles.append(file);
+ }
+}
+
+void tst_QAudioInput::format()
+{
+ QAudioInput audioInput(audioDevice.preferredFormat(), this);
+
+ QAudioFormat requested = audioDevice.preferredFormat();
+ QAudioFormat actual = audioInput.format();
+
+ QVERIFY2((requested.channels() == actual.channels()),
+ QString("channels: requested=%1, actual=%2").arg(requested.channels()).arg(actual.channels()).toLocal8Bit().constData());
+ QVERIFY2((requested.frequency() == actual.frequency()),
+ QString("frequency: requested=%1, actual=%2").arg(requested.frequency()).arg(actual.frequency()).toLocal8Bit().constData());
+ QVERIFY2((requested.sampleSize() == actual.sampleSize()),
+ QString("sampleSize: requested=%1, actual=%2").arg(requested.sampleSize()).arg(actual.sampleSize()).toLocal8Bit().constData());
+ QVERIFY2((requested.codec() == actual.codec()),
+ QString("codec: requested=%1, actual=%2").arg(requested.codec()).arg(actual.codec()).toLocal8Bit().constData());
+ QVERIFY2((requested.byteOrder() == actual.byteOrder()),
+ QString("byteOrder: requested=%1, actual=%2").arg(requested.byteOrder()).arg(actual.byteOrder()).toLocal8Bit().constData());
+ QVERIFY2((requested.sampleType() == actual.sampleType()),
+ QString("sampleType: requested=%1, actual=%2").arg(requested.sampleType()).arg(actual.sampleType()).toLocal8Bit().constData());
+}
+
+void tst_QAudioInput::invalidFormat_data()
+{
+ QTest::addColumn<QAudioFormat>("invalidFormat");
+
+ QAudioFormat format;
+
+ QTest::newRow("Null Format")
+ << format;
+
+ format = audioDevice.preferredFormat();
+ format.setChannelCount(0);
+ QTest::newRow("Channel count 0")
+ << format;
+
+ format = audioDevice.preferredFormat();
+ format.setSampleRate(0);
+ QTest::newRow("Sample rate 0")
+ << format;
+
+ format = audioDevice.preferredFormat();
+ format.setSampleSize(0);
+ QTest::newRow("Sample size 0")
+ << format;
+}
+
+void tst_QAudioInput::invalidFormat()
+{
+ QFETCH(QAudioFormat, invalidFormat);
+
+ QVERIFY2(!audioDevice.isFormatSupported(invalidFormat),
+ "isFormatSupported() is returning true on an invalid format");
+
+ QAudioInput audioInput(invalidFormat, this);
+
+ // Check that we are in the default state before calling start
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+
+ audioInput.start();
+ // Check that error is raised
+ QTRY_VERIFY2((audioInput.error() == QAudio::OpenError),"error() was not set to QAudio::OpenError after start()");
+}
+
+void tst_QAudioInput::bufferSize()
+{
+ QAudioInput audioInput(audioDevice.preferredFormat(), this);
+
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation");
+
+ audioInput.setBufferSize(512);
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(512)");
+ QVERIFY2((audioInput.bufferSize() == 512),
+ QString("bufferSize: requested=512, actual=%2").arg(audioInput.bufferSize()).toLocal8Bit().constData());
+
+ audioInput.setBufferSize(4096);
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(4096)");
+ QVERIFY2((audioInput.bufferSize() == 4096),
+ QString("bufferSize: requested=4096, actual=%2").arg(audioInput.bufferSize()).toLocal8Bit().constData());
+
+ audioInput.setBufferSize(8192);
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(8192)");
+ QVERIFY2((audioInput.bufferSize() == 8192),
+ QString("bufferSize: requested=8192, actual=%2").arg(audioInput.bufferSize()).toLocal8Bit().constData());
+}
+
+void tst_QAudioInput::notifyInterval()
+{
+ QAudioInput audioInput(audioDevice.preferredFormat(), this);
+
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation");
+
+ audioInput.setNotifyInterval(50);
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(50)");
+ QVERIFY2((audioInput.notifyInterval() == 50),
+ QString("notifyInterval: requested=50, actual=%2").arg(audioInput.notifyInterval()).toLocal8Bit().constData());
+
+ audioInput.setNotifyInterval(100);
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(100)");
+ QVERIFY2((audioInput.notifyInterval() == 100),
+ QString("notifyInterval: requested=100, actual=%2").arg(audioInput.notifyInterval()).toLocal8Bit().constData());
+
+ audioInput.setNotifyInterval(250);
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(250)");
+ QVERIFY2((audioInput.notifyInterval() == 250),
+ QString("notifyInterval: requested=250, actual=%2").arg(audioInput.notifyInterval()).toLocal8Bit().constData());
+
+ audioInput.setNotifyInterval(1000);
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(1000)");
+ QVERIFY2((audioInput.notifyInterval() == 1000),
+ QString("notifyInterval: requested=1000, actual=%2").arg(audioInput.notifyInterval()).toLocal8Bit().constData());
+}
+
+void tst_QAudioInput::disableNotifyInterval()
+{
+ // Sets an invalid notification interval (QAudioInput::setNotifyInterval(0))
+ // Checks that
+ // - No error is raised (QAudioInput::error() returns QAudio::NoError)
+ // - if <= 0, set to zero and disable notify signal
+
+ QAudioInput audioInput(audioDevice.preferredFormat(), this);
+
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation");
+
+ audioInput.setNotifyInterval(0);
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(0)");
+ QVERIFY2((audioInput.notifyInterval() == 0),
+ "notifyInterval() is not zero after setNotifyInterval(0)");
+
+ audioInput.setNotifyInterval(-1);
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(-1)");
+ QVERIFY2((audioInput.notifyInterval() == 0),
+ "notifyInterval() is not zero after setNotifyInterval(-1)");
+
+ //start and run to check if notify() is emitted
+ if (audioFiles.size() > 0) {
+ QAudioInput audioInputCheck(testFormats.at(0), this);
+ audioInputCheck.setNotifyInterval(0);
+ QSignalSpy notifySignal(&audioInputCheck, SIGNAL(notify()));
+ audioFiles.at(0)->open(QIODevice::WriteOnly);
+ audioInputCheck.start(audioFiles.at(0));
+ QTest::qWait(3000); // 3 seconds should be plenty
+ audioInputCheck.stop();
+ QVERIFY2((notifySignal.count() == 0),
+ QString("didn't disable notify interval: shouldn't have got any but got %1").arg(notifySignal.count()).toLocal8Bit().constData());
+ audioFiles.at(0)->close();
+ }
+}
+
+void tst_QAudioInput::stopWhileStopped()
+{
+ // Calls QAudioInput::stop() when object is already in StoppedState
+ // Checks that
+ // - No state change occurs
+ // - No error is raised (QAudioInput::error() returns QAudio::NoError)
+
+ QAudioInput audioInput(audioDevice.preferredFormat(), this);
+
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+
+ QSignalSpy stateSignal(&audioInput, SIGNAL(stateChanged(QAudio::State)));
+ audioInput.stop();
+
+ // Check that no state transition occurred
+ QVERIFY2((stateSignal.count() == 0), "stop() while stopped is emitting a signal and it shouldn't");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after stop()");
+}
+
+void tst_QAudioInput::suspendWhileStopped()
+{
+ // Calls QAudioInput::suspend() when object is already in StoppedState
+ // Checks that
+ // - No state change occurs
+ // - No error is raised (QAudioInput::error() returns QAudio::NoError)
+
+ QAudioInput audioInput(audioDevice.preferredFormat(), this);
+
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+
+ QSignalSpy stateSignal(&audioInput, SIGNAL(stateChanged(QAudio::State)));
+ audioInput.suspend();
+
+ // Check that no state transition occurred
+ QVERIFY2((stateSignal.count() == 0), "stop() while suspended is emitting a signal and it shouldn't");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after stop()");
+}
+
+void tst_QAudioInput::resumeWhileStopped()
+{
+ // Calls QAudioInput::resume() when object is already in StoppedState
+ // Checks that
+ // - No state change occurs
+ // - No error is raised (QAudioInput::error() returns QAudio::NoError)
+
+ QAudioInput audioInput(audioDevice.preferredFormat(), this);
+
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+
+ QSignalSpy stateSignal(&audioInput, SIGNAL(stateChanged(QAudio::State)));
+ audioInput.resume();
+
+ // Check that no state transition occurred
+ QVERIFY2((stateSignal.count() == 0), "resume() while stopped is emitting a signal and it shouldn't");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after resume()");
+}
+
+void tst_QAudioInput::pull()
+{
+ for(int i=0; i<audioFiles.count(); i++) {
+ QAudioInput audioInput(testFormats.at(i), this);
+
+ audioInput.setNotifyInterval(100);
+
+ QSignalSpy notifySignal(&audioInput, SIGNAL(notify()));
+ QSignalSpy stateSignal(&audioInput, SIGNAL(stateChanged(QAudio::State)));
+
+ // Check that we are in the default state before calling start
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+ QVERIFY2((audioInput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
+
+ audioFiles.at(i)->close();
+ audioFiles.at(i)->open(QIODevice::WriteOnly);
+ WavHeader wavHeader(testFormats.at(i));
+ QVERIFY(wavHeader.write(*audioFiles.at(i)));
+
+ audioInput.start(audioFiles.at(i));
+ // Check that QAudioInput immediately transitions to ActiveState or IdleState
+ QTRY_VERIFY2((stateSignal.count() > 0),"didn't emit signals on start()");
+ QVERIFY2((audioInput.state() == QAudio::ActiveState || audioInput.state() == QAudio::IdleState),
+ "didn't transition to ActiveState or IdleState after start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
+ QVERIFY(audioInput.periodSize() > 0);
+ stateSignal.clear();
+
+ // Check that 'elapsed' increases
+ QTest::qWait(40);
+ QVERIFY2((audioInput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()");
+
+ // Allow some recording to happen
+ QTest::qWait(3000); // 3 seconds should be plenty
+
+ stateSignal.clear();
+
+ qint64 processedUs = audioInput.processedUSecs();
+
+ audioInput.stop();
+ QTest::qWait(40);
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
+
+ QVERIFY2((processedUs > 2800000 && processedUs < 3200000),
+ QString("processedUSecs() doesn't fall in acceptable range, should be 3040000 (%1)").arg(processedUs).toLocal8Bit().constData());
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
+ QVERIFY2((audioInput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
+ QVERIFY2((notifySignal.count() > 20 && notifySignal.count() < 40),
+ QString("notify() signals emitted (%1) should be 30").arg(notifySignal.count()).toLocal8Bit().constData());
+
+ WavHeader::writeDataLength(*audioFiles.at(i),audioFiles.at(i)->pos()-WavHeader::headerLength());
+ audioFiles.at(i)->close();
+ }
+}
+
+void tst_QAudioInput::pullSuspendResume()
+{
+ for(int i=0; i<audioFiles.count(); i++) {
+ QAudioInput audioInput(testFormats.at(i), this);
+
+ audioInput.setNotifyInterval(100);
+
+ QSignalSpy notifySignal(&audioInput, SIGNAL(notify()));
+ QSignalSpy stateSignal(&audioInput, SIGNAL(stateChanged(QAudio::State)));
+
+ // Check that we are in the default state before calling start
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+ QVERIFY2((audioInput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
+
+ audioFiles.at(i)->close();
+ audioFiles.at(i)->open(QIODevice::WriteOnly);
+ WavHeader wavHeader(testFormats.at(i));
+ QVERIFY(wavHeader.write(*audioFiles.at(i)));
+
+ audioInput.start(audioFiles.at(i));
+ // Check that QAudioInput immediately transitions to ActiveState or IdleState
+ QTRY_VERIFY2((stateSignal.count() > 0),"didn't emit signals on start()");
+ QVERIFY2((audioInput.state() == QAudio::ActiveState || audioInput.state() == QAudio::IdleState),
+ "didn't transition to ActiveState or IdleState after start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
+ QVERIFY(audioInput.periodSize() > 0);
+ stateSignal.clear();
+
+ // Check that 'elapsed' increases
+ QTest::qWait(40);
+ QVERIFY2((audioInput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()");
+
+ // Allow some recording to happen
+ QTest::qWait(3000); // 3 seconds should be plenty
+
+ QVERIFY2((audioInput.state() == QAudio::ActiveState),
+ "didn't transition to ActiveState after some recording");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after some recording");
+
+ stateSignal.clear();
+
+ audioInput.suspend();
+
+ // Give backends running in separate threads a chance to suspend.
+ QTest::qWait(100);
+
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit SuspendedState signal after suspend(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioInput.state() == QAudio::SuspendedState), "didn't transitions to SuspendedState after stop()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
+ stateSignal.clear();
+
+ // Check that only 'elapsed', and not 'processed' increases while suspended
+ qint64 elapsedUs = audioInput.elapsedUSecs();
+ qint64 processedUs = audioInput.processedUSecs();
+ QTest::qWait(1000);
+ QVERIFY(audioInput.elapsedUSecs() > elapsedUs);
+ QVERIFY(audioInput.processedUSecs() == processedUs);
+
+ audioInput.resume();
+
+ // Give backends running in separate threads a chance to resume.
+ QTest::qWait(100);
+
+ // Check that QAudioInput immediately transitions to ActiveState
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit signal after resume(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioInput.state() == QAudio::ActiveState), "didn't transition to ActiveState after resume()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after resume()");
+ stateSignal.clear();
+
+ processedUs = audioInput.processedUSecs();
+
+ audioInput.stop();
+ QTest::qWait(40);
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
+
+ QVERIFY2((processedUs > 2800000 && processedUs < 3200000),
+ QString("processedUSecs() doesn't fall in acceptable range, should be 3040000 (%1)").arg(processedUs).toLocal8Bit().constData());
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
+ QVERIFY2((audioInput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
+ QVERIFY2((notifySignal.count() > 20 && notifySignal.count() < 40),
+ QString("notify() signals emitted (%1) should be 30").arg(notifySignal.count()).toLocal8Bit().constData());
+
+ WavHeader::writeDataLength(*audioFiles.at(i),audioFiles.at(i)->pos()-WavHeader::headerLength());
+ audioFiles.at(i)->close();
+ }
+}
+
+void tst_QAudioInput::push()
+{
+ for(int i=0; i<audioFiles.count(); i++) {
+ QAudioInput audioInput(testFormats.at(i), this);
+
+ audioInput.setNotifyInterval(100);
+
+ QSignalSpy notifySignal(&audioInput, SIGNAL(notify()));
+ QSignalSpy stateSignal(&audioInput, SIGNAL(stateChanged(QAudio::State)));
+
+ // Check that we are in the default state before calling start
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+ QVERIFY2((audioInput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
+
+ audioFiles.at(i)->close();
+ audioFiles.at(i)->open(QIODevice::WriteOnly);
+ WavHeader wavHeader(testFormats.at(i));
+ QVERIFY(wavHeader.write(*audioFiles.at(i)));
+
+ QIODevice* feed = audioInput.start();
+
+ // Check that QAudioInput immediately transitions to IdleState
+ QTRY_VERIFY2((stateSignal.count() == 1),"didn't emit IdleState signal on start()");
+ QVERIFY2((audioInput.state() == QAudio::IdleState),
+ "didn't transition to IdleState after start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
+ QVERIFY(audioInput.periodSize() > 0);
+ stateSignal.clear();
+
+ // Check that 'elapsed' increases
+ QTest::qWait(40);
+ QVERIFY2((audioInput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()");
+
+ qint64 totalBytesRead = 0;
+ bool firstBuffer = true;
+ QByteArray buffer(AUDIO_BUFFER, 0);
+ qint64 len = (testFormats.at(i).frequency()*testFormats.at(i).channels()*(testFormats.at(i).sampleSize()/8)*2); // 2 seconds
+ while (totalBytesRead < len) {
+ if (audioInput.bytesReady() >= audioInput.periodSize()) {
+ qint64 bytesRead = feed->read(buffer.data(), audioInput.periodSize());
+ audioFiles.at(i)->write(buffer.constData(),bytesRead);
+ totalBytesRead+=bytesRead;
+ if (firstBuffer && bytesRead) {
+ // Check for transition to ActiveState when data is provided
+ QVERIFY2((stateSignal.count() == 1),"didn't emit ActiveState signal on data");
+ QVERIFY2((audioInput.state() == QAudio::ActiveState),
+ "didn't transition to ActiveState after data");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
+ firstBuffer = false;
+ }
+ } else
+ QTest::qWait(20);
+ }
+
+ QTest::qWait(1000);
+
+ stateSignal.clear();
+
+ qint64 processedUs = audioInput.processedUSecs();
+
+ audioInput.stop();
+ QTest::qWait(40);
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
+
+ QVERIFY2((processedUs > 1800000 && processedUs < 2200000),
+ QString("processedUSecs() doesn't fall in acceptable range, should be 2040000 (%1)").arg(processedUs).toLocal8Bit().constData());
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
+ QVERIFY2((audioInput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
+ QVERIFY2((notifySignal.count() > 20 && notifySignal.count() < 40),
+ QString("notify() signals emitted (%1) should be 30").arg(notifySignal.count()).toLocal8Bit().constData());
+
+ WavHeader::writeDataLength(*audioFiles.at(i),audioFiles.at(i)->pos()-WavHeader::headerLength());
+ audioFiles.at(i)->close();
+ }
+}
+
+void tst_QAudioInput::pushSuspendResume()
+{
+ for(int i=0; i<audioFiles.count(); i++) {
+ QAudioInput audioInput(testFormats.at(i), this);
+
+ audioInput.setNotifyInterval(100);
+
+ QSignalSpy notifySignal(&audioInput, SIGNAL(notify()));
+ QSignalSpy stateSignal(&audioInput, SIGNAL(stateChanged(QAudio::State)));
+
+ // Check that we are in the default state before calling start
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+ QVERIFY2((audioInput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
+
+ audioFiles.at(i)->close();
+ audioFiles.at(i)->open(QIODevice::WriteOnly);
+ WavHeader wavHeader(testFormats.at(i));
+ QVERIFY(wavHeader.write(*audioFiles.at(i)));
+
+ QIODevice* feed = audioInput.start();
+
+ // Check that QAudioInput immediately transitions to IdleState
+ QTRY_VERIFY2((stateSignal.count() == 1),"didn't emit IdleState signal on start()");
+ QVERIFY2((audioInput.state() == QAudio::IdleState),
+ "didn't transition to IdleState after start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
+ QVERIFY(audioInput.periodSize() > 0);
+ stateSignal.clear();
+
+ // Check that 'elapsed' increases
+ QTest::qWait(40);
+ QVERIFY2((audioInput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()");
+
+ qint64 totalBytesRead = 0;
+ bool firstBuffer = true;
+ QByteArray buffer(AUDIO_BUFFER, 0);
+ qint64 len = (testFormats.at(i).frequency()*testFormats.at(i).channels()*(testFormats.at(i).sampleSize()/8)); // 1 seconds
+ while (totalBytesRead < len) {
+ if (audioInput.bytesReady() >= audioInput.periodSize()) {
+ qint64 bytesRead = feed->read(buffer.data(), audioInput.periodSize());
+ audioFiles.at(i)->write(buffer.constData(),bytesRead);
+ totalBytesRead+=bytesRead;
+ if (firstBuffer && bytesRead) {
+ // Check for transition to ActiveState when data is provided
+ QVERIFY2((stateSignal.count() == 1),"didn't emit ActiveState signal on data");
+ QVERIFY2((audioInput.state() == QAudio::ActiveState),
+ "didn't transition to ActiveState after data");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
+ firstBuffer = false;
+ }
+ } else
+ QTest::qWait(20);
+ }
+ stateSignal.clear();
+
+ audioInput.suspend();
+
+ // Give backends running in separate threads a chance to suspend
+ QTest::qWait(100);
+
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit SuspendedState signal after suspend(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioInput.state() == QAudio::SuspendedState), "didn't transitions to SuspendedState after stop()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
+ stateSignal.clear();
+
+ // Check that only 'elapsed', and not 'processed' increases while suspended
+ qint64 elapsedUs = audioInput.elapsedUSecs();
+ qint64 processedUs = audioInput.processedUSecs();
+ QTest::qWait(1000);
+ QVERIFY(audioInput.elapsedUSecs() > elapsedUs);
+ QVERIFY(audioInput.processedUSecs() == processedUs);
+
+ audioInput.resume();
+
+ // Give backends running in separate threads a chance to resume.
+ QTest::qWait(100);
+
+ // Check that QAudioInput immediately transitions to Active or IdleState
+ QVERIFY2((stateSignal.count() > 0),"didn't emit signals on resume()");
+ QVERIFY2((audioInput.state() == QAudio::ActiveState || audioInput.state() == QAudio::IdleState),
+ "didn't transition to ActiveState or IdleState after resume()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after resume()");
+ QVERIFY(audioInput.periodSize() > 0);
+
+ // Let it play out what is in buffer and go to Idle before continue
+ QTest::qWait(1000);
+ stateSignal.clear();
+
+ // Read another seconds worth
+ totalBytesRead = 0;
+ firstBuffer = true;
+ while (totalBytesRead < len) {
+ if (audioInput.bytesReady() >= audioInput.periodSize()) {
+ qint64 bytesRead = feed->read(buffer.data(), audioInput.periodSize());
+ audioFiles.at(i)->write(buffer.constData(),bytesRead);
+ totalBytesRead+=bytesRead;
+ } else
+ QTest::qWait(20);
+ }
+ stateSignal.clear();
+
+ processedUs = audioInput.processedUSecs();
+
+ audioInput.stop();
+ QTest::qWait(40);
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
+
+ QVERIFY2((processedUs > 1800000 && processedUs < 2200000),
+ QString("processedUSecs() doesn't fall in acceptable range, should be 2040000 (%1)").arg(processedUs).toLocal8Bit().constData());
+ QVERIFY2((audioInput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
+
+ WavHeader::writeDataLength(*audioFiles.at(i),audioFiles.at(i)->pos()-WavHeader::headerLength());
+ audioFiles.at(i)->close();
+ }
+}
+
+void tst_QAudioInput::reset()
+{
+ for(int i=0; i<audioFiles.count(); i++) {
+ QAudioInput audioInput(testFormats.at(i), this);
+
+ audioInput.setNotifyInterval(100);
+
+ QSignalSpy notifySignal(&audioInput, SIGNAL(notify()));
+ QSignalSpy stateSignal(&audioInput, SIGNAL(stateChanged(QAudio::State)));
+
+ // Check that we are in the default state before calling start
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+ QVERIFY2((audioInput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
+
+ audioInput.start();
+ // Check that QAudioInput immediately transitions to IdleState
+ QTRY_VERIFY2((stateSignal.count() == 1),"didn't emit IdleState signal on start()");
+ QVERIFY2((audioInput.state() == QAudio::IdleState), "didn't transition to IdleState after start()");
+ QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
+ QVERIFY(audioInput.periodSize() > 0);
+ QTest::qWait(500);
+ QVERIFY(audioInput.bytesReady() > 0);
+ stateSignal.clear();
+
+ audioInput.reset();
+ QTRY_VERIFY2((stateSignal.count() == 1),"didn't emit StoppedState signal after reset()");
+ QVERIFY2((audioInput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after reset()");
+ QVERIFY2((audioInput.bytesReady() == 0), "buffer not cleared after reset()");
+ }
+}
+
+void tst_QAudioInput::cleanupTestCase()
+{
+ QFile* file;
+
+ foreach (file, audioFiles) {
+ file->remove();
+ delete file;
+ }
+}
+
+QTEST_MAIN(tst_QAudioInput)
+
+#include "tst_qaudioinput.moc"
diff --git a/tests/auto/qaudioinput/wavheader.cpp b/tests/auto/qaudioinput/wavheader.cpp
new file mode 100755
index 000000000..26fcd6f98
--- /dev/null
+++ b/tests/auto/qaudioinput/wavheader.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** 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 test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qendian.h>
+#include "wavheader.h"
+
+
+struct chunk
+{
+ char id[4];
+ quint32 size;
+};
+
+struct RIFFHeader
+{
+ chunk descriptor; // "RIFF"
+ char type[4]; // "WAVE"
+};
+
+struct WAVEHeader
+{
+ chunk descriptor;
+ quint16 audioFormat;
+ quint16 numChannels;
+ quint32 sampleRate;
+ quint32 byteRate;
+ quint16 blockAlign;
+ quint16 bitsPerSample;
+};
+
+struct DATAHeader
+{
+ chunk descriptor;
+};
+
+struct CombinedHeader
+{
+ RIFFHeader riff;
+ WAVEHeader wave;
+ DATAHeader data;
+};
+
+static const int HeaderLength = sizeof(CombinedHeader);
+
+
+WavHeader::WavHeader(const QAudioFormat &format, qint64 dataLength)
+ : m_format(format)
+ , m_dataLength(dataLength)
+{
+
+}
+
+bool WavHeader::read(QIODevice &device)
+{
+ bool result = true;
+
+ if (!device.isSequential())
+ result = device.seek(0);
+ // else, assume that current position is the start of the header
+
+ if (result) {
+ CombinedHeader header;
+ result = (device.read(reinterpret_cast<char *>(&header), HeaderLength) == HeaderLength);
+ if (result) {
+ if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0
+ || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0)
+ && memcmp(&header.riff.type, "WAVE", 4) == 0
+ && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0
+ && header.wave.audioFormat == 1 // PCM
+ ) {
+ if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
+ m_format.setByteOrder(QAudioFormat::LittleEndian);
+ else
+ m_format.setByteOrder(QAudioFormat::BigEndian);
+
+ m_format.setChannels(qFromLittleEndian<quint16>(header.wave.numChannels));
+ m_format.setCodec("audio/pcm");
+ m_format.setFrequency(qFromLittleEndian<quint32>(header.wave.sampleRate));
+ m_format.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample));
+
+ switch(header.wave.bitsPerSample) {
+ case 8:
+ m_format.setSampleType(QAudioFormat::UnSignedInt);
+ break;
+ case 16:
+ m_format.setSampleType(QAudioFormat::SignedInt);
+ break;
+ default:
+ result = false;
+ }
+
+ m_dataLength = device.size() - HeaderLength;
+ } else {
+ result = false;
+ }
+ }
+ }
+
+ return result;
+}
+
+bool WavHeader::write(QIODevice &device)
+{
+ CombinedHeader header;
+
+ memset(&header, 0, HeaderLength);
+
+ // RIFF header
+ if (m_format.byteOrder() == QAudioFormat::LittleEndian)
+ memcpy(header.riff.descriptor.id,"RIFF",4);
+ else
+ memcpy(header.riff.descriptor.id,"RIFX",4);
+ qToLittleEndian<quint32>(quint32(m_dataLength + HeaderLength - 8),
+ reinterpret_cast<unsigned char*>(&header.riff.descriptor.size));
+ memcpy(header.riff.type, "WAVE",4);
+
+ // WAVE header
+ memcpy(header.wave.descriptor.id,"fmt ",4);
+ qToLittleEndian<quint32>(quint32(16),
+ reinterpret_cast<unsigned char*>(&header.wave.descriptor.size));
+ qToLittleEndian<quint16>(quint16(1),
+ reinterpret_cast<unsigned char*>(&header.wave.audioFormat));
+ qToLittleEndian<quint16>(quint16(m_format.channels()),
+ reinterpret_cast<unsigned char*>(&header.wave.numChannels));
+ qToLittleEndian<quint32>(quint32(m_format.frequency()),
+ reinterpret_cast<unsigned char*>(&header.wave.sampleRate));
+ qToLittleEndian<quint32>(quint32(m_format.frequency() * m_format.channels() * m_format.sampleSize() / 8),
+ reinterpret_cast<unsigned char*>(&header.wave.byteRate));
+ qToLittleEndian<quint16>(quint16(m_format.channels() * m_format.sampleSize() / 8),
+ reinterpret_cast<unsigned char*>(&header.wave.blockAlign));
+ qToLittleEndian<quint16>(quint16(m_format.sampleSize()),
+ reinterpret_cast<unsigned char*>(&header.wave.bitsPerSample));
+
+ // DATA header
+ memcpy(header.data.descriptor.id,"data",4);
+ qToLittleEndian<quint32>(quint32(m_dataLength),
+ reinterpret_cast<unsigned char*>(&header.data.descriptor.size));
+
+ return (device.write(reinterpret_cast<const char *>(&header), HeaderLength) == HeaderLength);
+}
+
+const QAudioFormat& WavHeader::format() const
+{
+ return m_format;
+}
+
+qint64 WavHeader::dataLength() const
+{
+ return m_dataLength;
+}
+
+qint64 WavHeader::headerLength()
+{
+ return HeaderLength;
+}
+
+bool WavHeader::writeDataLength(QIODevice &device, qint64 dataLength)
+{
+ bool result = false;
+ if (!device.isSequential()) {
+ device.seek(40);
+ unsigned char dataLengthLE[4];
+ qToLittleEndian<quint32>(quint32(dataLength), dataLengthLE);
+ result = (device.write(reinterpret_cast<const char *>(dataLengthLE), 4) == 4);
+ }
+ return result;
+}
diff --git a/tests/auto/qaudioinput/wavheader.h b/tests/auto/qaudioinput/wavheader.h
new file mode 100755
index 000000000..4136da027
--- /dev/null
+++ b/tests/auto/qaudioinput/wavheader.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** 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 test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef WAVHEADER_H
+#define WAVHEADER_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qfile.h>
+#include <qaudioformat.h>
+
+/**
+ * Helper class for parsing WAV file headers.
+ *
+ * See https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
+ */
+class WavHeader
+{
+public:
+ WavHeader(const QAudioFormat &format = QAudioFormat(),
+ qint64 dataLength = 0);
+
+ // Reads WAV header and seeks to start of data
+ bool read(QIODevice &device);
+
+ // Writes WAV header
+ bool write(QIODevice &device);
+
+ const QAudioFormat& format() const;
+ qint64 dataLength() const;
+
+ static qint64 headerLength();
+
+ static bool writeDataLength(QIODevice &device, qint64 dataLength);
+
+private:
+ QAudioFormat m_format;
+ qint64 m_dataLength;
+};
+
+#endif
+
diff --git a/tests/auto/qaudiooutput/qaudiooutput.pro b/tests/auto/qaudiooutput/qaudiooutput.pro
new file mode 100644
index 000000000..b99128c77
--- /dev/null
+++ b/tests/auto/qaudiooutput/qaudiooutput.pro
@@ -0,0 +1,18 @@
+load(qttest_p4)
+
+QT += core multimediakit-private
+
+# TARGET = tst_qaudiooutput
+# CONFIG += testcase
+
+wince*: {
+ DEFINES += SRCDIR=\\\"\\\"
+ QT += gui
+} else {
+ !symbian:DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
+
+HEADERS += wavheader.h
+SOURCES += wavheader.cpp tst_qaudiooutput.cpp
+
+maemo*:CONFIG += insignificant_test
diff --git a/tests/auto/qaudiooutput/tst_qaudiooutput.cpp b/tests/auto/qaudiooutput/tst_qaudiooutput.cpp
new file mode 100755
index 000000000..2590af39d
--- /dev/null
+++ b/tests/auto/qaudiooutput/tst_qaudiooutput.cpp
@@ -0,0 +1,962 @@
+/****************************************************************************
+**
+** 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 test suite 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <QtTest/QtTest>
+#include <QtCore/qlocale.h>
+
+#include <qaudiooutput.h>
+#include <qaudiodeviceinfo.h>
+#include <qaudioformat.h>
+#include <qaudio.h>
+
+#include "wavheader.h"
+
+#define AUDIO_BUFFER 192000
+
+#if defined(Q_OS_SYMBIAN)
+#define SRCDIR ""
+#endif
+
+#ifndef QTRY_VERIFY2
+#define QTRY_VERIFY2(__expr,__msg) \
+ do { \
+ const int __step = 50; \
+ const int __timeout = 5000; \
+ if (!(__expr)) { \
+ QTest::qWait(0); \
+ } \
+ for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \
+ QTest::qWait(__step); \
+ } \
+ QVERIFY2(__expr,__msg); \
+ } while(0)
+#endif
+
+Q_DECLARE_METATYPE(QAudioFormat)
+
+class tst_QAudioOutput : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QAudioOutput(QObject* parent=0) : QObject(parent) {}
+
+private slots:
+ void initTestCase();
+
+ void format();
+ void invalidFormat_data();
+ void invalidFormat();
+
+ void bufferSize();
+
+ void notifyInterval();
+ void disableNotifyInterval();
+
+ void stopWhileStopped();
+ void suspendWhileStopped();
+ void resumeWhileStopped();
+
+ void pull();
+ void pullSuspendResume();
+
+ void push();
+ void pushSuspendResume();
+ void pushUnderrun();
+
+ void cleanupTestCase();
+
+private:
+ QString formatToFileName(const QAudioFormat &format);
+ QString workingDir();
+ void createSineWaveData(const QAudioFormat &format, qint64 length, int frequency = 440);
+
+ QAudioDeviceInfo audioDevice;
+ QList<QAudioFormat> testFormats;
+ QList<QFile*> audioFiles;
+
+ QScopedPointer<QByteArray> m_byteArray;
+ QScopedPointer<QBuffer> m_buffer;
+};
+
+QString tst_QAudioOutput::formatToFileName(const QAudioFormat &format)
+{
+ const QString formatEndian = (format.byteOrder() == QAudioFormat::LittleEndian)
+ ? QString("LE") : QString("BE");
+
+ const QString formatSigned = (format.sampleType() == QAudioFormat::SignedInt)
+ ? QString("signed") : QString("unsigned");
+
+ return QString("%1_%2_%3_%4_%5")
+ .arg(format.frequency())
+ .arg(format.sampleSize())
+ .arg(formatSigned)
+ .arg(formatEndian)
+ .arg(format.channels());
+}
+
+
+QString tst_QAudioOutput::workingDir()
+{
+ QDir working(QString(SRCDIR));
+
+ if (working.exists())
+ return QString(SRCDIR);
+
+ return QDir::currentPath();
+}
+
+void tst_QAudioOutput::createSineWaveData(const QAudioFormat &format, qint64 length, int frequency)
+{
+ const int channelBytes = format.sampleSize() / 8;
+ const int sampleBytes = format.channels() * channelBytes;
+
+ Q_ASSERT(length % sampleBytes == 0);
+ Q_UNUSED(sampleBytes) // suppress warning in release builds
+
+ m_byteArray.reset(new QByteArray(length, 0));
+ unsigned char *ptr = reinterpret_cast<unsigned char *>(m_byteArray->data());
+ int sampleIndex = 0;
+
+ while (length) {
+ const qreal x = qSin(2 * M_PI * frequency * qreal(sampleIndex % format.frequency()) / format.frequency());
+ for (int i=0; i<format.channels(); ++i) {
+ if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::UnSignedInt) {
+ const quint8 value = static_cast<quint8>((1.0 + x) / 2 * 255);
+ *reinterpret_cast<quint8*>(ptr) = value;
+ } else if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::SignedInt) {
+ const qint8 value = static_cast<qint8>(x * 127);
+ *reinterpret_cast<quint8*>(ptr) = value;
+ } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::UnSignedInt) {
+ quint16 value = static_cast<quint16>((1.0 + x) / 2 * 65535);
+ if (format.byteOrder() == QAudioFormat::LittleEndian)
+ qToLittleEndian<quint16>(value, ptr);
+ else
+ qToBigEndian<quint16>(value, ptr);
+ } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::SignedInt) {
+ qint16 value = static_cast<qint16>(x * 32767);
+ if (format.byteOrder() == QAudioFormat::LittleEndian)
+ qToLittleEndian<qint16>(value, ptr);
+ else
+ qToBigEndian<qint16>(value, ptr);
+ }
+
+ ptr += channelBytes;
+ length -= channelBytes;
+ }
+ ++sampleIndex;
+ }
+
+ m_buffer.reset(new QBuffer(m_byteArray.data(), this));
+ Q_ASSERT(m_buffer->open(QIODevice::ReadOnly));
+}
+
+void tst_QAudioOutput::initTestCase()
+{
+ qRegisterMetaType<QAudioFormat>();
+
+ // Only perform tests if audio output device exists
+ const QList<QAudioDeviceInfo> devices =
+ QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
+
+ if (devices.size() <= 0)
+ QSKIP("No audio backend", SkipAll);
+
+ audioDevice = QAudioDeviceInfo::defaultOutputDevice();
+
+
+ QAudioFormat format;
+
+ format.setCodec("audio/pcm");
+
+ if (audioDevice.isFormatSupported(audioDevice.preferredFormat()))
+ testFormats.append(audioDevice.preferredFormat());
+
+ // PCM 8000 mono S8
+ format.setFrequency(8000);
+ format.setSampleSize(8);
+ format.setSampleType(QAudioFormat::SignedInt);
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setChannels(1);
+ if (audioDevice.isFormatSupported(format))
+ testFormats.append(format);
+
+ // PCM 11025 mono S16LE
+ format.setFrequency(11025);
+ format.setSampleSize(16);
+ if (audioDevice.isFormatSupported(format))
+ testFormats.append(format);
+
+ // PCM 22050 mono S16LE
+ format.setFrequency(22050);
+ if (audioDevice.isFormatSupported(format))
+ testFormats.append(format);
+
+ // PCM 22050 stereo S16LE
+ format.setChannels(2);
+ if (audioDevice.isFormatSupported(format))
+ testFormats.append(format);
+
+ // PCM 44100 stereo S16LE
+ format.setFrequency(44100);
+ if (audioDevice.isFormatSupported(format))
+ testFormats.append(format);
+
+ // PCM 48000 stereo S16LE
+ format.setFrequency(48000);
+ if (audioDevice.isFormatSupported(format))
+ testFormats.append(format);
+
+ QVERIFY(testFormats.size());
+
+ foreach (format, testFormats) {
+ qint64 len = (format.frequency()*format.channels()*(format.sampleSize()/8)*2); // 2 seconds
+ createSineWaveData(format, len);
+ // Write generate sine wave data to file
+ QFile* file = new QFile(workingDir() + QString("generated") + formatToFileName(format) + QString(".wav"));
+ if (file->open(QIODevice::WriteOnly)) {
+ WavHeader wavHeader(format, len);
+ wavHeader.write(*file);
+ file->write(m_byteArray->data(), len);
+ file->close();
+ audioFiles.append(file);
+ }
+ }
+}
+
+void tst_QAudioOutput::format()
+{
+ QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
+
+ QAudioFormat requested = audioDevice.preferredFormat();
+ QAudioFormat actual = audioOutput.format();
+
+ QVERIFY2((requested.channels() == actual.channels()),
+ QString("channels: requested=%1, actual=%2").arg(requested.channels()).arg(actual.channels()).toLocal8Bit().constData());
+ QVERIFY2((requested.frequency() == actual.frequency()),
+ QString("frequency: requested=%1, actual=%2").arg(requested.frequency()).arg(actual.frequency()).toLocal8Bit().constData());
+ QVERIFY2((requested.sampleSize() == actual.sampleSize()),
+ QString("sampleSize: requested=%1, actual=%2").arg(requested.sampleSize()).arg(actual.sampleSize()).toLocal8Bit().constData());
+ QVERIFY2((requested.codec() == actual.codec()),
+ QString("codec: requested=%1, actual=%2").arg(requested.codec()).arg(actual.codec()).toLocal8Bit().constData());
+ QVERIFY2((requested.byteOrder() == actual.byteOrder()),
+ QString("byteOrder: requested=%1, actual=%2").arg(requested.byteOrder()).arg(actual.byteOrder()).toLocal8Bit().constData());
+ QVERIFY2((requested.sampleType() == actual.sampleType()),
+ QString("sampleType: requested=%1, actual=%2").arg(requested.sampleType()).arg(actual.sampleType()).toLocal8Bit().constData());
+}
+
+void tst_QAudioOutput::invalidFormat_data()
+{
+ QTest::addColumn<QAudioFormat>("invalidFormat");
+
+ QAudioFormat format;
+
+ QTest::newRow("Null Format")
+ << format;
+
+ format = audioDevice.preferredFormat();
+ format.setChannelCount(0);
+ QTest::newRow("Channel count 0")
+ << format;
+
+ format = audioDevice.preferredFormat();
+ format.setSampleRate(0);
+ QTest::newRow("Sample rate 0")
+ << format;
+
+ format = audioDevice.preferredFormat();
+ format.setSampleSize(0);
+ QTest::newRow("Sample size 0")
+ << format;
+}
+
+void tst_QAudioOutput::invalidFormat()
+{
+ QFETCH(QAudioFormat, invalidFormat);
+
+ QVERIFY2(!audioDevice.isFormatSupported(invalidFormat),
+ "isFormatSupported() is returning true on an invalid format");
+
+ QAudioOutput audioOutput(invalidFormat, this);
+
+ // Check that we are in the default state before calling start
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+
+ audioOutput.start();
+ // Check that error is raised
+ QTRY_VERIFY2((audioOutput.error() == QAudio::OpenError),"error() was not set to QAudio::OpenError after start()");
+}
+
+void tst_QAudioOutput::bufferSize()
+{
+ QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
+
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation");
+
+ audioOutput.setBufferSize(512);
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(512)");
+ QVERIFY2((audioOutput.bufferSize() == 512),
+ QString("bufferSize: requested=512, actual=%2").arg(audioOutput.bufferSize()).toLocal8Bit().constData());
+
+ audioOutput.setBufferSize(4096);
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(4096)");
+ QVERIFY2((audioOutput.bufferSize() == 4096),
+ QString("bufferSize: requested=4096, actual=%2").arg(audioOutput.bufferSize()).toLocal8Bit().constData());
+
+ audioOutput.setBufferSize(8192);
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(8192)");
+ QVERIFY2((audioOutput.bufferSize() == 8192),
+ QString("bufferSize: requested=8192, actual=%2").arg(audioOutput.bufferSize()).toLocal8Bit().constData());
+}
+
+void tst_QAudioOutput::notifyInterval()
+{
+ QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
+
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation");
+
+ audioOutput.setNotifyInterval(50);
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(50)");
+ QVERIFY2((audioOutput.notifyInterval() == 50),
+ QString("notifyInterval: requested=50, actual=%2").arg(audioOutput.notifyInterval()).toLocal8Bit().constData());
+
+ audioOutput.setNotifyInterval(100);
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(100)");
+ QVERIFY2((audioOutput.notifyInterval() == 100),
+ QString("notifyInterval: requested=100, actual=%2").arg(audioOutput.notifyInterval()).toLocal8Bit().constData());
+
+ audioOutput.setNotifyInterval(250);
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(250)");
+ QVERIFY2((audioOutput.notifyInterval() == 250),
+ QString("notifyInterval: requested=250, actual=%2").arg(audioOutput.notifyInterval()).toLocal8Bit().constData());
+
+ audioOutput.setNotifyInterval(1000);
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(1000)");
+ QVERIFY2((audioOutput.notifyInterval() == 1000),
+ QString("notifyInterval: requested=1000, actual=%2").arg(audioOutput.notifyInterval()).toLocal8Bit().constData());
+}
+
+void tst_QAudioOutput::disableNotifyInterval()
+{
+ // Sets an invalid notification interval (QAudioOutput::setNotifyInterval(0))
+ // Checks that
+ // - No error is raised (QAudioOutput::error() returns QAudio::NoError)
+ // - if <= 0, set to zero and disable notify signal
+
+ QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
+
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation");
+
+ audioOutput.setNotifyInterval(0);
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(0)");
+ QVERIFY2((audioOutput.notifyInterval() == 0),
+ "notifyInterval() is not zero after setNotifyInterval(0)");
+
+ audioOutput.setNotifyInterval(-1);
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(-1)");
+ QVERIFY2((audioOutput.notifyInterval() == 0),
+ "notifyInterval() is not zero after setNotifyInterval(-1)");
+
+ //start and run to check if notify() is emitted
+ if (audioFiles.size() > 0) {
+ QAudioOutput audioOutputCheck(testFormats.at(0), this);
+ audioOutputCheck.setNotifyInterval(0);
+ QSignalSpy notifySignal(&audioOutputCheck, SIGNAL(notify()));
+ audioFiles.at(0)->open(QIODevice::ReadOnly);
+ audioOutputCheck.start(audioFiles.at(0));
+ QTest::qWait(3000); // 3 seconds should be plenty
+ audioOutputCheck.stop();
+ QVERIFY2((notifySignal.count() == 0),
+ QString("didn't disable notify interval: shouldn't have got any but got %1").arg(notifySignal.count()).toLocal8Bit().constData());
+ audioFiles.at(0)->close();
+ }
+}
+
+void tst_QAudioOutput::stopWhileStopped()
+{
+ // Calls QAudioOutput::stop() when object is already in StoppedState
+ // Checks that
+ // - No state change occurs
+ // - No error is raised (QAudioOutput::error() returns QAudio::NoError)
+
+ QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
+
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+
+ QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
+ audioOutput.stop();
+
+ // Check that no state transition occurred
+ QVERIFY2((stateSignal.count() == 0), "stop() while stopped is emitting a signal and it shouldn't");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after stop()");
+}
+
+void tst_QAudioOutput::suspendWhileStopped()
+{
+ // Calls QAudioOutput::suspend() when object is already in StoppedState
+ // Checks that
+ // - No state change occurs
+ // - No error is raised (QAudioOutput::error() returns QAudio::NoError)
+
+ QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
+
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+
+ QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
+ audioOutput.suspend();
+
+ // Check that no state transition occurred
+ QVERIFY2((stateSignal.count() == 0), "stop() while suspended is emitting a signal and it shouldn't");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after stop()");
+}
+
+void tst_QAudioOutput::resumeWhileStopped()
+{
+ // Calls QAudioOutput::resume() when object is already in StoppedState
+ // Checks that
+ // - No state change occurs
+ // - No error is raised (QAudioOutput::error() returns QAudio::NoError)
+
+ QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
+
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+
+ QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
+ audioOutput.resume();
+
+ // Check that no state transition occurred
+ QVERIFY2((stateSignal.count() == 0), "resume() while stopped is emitting a signal and it shouldn't");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after resume()");
+}
+
+void tst_QAudioOutput::pull()
+{
+ for(int i=0; i<audioFiles.count(); i++) {
+ QAudioOutput audioOutput(testFormats.at(i), this);
+
+ audioOutput.setNotifyInterval(100);
+
+ QSignalSpy notifySignal(&audioOutput, SIGNAL(notify()));
+ QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
+
+ // Check that we are in the default state before calling start
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+ QVERIFY2((audioOutput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
+
+ audioFiles.at(i)->close();
+ audioFiles.at(i)->open(QIODevice::ReadOnly);
+ audioFiles.at(i)->seek(WavHeader::headerLength());
+
+ audioOutput.start(audioFiles.at(i));
+ // Check that QAudioOutput immediately transitions to ActiveState
+ QTRY_VERIFY2((stateSignal.count() == 1),
+ QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
+ QVERIFY(audioOutput.periodSize() > 0);
+ stateSignal.clear();
+
+ // Check that 'elapsed' increases
+ QTest::qWait(40);
+ QVERIFY2((audioOutput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()");
+
+ // Wait until playback finishes
+ QTest::qWait(3000); // 3 seconds should be plenty
+
+ QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF");
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF");
+ stateSignal.clear();
+
+ qint64 processedUs = audioOutput.processedUSecs();
+
+ audioOutput.stop();
+ QTest::qWait(40);
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
+
+ QVERIFY2((processedUs == 2000000),
+ QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
+ QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
+ QVERIFY2((notifySignal.count() > 15 && notifySignal.count() < 25),
+ QString("too many notify() signals emitted (%1)").arg(notifySignal.count()).toLocal8Bit().constData());
+
+ audioFiles.at(i)->close();
+ }
+}
+
+void tst_QAudioOutput::pullSuspendResume()
+{
+ for(int i=0; i<audioFiles.count(); i++) {
+ QAudioOutput audioOutput(testFormats.at(i), this);
+
+ audioOutput.setNotifyInterval(100);
+
+ QSignalSpy notifySignal(&audioOutput, SIGNAL(notify()));
+ QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
+
+ // Check that we are in the default state before calling start
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+ QVERIFY2((audioOutput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
+
+ audioFiles.at(i)->close();
+ audioFiles.at(i)->open(QIODevice::ReadOnly);
+ audioFiles.at(i)->seek(WavHeader::headerLength());
+
+ audioOutput.start(audioFiles.at(i));
+ // Check that QAudioOutput immediately transitions to ActiveState
+ QTRY_VERIFY2((stateSignal.count() == 1),
+ QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
+ QVERIFY(audioOutput.periodSize() > 0);
+ stateSignal.clear();
+
+ // Wait for half of clip to play
+ QTest::qWait(1000);
+
+ audioOutput.suspend();
+
+ // Give backends running in separate threads a chance to suspend.
+ QTest::qWait(100);
+
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit SuspendedState signal after suspend(), got %1 signals instead")
+ .arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::SuspendedState), "didn't transition to SuspendedState after suspend()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after suspend()");
+ stateSignal.clear();
+
+ // Check that only 'elapsed', and not 'processed' increases while suspended
+ qint64 elapsedUs = audioOutput.elapsedUSecs();
+ qint64 processedUs = audioOutput.processedUSecs();
+ QTest::qWait(1000);
+ QVERIFY(audioOutput.elapsedUSecs() > elapsedUs);
+ QVERIFY(audioOutput.processedUSecs() == processedUs);
+
+ audioOutput.resume();
+
+ // Give backends running in separate threads a chance to suspend.
+ QTest::qWait(100);
+
+ // Check that QAudioOutput immediately transitions to ActiveState
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit signal after resume(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after resume()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after resume()");
+ stateSignal.clear();
+
+ // Wait until playback finishes
+ QTest::qWait(3000); // 3 seconds should be plenty
+
+ QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF");
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF");
+ stateSignal.clear();
+
+ processedUs = audioOutput.processedUSecs();
+
+ audioOutput.stop();
+ QTest::qWait(40);
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
+
+ QVERIFY2((processedUs == 2000000),
+ QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
+ QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
+
+ audioFiles.at(i)->close();
+ }
+}
+
+void tst_QAudioOutput::push()
+{
+ for(int i=0; i<audioFiles.count(); i++) {
+ QAudioOutput audioOutput(testFormats.at(i), this);
+
+ audioOutput.setNotifyInterval(100);
+
+ QSignalSpy notifySignal(&audioOutput, SIGNAL(notify()));
+ QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
+
+ // Check that we are in the default state before calling start
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+ QVERIFY2((audioOutput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
+
+ audioFiles.at(i)->close();
+ audioFiles.at(i)->open(QIODevice::ReadOnly);
+ audioFiles.at(i)->seek(WavHeader::headerLength());
+
+ QIODevice* feed = audioOutput.start();
+
+ // Check that QAudioOutput immediately transitions to IdleState
+ QTRY_VERIFY2((stateSignal.count() == 1),
+ QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transition to IdleState after start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
+ QVERIFY(audioOutput.periodSize() > 0);
+ stateSignal.clear();
+
+ // Check that 'elapsed' increases
+ QTest::qWait(40);
+ QVERIFY2((audioOutput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()");
+ QVERIFY2((audioOutput.processedUSecs() == qint64(0)), "processedUSecs() is not zero after start()");
+
+ qint64 written = 0;
+ bool firstBuffer = true;
+ QByteArray buffer(AUDIO_BUFFER, 0);
+
+ while (written < audioFiles.at(i)->size()-WavHeader::headerLength()) {
+
+ if (audioOutput.bytesFree() >= audioOutput.periodSize()) {
+ qint64 len = audioFiles.at(i)->read(buffer.data(),audioOutput.periodSize());
+ written += feed->write(buffer.constData(), len);
+
+ if (firstBuffer) {
+ // Check for transition to ActiveState when data is provided
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit signal after receiving data, got %1 signals instead")
+ .arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after receiving data");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after receiving data");
+ firstBuffer = false;
+ }
+ } else
+ QTest::qWait(20);
+ }
+ stateSignal.clear();
+
+ // Wait until playback finishes
+ QTest::qWait(3000); // 3 seconds should be plenty
+
+ QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF");
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF");
+ stateSignal.clear();
+
+ qint64 processedUs = audioOutput.processedUSecs();
+
+ audioOutput.stop();
+ QTest::qWait(40);
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
+
+ QVERIFY2((processedUs == 2000000),
+ QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
+ QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
+ QVERIFY2((notifySignal.count() > 15 && notifySignal.count() < 25),
+ QString("too many notify() signals emitted (%1)").arg(notifySignal.count()).toLocal8Bit().constData());
+
+ audioFiles.at(i)->close();
+ }
+}
+
+void tst_QAudioOutput::pushSuspendResume()
+{
+ for(int i=0; i<audioFiles.count(); i++) {
+ QAudioOutput audioOutput(testFormats.at(i), this);
+
+ audioOutput.setNotifyInterval(100);
+
+ QSignalSpy notifySignal(&audioOutput, SIGNAL(notify()));
+ QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
+
+ // Check that we are in the default state before calling start
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+ QVERIFY2((audioOutput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
+
+ audioFiles.at(i)->close();
+ audioFiles.at(i)->open(QIODevice::ReadOnly);
+ audioFiles.at(i)->seek(WavHeader::headerLength());
+
+ QIODevice* feed = audioOutput.start();
+
+ // Check that QAudioOutput immediately transitions to IdleState
+ QTRY_VERIFY2((stateSignal.count() == 1),
+ QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transition to IdleState after start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
+ QVERIFY(audioOutput.periodSize() > 0);
+ stateSignal.clear();
+
+ // Check that 'elapsed' increases
+ QTest::qWait(40);
+ QVERIFY2((audioOutput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()");
+ QVERIFY2((audioOutput.processedUSecs() == qint64(0)), "processedUSecs() is not zero after start()");
+
+ qint64 written = 0;
+ bool firstBuffer = true;
+ QByteArray buffer(AUDIO_BUFFER, 0);
+
+ // Play half of the clip
+ while (written < (audioFiles.at(i)->size()-WavHeader::headerLength())/2) {
+
+ if (audioOutput.bytesFree() >= audioOutput.periodSize()) {
+ qint64 len = audioFiles.at(i)->read(buffer.data(),audioOutput.periodSize());
+ written += feed->write(buffer.constData(), len);
+
+ if (firstBuffer) {
+ // Check for transition to ActiveState when data is provided
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit signal after receiving data, got %1 signals instead")
+ .arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after receiving data");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after receiving data");
+ firstBuffer = false;
+ }
+ } else
+ QTest::qWait(20);
+ }
+ stateSignal.clear();
+
+ audioOutput.suspend();
+
+ // Give backends running in separate threads a chance to suspend.
+ QTest::qWait(100);
+
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit SuspendedState signal after suspend(), got %1 signals instead")
+ .arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::SuspendedState), "didn't transition to SuspendedState after suspend()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after suspend()");
+ stateSignal.clear();
+
+ // Check that only 'elapsed', and not 'processed' increases while suspended
+ qint64 elapsedUs = audioOutput.elapsedUSecs();
+ qint64 processedUs = audioOutput.processedUSecs();
+ QTest::qWait(1000);
+ QVERIFY(audioOutput.elapsedUSecs() > elapsedUs);
+ QVERIFY(audioOutput.processedUSecs() == processedUs);
+
+ audioOutput.resume();
+
+ // Give backends running in separate threads a chance to suspend.
+ QTest::qWait(100);
+
+ // Check that QAudioOutput immediately transitions to ActiveState
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit signal after resume(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after resume()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after resume()");
+ stateSignal.clear();
+
+ // Play rest of the clip
+ while (!audioFiles.at(i)->atEnd()) {
+ if (audioOutput.bytesFree() >= audioOutput.periodSize()) {
+ qint64 len = audioFiles.at(i)->read(buffer.data(),audioOutput.periodSize());
+ written += feed->write(buffer.constData(), len);
+ } else
+ QTest::qWait(20);
+ }
+ stateSignal.clear();
+
+ // Wait until playback finishes
+ QTest::qWait(1000); // 1 seconds should be plenty
+
+ QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF");
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF");
+ stateSignal.clear();
+
+ processedUs = audioOutput.processedUSecs();
+
+ audioOutput.stop();
+ QTest::qWait(40);
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
+
+ QVERIFY2((processedUs == 2000000),
+ QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
+ QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
+
+ audioFiles.at(i)->close();
+ }
+}
+
+void tst_QAudioOutput::pushUnderrun()
+{
+ for(int i=0; i<audioFiles.count(); i++) {
+ QAudioOutput audioOutput(testFormats.at(i), this);
+
+ audioOutput.setNotifyInterval(100);
+
+ QSignalSpy notifySignal(&audioOutput, SIGNAL(notify()));
+ QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
+
+ // Check that we are in the default state before calling start
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
+ QVERIFY2((audioOutput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
+
+ audioFiles.at(i)->close();
+ audioFiles.at(i)->open(QIODevice::ReadOnly);
+ audioFiles.at(i)->seek(WavHeader::headerLength());
+
+ QIODevice* feed = audioOutput.start();
+
+ // Check that QAudioOutput immediately transitions to IdleState
+ QTRY_VERIFY2((stateSignal.count() == 1),
+ QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transition to IdleState after start()");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
+ QVERIFY(audioOutput.periodSize() > 0);
+ stateSignal.clear();
+
+ // Check that 'elapsed' increases
+ QTest::qWait(40);
+ QVERIFY2((audioOutput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()");
+ QVERIFY2((audioOutput.processedUSecs() == qint64(0)), "processedUSecs() is not zero after start()");
+
+ qint64 written = 0;
+ bool firstBuffer = true;
+ QByteArray buffer(AUDIO_BUFFER, 0);
+
+ // Play half of the clip
+ while (written < (audioFiles.at(i)->size()-WavHeader::headerLength())/2) {
+
+ if (audioOutput.bytesFree() >= audioOutput.periodSize()) {
+ qint64 len = audioFiles.at(i)->read(buffer.data(),audioOutput.periodSize());
+ written += feed->write(buffer.constData(), len);
+
+ if (firstBuffer) {
+ // Check for transition to ActiveState when data is provided
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit signal after receiving data, got %1 signals instead")
+ .arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after receiving data");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after receiving data");
+ firstBuffer = false;
+ }
+ } else
+ QTest::qWait(20);
+ }
+ stateSignal.clear();
+
+ // Wait for data to be played
+ QTest::qWait(1000);
+
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit IdleState signal after suspend(), got %1 signals instead")
+ .arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transition to IdleState, no data");
+ QVERIFY2((audioOutput.error() == QAudio::UnderrunError), "error state is not equal to QAudio::UnderrunError, no data");
+ stateSignal.clear();
+
+ firstBuffer = true;
+ // Play rest of the clip
+ while (!audioFiles.at(i)->atEnd()) {
+ if (audioOutput.bytesFree() >= audioOutput.periodSize()) {
+ qint64 len = audioFiles.at(i)->read(buffer.data(),audioOutput.periodSize());
+ written += feed->write(buffer.constData(), len);
+ if (firstBuffer) {
+ // Check for transition to ActiveState when data is provided
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit signal after receiving data, got %1 signals instead")
+ .arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after receiving data");
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after receiving data");
+ firstBuffer = false;
+ }
+ } else
+ QTest::qWait(20);
+ }
+ stateSignal.clear();
+
+ // Wait until playback finishes
+ QTest::qWait(1000); // 1 seconds should be plenty
+
+ QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF");
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF");
+ stateSignal.clear();
+
+ qint64 processedUs = audioOutput.processedUSecs();
+
+ audioOutput.stop();
+ QTest::qWait(40);
+ QVERIFY2((stateSignal.count() == 1),
+ QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
+
+ QVERIFY2((processedUs == 2000000),
+ QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData());
+ QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
+ QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
+
+ audioFiles.at(i)->close();
+ }
+}
+
+void tst_QAudioOutput::cleanupTestCase()
+{
+ QFile* file;
+
+ foreach (file, audioFiles) {
+ file->remove();
+ delete file;
+ }
+}
+
+QTEST_MAIN(tst_QAudioOutput)
+
+#include "tst_qaudiooutput.moc"
diff --git a/tests/auto/qaudiooutput/wavheader.cpp b/tests/auto/qaudiooutput/wavheader.cpp
new file mode 100755
index 000000000..26fcd6f98
--- /dev/null
+++ b/tests/auto/qaudiooutput/wavheader.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** 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 test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qendian.h>
+#include "wavheader.h"
+
+
+struct chunk
+{
+ char id[4];
+ quint32 size;
+};
+
+struct RIFFHeader
+{
+ chunk descriptor; // "RIFF"
+ char type[4]; // "WAVE"
+};
+
+struct WAVEHeader
+{
+ chunk descriptor;
+ quint16 audioFormat;
+ quint16 numChannels;
+ quint32 sampleRate;
+ quint32 byteRate;
+ quint16 blockAlign;
+ quint16 bitsPerSample;
+};
+
+struct DATAHeader
+{
+ chunk descriptor;
+};
+
+struct CombinedHeader
+{
+ RIFFHeader riff;
+ WAVEHeader wave;
+ DATAHeader data;
+};
+
+static const int HeaderLength = sizeof(CombinedHeader);
+
+
+WavHeader::WavHeader(const QAudioFormat &format, qint64 dataLength)
+ : m_format(format)
+ , m_dataLength(dataLength)
+{
+
+}
+
+bool WavHeader::read(QIODevice &device)
+{
+ bool result = true;
+
+ if (!device.isSequential())
+ result = device.seek(0);
+ // else, assume that current position is the start of the header
+
+ if (result) {
+ CombinedHeader header;
+ result = (device.read(reinterpret_cast<char *>(&header), HeaderLength) == HeaderLength);
+ if (result) {
+ if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0
+ || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0)
+ && memcmp(&header.riff.type, "WAVE", 4) == 0
+ && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0
+ && header.wave.audioFormat == 1 // PCM
+ ) {
+ if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
+ m_format.setByteOrder(QAudioFormat::LittleEndian);
+ else
+ m_format.setByteOrder(QAudioFormat::BigEndian);
+
+ m_format.setChannels(qFromLittleEndian<quint16>(header.wave.numChannels));
+ m_format.setCodec("audio/pcm");
+ m_format.setFrequency(qFromLittleEndian<quint32>(header.wave.sampleRate));
+ m_format.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample));
+
+ switch(header.wave.bitsPerSample) {
+ case 8:
+ m_format.setSampleType(QAudioFormat::UnSignedInt);
+ break;
+ case 16:
+ m_format.setSampleType(QAudioFormat::SignedInt);
+ break;
+ default:
+ result = false;
+ }
+
+ m_dataLength = device.size() - HeaderLength;
+ } else {
+ result = false;
+ }
+ }
+ }
+
+ return result;
+}
+
+bool WavHeader::write(QIODevice &device)
+{
+ CombinedHeader header;
+
+ memset(&header, 0, HeaderLength);
+
+ // RIFF header
+ if (m_format.byteOrder() == QAudioFormat::LittleEndian)
+ memcpy(header.riff.descriptor.id,"RIFF",4);
+ else
+ memcpy(header.riff.descriptor.id,"RIFX",4);
+ qToLittleEndian<quint32>(quint32(m_dataLength + HeaderLength - 8),
+ reinterpret_cast<unsigned char*>(&header.riff.descriptor.size));
+ memcpy(header.riff.type, "WAVE",4);
+
+ // WAVE header
+ memcpy(header.wave.descriptor.id,"fmt ",4);
+ qToLittleEndian<quint32>(quint32(16),
+ reinterpret_cast<unsigned char*>(&header.wave.descriptor.size));
+ qToLittleEndian<quint16>(quint16(1),
+ reinterpret_cast<unsigned char*>(&header.wave.audioFormat));
+ qToLittleEndian<quint16>(quint16(m_format.channels()),
+ reinterpret_cast<unsigned char*>(&header.wave.numChannels));
+ qToLittleEndian<quint32>(quint32(m_format.frequency()),
+ reinterpret_cast<unsigned char*>(&header.wave.sampleRate));
+ qToLittleEndian<quint32>(quint32(m_format.frequency() * m_format.channels() * m_format.sampleSize() / 8),
+ reinterpret_cast<unsigned char*>(&header.wave.byteRate));
+ qToLittleEndian<quint16>(quint16(m_format.channels() * m_format.sampleSize() / 8),
+ reinterpret_cast<unsigned char*>(&header.wave.blockAlign));
+ qToLittleEndian<quint16>(quint16(m_format.sampleSize()),
+ reinterpret_cast<unsigned char*>(&header.wave.bitsPerSample));
+
+ // DATA header
+ memcpy(header.data.descriptor.id,"data",4);
+ qToLittleEndian<quint32>(quint32(m_dataLength),
+ reinterpret_cast<unsigned char*>(&header.data.descriptor.size));
+
+ return (device.write(reinterpret_cast<const char *>(&header), HeaderLength) == HeaderLength);
+}
+
+const QAudioFormat& WavHeader::format() const
+{
+ return m_format;
+}
+
+qint64 WavHeader::dataLength() const
+{
+ return m_dataLength;
+}
+
+qint64 WavHeader::headerLength()
+{
+ return HeaderLength;
+}
+
+bool WavHeader::writeDataLength(QIODevice &device, qint64 dataLength)
+{
+ bool result = false;
+ if (!device.isSequential()) {
+ device.seek(40);
+ unsigned char dataLengthLE[4];
+ qToLittleEndian<quint32>(quint32(dataLength), dataLengthLE);
+ result = (device.write(reinterpret_cast<const char *>(dataLengthLE), 4) == 4);
+ }
+ return result;
+}
diff --git a/tests/auto/qaudiooutput/wavheader.h b/tests/auto/qaudiooutput/wavheader.h
new file mode 100755
index 000000000..5212eca67
--- /dev/null
+++ b/tests/auto/qaudiooutput/wavheader.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef WAVHEADER_H
+#define WAVHEADER_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qfile.h>
+#include <qaudioformat.h>
+
+/**
+ * Helper class for parsing WAV file headers.
+ *
+ * See https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
+ */
+class WavHeader
+{
+public:
+ WavHeader(const QAudioFormat &format = QAudioFormat(),
+ qint64 dataLength = 0);
+
+ // Reads WAV header and seeks to start of data
+ bool read(QIODevice &device);
+
+ // Writes WAV header
+ bool write(QIODevice &device);
+
+ const QAudioFormat& format() const;
+ qint64 dataLength() const;
+
+ static qint64 headerLength();
+
+ static bool writeDataLength(QIODevice &device, qint64 dataLength);
+
+private:
+ QAudioFormat m_format;
+ qint64 m_dataLength;
+};
+
+#endif
+
diff --git a/tests/auto/qcamera/qcamera.pro b/tests/auto/qcamera/qcamera.pro
new file mode 100644
index 000000000..6ebbe3182
--- /dev/null
+++ b/tests/auto/qcamera/qcamera.pro
@@ -0,0 +1,15 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qcamera
+# CONFIG += testcase
+
+SOURCES += tst_qcamera.cpp
+
+symbian {
+ TARGET.CAPABILITY = ALL -TCB
+ TARGET.EPOCHEAPSIZE = 0x20000 0x3000000
+}
+
+maemo*:CONFIG += insignificant_test
diff --git a/tests/auto/qcamera/tst_qcamera.cpp b/tests/auto/qcamera/tst_qcamera.cpp
new file mode 100644
index 000000000..010309a0d
--- /dev/null
+++ b/tests/auto/qcamera/tst_qcamera.cpp
@@ -0,0 +1,2012 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <QtTest/QtTest>
+#include <QDebug>
+
+#include <qabstractvideosurface.h>
+#include <qcameracontrol.h>
+#include <qcameralockscontrol.h>
+#include <qcameraexposurecontrol.h>
+#include <qcameraflashcontrol.h>
+#include <qcamerafocuscontrol.h>
+#include <qcameraimagecapturecontrol.h>
+#include <qimageencodercontrol.h>
+#include <qcameraimageprocessingcontrol.h>
+#include <qcameracapturebufferformatcontrol.h>
+#include <qcameracapturedestinationcontrol.h>
+#include <qmediaservice.h>
+#include <qcamera.h>
+#include <qcameraimagecapture.h>
+#include <qgraphicsvideoitem.h>
+#include <qvideorenderercontrol.h>
+#include <qvideowidget.h>
+#include <qvideowindowcontrol.h>
+
+QT_USE_NAMESPACE
+class MockCaptureControl;
+
+Q_DECLARE_METATYPE(QtMultimediaKit::MetaData)
+
+class MockCameraControl : public QCameraControl
+{
+ friend class MockCaptureControl;
+ Q_OBJECT
+public:
+ MockCameraControl(QObject *parent = 0):
+ QCameraControl(parent),
+ m_state(QCamera::UnloadedState),
+ m_captureMode(QCamera::CaptureStillImage),
+ m_status(QCamera::UnloadedStatus),
+ m_propertyChangesSupported(false)
+ {
+ }
+
+ ~MockCameraControl() {}
+
+ void start() { m_state = QCamera::ActiveState; }
+ virtual void stop() { m_state = QCamera::UnloadedState; }
+ QCamera::State state() const { return m_state; }
+ void setState(QCamera::State state) {
+ if (m_state != state) {
+ m_state = state;
+
+ switch (state) {
+ case QCamera::UnloadedState:
+ m_status = QCamera::UnloadedStatus;
+ break;
+ case QCamera::LoadedState:
+ m_status = QCamera::LoadedStatus;
+ break;
+ case QCamera::ActiveState:
+ m_status = QCamera::ActiveStatus;
+ break;
+ default:
+ emit error(QCamera::NotSupportedFeatureError, "State not supported.");
+ return;
+ }
+
+ emit stateChanged(m_state);
+ emit statusChanged(m_status);
+ }
+ }
+
+ QCamera::Status status() const { return m_status; }
+
+ QCamera::CaptureMode captureMode() const { return m_captureMode; }
+ void setCaptureMode(QCamera::CaptureMode mode)
+ {
+ if (m_captureMode != mode) {
+ if (m_state == QCamera::ActiveState)
+ QVERIFY(m_propertyChangesSupported);
+ m_captureMode = mode;
+ emit captureModeChanged(mode);
+ }
+ }
+
+ bool isCaptureModeSupported(QCamera::CaptureMode mode) const
+ {
+ return mode == QCamera::CaptureStillImage || mode == QCamera::CaptureVideo;
+ }
+
+ QCamera::LockTypes supportedLocks() const
+ {
+ return QCamera::LockExposure | QCamera::LockFocus | QCamera::LockWhiteBalance;
+ }
+
+ bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const
+ {
+ Q_UNUSED(changeType);
+ Q_UNUSED(status);
+ return m_propertyChangesSupported;
+ }
+
+ QCamera::State m_state;
+ QCamera::CaptureMode m_captureMode;
+ QCamera::Status m_status;
+ bool m_propertyChangesSupported;
+};
+
+
+class MockCameraLocksControl : public QCameraLocksControl
+{
+ Q_OBJECT
+public:
+ MockCameraLocksControl(QObject *parent = 0):
+ QCameraLocksControl(parent),
+ m_focusLock(QCamera::Unlocked),
+ m_exposureLock(QCamera::Unlocked)
+ {
+ }
+
+ ~MockCameraLocksControl() {}
+
+ QCamera::LockTypes supportedLocks() const
+ {
+ return QCamera::LockExposure | QCamera::LockFocus;
+ }
+
+ QCamera::LockStatus lockStatus(QCamera::LockType lock) const
+ {
+ switch (lock) {
+ case QCamera::LockExposure:
+ return m_exposureLock;
+ case QCamera::LockFocus:
+ return m_focusLock;
+ default:
+ return QCamera::Unlocked;
+ }
+ }
+
+ void searchAndLock(QCamera::LockTypes locks)
+ {
+ if (locks & QCamera::LockExposure) {
+ QCamera::LockStatus newStatus = locks & QCamera::LockFocus ? QCamera::Searching : QCamera::Locked;
+
+ if (newStatus != m_exposureLock)
+ emit lockStatusChanged(QCamera::LockExposure,
+ m_exposureLock = newStatus,
+ QCamera::UserRequest);
+ }
+
+ if (locks & QCamera::LockFocus) {
+ emit lockStatusChanged(QCamera::LockFocus,
+ m_focusLock = QCamera::Searching,
+ QCamera::UserRequest);
+
+ QTimer::singleShot(5, this, SLOT(focused()));
+ }
+ }
+
+ void unlock(QCamera::LockTypes locks) {
+ if (locks & QCamera::LockFocus && m_focusLock != QCamera::Unlocked) {
+ emit lockStatusChanged(QCamera::LockFocus,
+ m_focusLock = QCamera::Unlocked,
+ QCamera::UserRequest);
+ }
+
+ if (locks & QCamera::LockExposure && m_exposureLock != QCamera::Unlocked) {
+ emit lockStatusChanged(QCamera::LockExposure,
+ m_exposureLock = QCamera::Unlocked,
+ QCamera::UserRequest);
+ }
+ }
+
+private slots:
+ void focused()
+ {
+ if (m_focusLock == QCamera::Searching) {
+ emit lockStatusChanged(QCamera::LockFocus,
+ m_focusLock = QCamera::Locked,
+ QCamera::UserRequest);
+ }
+
+ if (m_exposureLock == QCamera::Searching) {
+ emit lockStatusChanged(QCamera::LockExposure,
+ m_exposureLock = QCamera::Locked,
+ QCamera::UserRequest);
+ }
+ }
+
+
+private:
+ QCamera::LockStatus m_focusLock;
+ QCamera::LockStatus m_exposureLock;
+};
+
+class MockCaptureControl : public QCameraImageCaptureControl
+{
+ Q_OBJECT
+public:
+ MockCaptureControl(MockCameraControl *cameraControl, QObject *parent = 0)
+ :QCameraImageCaptureControl(parent), m_cameraControl(cameraControl), m_captureRequest(0), m_ready(true), m_captureCanceled(false)
+ {
+ }
+
+ ~MockCaptureControl()
+ {
+ }
+
+ QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; }
+ void setDriveMode(QCameraImageCapture::DriveMode) {}
+
+ bool isReadyForCapture() const { return m_ready && m_cameraControl->state() == QCamera::ActiveState; }
+
+ int capture(const QString &fileName)
+ {
+ if (isReadyForCapture()) {
+ m_fileName = fileName;
+ m_captureRequest++;
+ emit readyForCaptureChanged(m_ready = false);
+ QTimer::singleShot(5, this, SLOT(captured()));
+ return m_captureRequest;
+ } else {
+ emit error(-1, QCameraImageCapture::NotReadyError,
+ QLatin1String("Could not capture in stopped state"));
+ }
+
+ return -1;
+ }
+
+ void cancelCapture()
+ {
+ m_captureCanceled = true;
+ }
+
+private Q_SLOTS:
+ void captured()
+ {
+ if (!m_captureCanceled) {
+ emit imageCaptured(m_captureRequest, QImage());
+
+ emit imageMetadataAvailable(m_captureRequest,
+ QtMultimediaKit::FocalLengthIn35mmFilm,
+ QVariant(50));
+
+ emit imageMetadataAvailable(m_captureRequest,
+ QtMultimediaKit::DateTimeOriginal,
+ QVariant(QDateTime::currentDateTime()));
+
+ emit imageMetadataAvailable(m_captureRequest,
+ QLatin1String("Answer to the Ultimate Question of Life, the Universe, and Everything"),
+ QVariant(42));
+ }
+
+ if (!m_ready)
+ emit readyForCaptureChanged(m_ready = true);
+
+ if (!m_captureCanceled)
+ emit imageSaved(m_captureRequest, m_fileName);
+
+ m_captureCanceled = false;
+ }
+
+private:
+ MockCameraControl *m_cameraControl;
+ QString m_fileName;
+ int m_captureRequest;
+ bool m_ready;
+ bool m_captureCanceled;
+};
+
+class MockCaptureDestinationControl : public QCameraCaptureDestinationControl
+{
+ Q_OBJECT
+public:
+ MockCaptureDestinationControl(QObject *parent = 0):
+ QCameraCaptureDestinationControl(parent),
+ m_destination(QCameraImageCapture::CaptureToFile)
+ {
+ }
+
+ bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const
+ {
+ return destination == QCameraImageCapture::CaptureToBuffer ||
+ destination == QCameraImageCapture::CaptureToFile;
+ }
+
+ QCameraImageCapture::CaptureDestinations captureDestination() const
+ {
+ return m_destination;
+ }
+
+ void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination)
+ {
+ if (isCaptureDestinationSupported(destination) && destination != m_destination) {
+ m_destination = destination;
+ emit captureDestinationChanged(m_destination);
+ }
+ }
+
+private:
+ QCameraImageCapture::CaptureDestinations m_destination;
+};
+
+class MockCaptureBufferFormatControl : public QCameraCaptureBufferFormatControl
+{
+ Q_OBJECT
+public:
+ MockCaptureBufferFormatControl(QObject *parent = 0):
+ QCameraCaptureBufferFormatControl(parent),
+ m_format(QVideoFrame::Format_Jpeg)
+ {
+ }
+
+ QList<QVideoFrame::PixelFormat> supportedBufferFormats() const
+ {
+ return QList<QVideoFrame::PixelFormat>()
+ << QVideoFrame::Format_Jpeg
+ << QVideoFrame::Format_RGB32
+ << QVideoFrame::Format_AdobeDng;
+ }
+
+ QVideoFrame::PixelFormat bufferFormat() const
+ {
+ return m_format;
+ }
+
+ void setBufferFormat(QVideoFrame::PixelFormat format)
+ {
+ if (format != m_format && supportedBufferFormats().contains(format)) {
+ m_format = format;
+ emit bufferFormatChanged(m_format);
+ }
+ }
+
+private:
+ QVideoFrame::PixelFormat m_format;
+};
+
+class MockCameraExposureControl : public QCameraExposureControl
+{
+ Q_OBJECT
+public:
+ MockCameraExposureControl(QObject *parent = 0):
+ QCameraExposureControl(parent),
+ m_aperture(2.8),
+ m_shutterSpeed(0.01),
+ m_isoSensitivity(100),
+ m_meteringMode(QCameraExposure::MeteringMatrix),
+ m_exposureCompensation(0),
+ m_exposureMode(QCameraExposure::ExposureAuto),
+ m_flashMode(QCameraExposure::FlashAuto)
+ {
+ }
+
+ ~MockCameraExposureControl() {}
+
+ QCameraExposure::FlashModes flashMode() const
+ {
+ return m_flashMode;
+ }
+
+ void setFlashMode(QCameraExposure::FlashModes mode)
+ {
+ if (isFlashModeSupported(mode)) {
+ m_flashMode = mode;
+ }
+ }
+
+ bool isFlashModeSupported(QCameraExposure::FlashModes mode) const
+ {
+ return mode & (QCameraExposure::FlashAuto | QCameraExposure::FlashOff | QCameraExposure::FlashOn);
+ }
+
+ bool isFlashReady() const
+ {
+ return true;
+ }
+
+ QCameraExposure::ExposureMode exposureMode() const
+ {
+ return m_exposureMode;
+ }
+
+ void setExposureMode(QCameraExposure::ExposureMode mode)
+ {
+ if (isExposureModeSupported(mode))
+ m_exposureMode = mode;
+ }
+
+ bool isExposureModeSupported(QCameraExposure::ExposureMode mode) const
+ {
+ return mode == QCameraExposure::ExposureAuto ||
+ mode == QCameraExposure::ExposureManual;
+ }
+
+ bool isParameterSupported(ExposureParameter parameter) const
+ {
+ switch (parameter) {
+ case QCameraExposureControl::ExposureCompensation:
+ case QCameraExposureControl::ISO:
+ case QCameraExposureControl::Aperture:
+ case QCameraExposureControl::ShutterSpeed:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ QVariant exposureParameter(ExposureParameter parameter) const
+ {
+ switch (parameter) {
+ case QCameraExposureControl::ExposureCompensation:
+ return QVariant(m_exposureCompensation);
+ case QCameraExposureControl::ISO:
+ return QVariant(m_isoSensitivity);
+ case QCameraExposureControl::Aperture:
+ return QVariant(m_aperture);
+ case QCameraExposureControl::ShutterSpeed:
+ return QVariant(m_shutterSpeed);
+ default:
+ return QVariant();
+ }
+ }
+
+ QVariantList supportedParameterRange(ExposureParameter parameter) const
+ {
+ QVariantList res;
+ switch (parameter) {
+ case QCameraExposureControl::ExposureCompensation:
+ res << -2.0 << 2.0;
+ break;
+ case QCameraExposureControl::ISO:
+ res << 100 << 200 << 400 << 800;
+ break;
+ case QCameraExposureControl::Aperture:
+ res << 2.8 << 4.0 << 5.6 << 8.0 << 11.0 << 16.0;
+ break;
+ case QCameraExposureControl::ShutterSpeed:
+ res << 0.001 << 0.01 << 0.1 << 1.0;
+ break;
+ default:
+ break;
+ }
+
+ return res;
+ }
+
+ ParameterFlags exposureParameterFlags(ExposureParameter parameter) const
+ {
+ ParameterFlags res = 0;
+ switch (parameter) {
+ case QCameraExposureControl::ExposureCompensation:
+ case QCameraExposureControl::Aperture:
+ case QCameraExposureControl::ShutterSpeed:
+ res |= ContinuousRange;
+ default:
+ break;
+ }
+
+ return res;
+ }
+
+ bool setExposureParameter(ExposureParameter parameter, const QVariant& value)
+ {
+ switch (parameter) {
+ case QCameraExposureControl::ExposureCompensation:
+ m_exposureCompensation = qBound<qreal>(-2.0, value.toReal(), 2.0);
+ break;
+ case QCameraExposureControl::ISO:
+ m_isoSensitivity = 100*qRound(qBound(100, value.toInt(), 800)/100.0);
+ break;
+ case QCameraExposureControl::Aperture:
+ m_aperture = qBound<qreal>(2.8, value.toReal(), 16.0);
+ break;
+ case QCameraExposureControl::ShutterSpeed:
+ m_shutterSpeed = qBound<qreal>(0.001, value.toReal(), 1.0);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+ }
+
+ QString extendedParameterName(ExposureParameter)
+ {
+ return QString();
+ }
+
+ QCameraExposure::MeteringMode meteringMode() const
+ {
+ return m_meteringMode;
+ }
+
+ void setMeteringMode(QCameraExposure::MeteringMode mode)
+ {
+ if (isMeteringModeSupported(mode))
+ m_meteringMode = mode;
+ }
+
+ bool isMeteringModeSupported(QCameraExposure::MeteringMode mode) const
+ {
+ return mode == QCameraExposure::MeteringAverage
+ || mode == QCameraExposure::MeteringMatrix;
+ }
+
+private:
+ qreal m_aperture;
+ qreal m_shutterSpeed;
+ int m_isoSensitivity;
+ QCameraExposure::MeteringMode m_meteringMode;
+ qreal m_exposureCompensation;
+ QCameraExposure::ExposureMode m_exposureMode;
+ QCameraExposure::FlashModes m_flashMode;
+};
+
+class MockCameraFlashControl : public QCameraFlashControl
+{
+ Q_OBJECT
+public:
+ MockCameraFlashControl(QObject *parent = 0):
+ QCameraFlashControl(parent),
+ m_flashMode(QCameraExposure::FlashAuto)
+ {
+ }
+
+ ~MockCameraFlashControl() {}
+
+ QCameraExposure::FlashModes flashMode() const
+ {
+ return m_flashMode;
+ }
+
+ void setFlashMode(QCameraExposure::FlashModes mode)
+ {
+ if (isFlashModeSupported(mode)) {
+ m_flashMode = mode;
+ }
+ }
+
+ bool isFlashModeSupported(QCameraExposure::FlashModes mode) const
+ {
+ return mode & (QCameraExposure::FlashAuto | QCameraExposure::FlashOff | QCameraExposure::FlashOn);
+ }
+
+ bool isFlashReady() const
+ {
+ return true;
+ }
+
+private:
+ QCameraExposure::FlashModes m_flashMode;
+};
+
+
+class MockCameraFocusControl : public QCameraFocusControl
+{
+ Q_OBJECT
+public:
+ MockCameraFocusControl(QObject *parent = 0):
+ QCameraFocusControl(parent),
+ m_opticalZoom(1.0),
+ m_digitalZoom(1.0),
+ m_focusMode(QCameraFocus::AutoFocus),
+ m_focusPointMode(QCameraFocus::FocusPointAuto),
+ m_focusPoint(0.5, 0.5)
+ {
+ }
+
+ ~MockCameraFocusControl() {}
+
+ QCameraFocus::FocusMode focusMode() const
+ {
+ return m_focusMode;
+ }
+
+ void setFocusMode(QCameraFocus::FocusMode mode)
+ {
+ if (isFocusModeSupported(mode))
+ m_focusMode = mode;
+ }
+
+ bool isFocusModeSupported(QCameraFocus::FocusMode mode) const
+ {
+ return mode == QCameraFocus::AutoFocus || mode == QCameraFocus::ContinuousFocus;
+ }
+
+ qreal maximumOpticalZoom() const
+ {
+ return 3.0;
+ }
+
+ qreal maximumDigitalZoom() const
+ {
+ return 4.0;
+ }
+
+ qreal opticalZoom() const
+ {
+ return m_opticalZoom;
+ }
+
+ qreal digitalZoom() const
+ {
+ return m_digitalZoom;
+ }
+
+ void zoomTo(qreal optical, qreal digital)
+ {
+ optical = qBound<qreal>(1.0, optical, maximumOpticalZoom());
+ digital = qBound<qreal>(1.0, digital, maximumDigitalZoom());
+
+ if (!qFuzzyCompare(digital, m_digitalZoom)) {
+ m_digitalZoom = digital;
+ emit digitalZoomChanged(m_digitalZoom);
+ }
+
+ if (!qFuzzyCompare(optical, m_opticalZoom)) {
+ m_opticalZoom = optical;
+ emit opticalZoomChanged(m_opticalZoom);
+ }
+ }
+
+ QCameraFocus::FocusPointMode focusPointMode() const
+ {
+ return m_focusPointMode;
+ }
+
+ void setFocusPointMode(QCameraFocus::FocusPointMode mode)
+ {
+ if (isFocusPointModeSupported(mode))
+ m_focusPointMode = mode;
+ }
+
+ bool isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const
+ {
+ switch (mode) {
+ case QCameraFocus::FocusPointAuto:
+ case QCameraFocus::FocusPointCenter:
+ case QCameraFocus::FocusPointCustom:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ QPointF customFocusPoint() const
+ {
+ return m_focusPoint;
+ }
+
+ void setCustomFocusPoint(const QPointF &point)
+ {
+ m_focusPoint = point;
+ }
+
+ QCameraFocusZoneList focusZones() const { return QCameraFocusZoneList() << QCameraFocusZone(QRectF(0.45, 0.45, 0.1, 0.1)); }
+
+
+private:
+ qreal m_opticalZoom;
+ qreal m_digitalZoom;
+ QCameraFocus::FocusMode m_focusMode;
+ QCameraFocus::FocusPointMode m_focusPointMode;
+ QPointF m_focusPoint;
+};
+
+class MockImageProcessingControl : public QCameraImageProcessingControl
+{
+ Q_OBJECT
+public:
+ MockImageProcessingControl(QObject *parent = 0)
+ : QCameraImageProcessingControl(parent)
+ {
+ m_supportedWhiteBalance.insert(QCameraImageProcessing::WhiteBalanceAuto);
+ }
+
+ QCameraImageProcessing::WhiteBalanceMode whiteBalanceMode() const { return m_whiteBalanceMode; }
+ void setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode) { m_whiteBalanceMode = mode; }
+
+ bool isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const {
+ return m_supportedWhiteBalance.contains(mode); }
+
+ void setSupportedWhiteBalanceModes(QSet<QCameraImageProcessing::WhiteBalanceMode> modes) {
+ m_supportedWhiteBalance = modes; }
+
+ bool isProcessingParameterSupported(ProcessingParameter parameter) const
+ {
+ return parameter == Contrast || parameter == Sharpening || parameter == ColorTemperature;
+ }
+ QVariant processingParameter(ProcessingParameter parameter) const
+ {
+ switch (parameter) {
+ case Contrast:
+ return m_contrast;
+ case Sharpening:
+ return m_sharpeningLevel;
+ case ColorTemperature:
+ return m_manualWhiteBalance;
+ default:
+ return QVariant();
+ }
+ }
+ void setProcessingParameter(ProcessingParameter parameter, QVariant value)
+ {
+ switch (parameter) {
+ case Contrast:
+ m_contrast = value;
+ break;
+ case Sharpening:
+ m_sharpeningLevel = value;
+ break;
+ case ColorTemperature:
+ m_manualWhiteBalance = value;
+ break;
+ default:
+ break;
+ }
+ }
+
+
+private:
+ QCameraImageProcessing::WhiteBalanceMode m_whiteBalanceMode;
+ QSet<QCameraImageProcessing::WhiteBalanceMode> m_supportedWhiteBalance;
+ QVariant m_manualWhiteBalance;
+ QVariant m_contrast;
+ QVariant m_sharpeningLevel;
+};
+
+class MockImageEncoderControl : public QImageEncoderControl
+{
+public:
+ MockImageEncoderControl(QObject *parent = 0)
+ : QImageEncoderControl(parent)
+ {
+ }
+
+ QList<QSize> supportedResolutions(const QImageEncoderSettings & = QImageEncoderSettings(),
+ bool *continuous = 0) const
+ {
+ if (continuous)
+ *continuous = true;
+
+ return m_supportedResolutions;
+ }
+
+ void setSupportedResolutions(const QList<QSize> &resolutions) {
+ m_supportedResolutions = resolutions; }
+
+ QStringList supportedImageCodecs() const { return m_supportedCodecs; }
+ void setSupportedImageCodecs(const QStringList &codecs) { m_supportedCodecs = codecs; }
+
+ QString imageCodecDescription(const QString &codecName) const {
+ return m_codecDescriptions.value(codecName); }
+ void setImageCodecDescriptions(const QMap<QString, QString> &descriptions) {
+ m_codecDescriptions = descriptions; }
+
+ QImageEncoderSettings imageSettings() const { return m_settings; }
+ void setImageSettings(const QImageEncoderSettings &settings) { m_settings = settings; }
+
+private:
+ QImageEncoderSettings m_settings;
+
+ QList<QSize> m_supportedResolutions;
+ QStringList m_supportedCodecs;
+ QMap<QString, QString> m_codecDescriptions;
+};
+
+class MockVideoSurface : public QAbstractVideoSurface
+{
+public:
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ const QAbstractVideoBuffer::HandleType) const
+ {
+ return QList<QVideoFrame::PixelFormat>();
+ }
+
+ bool present(const QVideoFrame &) { return false; }
+};
+
+class MockVideoRendererControl : public QVideoRendererControl
+{
+public:
+ MockVideoRendererControl(QObject *parent) : QVideoRendererControl(parent), m_surface(0) {}
+
+ QAbstractVideoSurface *surface() const { return m_surface; }
+ void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; }
+
+ QAbstractVideoSurface *m_surface;
+};
+
+class MockVideoWindowControl : public QVideoWindowControl
+{
+public:
+ MockVideoWindowControl(QObject *parent) : QVideoWindowControl(parent) {}
+ WId winId() const { return 0; }
+ void setWinId(WId) {}
+ QRect displayRect() const { return QRect(); }
+ void setDisplayRect(const QRect &) {}
+ bool isFullScreen() const { return false; }
+ void setFullScreen(bool) {}
+ void repaint() {}
+ QSize nativeSize() const { return QSize(); }
+ Qt::AspectRatioMode aspectRatioMode() const { return Qt::KeepAspectRatio; }
+ void setAspectRatioMode(Qt::AspectRatioMode) {}
+ int brightness() const { return 0; }
+ void setBrightness(int) {}
+ int contrast() const { return 0; }
+ void setContrast(int) {}
+ int hue() const { return 0; }
+ void setHue(int) {}
+ int saturation() const { return 0; }
+ void setSaturation(int) {}
+};
+
+class MockSimpleCameraService : public QMediaService
+{
+ Q_OBJECT
+
+public:
+ MockSimpleCameraService(): QMediaService(0)
+ {
+ mockControl = new MockCameraControl(this);
+ }
+
+ ~MockSimpleCameraService()
+ {
+ }
+
+ QMediaControl* requestControl(const char *iid)
+ {
+ if (qstrcmp(iid, QCameraControl_iid) == 0)
+ return mockControl;
+ return 0;
+ }
+
+ void releaseControl(QMediaControl*) {}
+
+ MockCameraControl *mockControl;
+};
+
+class MockCameraService : public QMediaService
+{
+ Q_OBJECT
+
+public:
+ MockCameraService(): QMediaService(0)
+ {
+ mockControl = new MockCameraControl(this);
+ mockLocksControl = new MockCameraLocksControl(this);
+ mockExposureControl = new MockCameraExposureControl(this);
+ mockFlashControl = new MockCameraFlashControl(this);
+ mockFocusControl = new MockCameraFocusControl(this);
+ mockCaptureControl = new MockCaptureControl(mockControl, this);
+ mockCaptureBufferControl = new MockCaptureBufferFormatControl(this);
+ mockCaptureDestinationControl = new MockCaptureDestinationControl(this);
+ mockImageProcessingControl = new MockImageProcessingControl(this);
+ mockImageEncoderControl = new MockImageEncoderControl(this);
+ rendererControl = new MockVideoRendererControl(this);
+ windowControl = new MockVideoWindowControl(this);
+ rendererRef = 0;
+ windowRef = 0;
+ }
+
+ ~MockCameraService()
+ {
+ }
+
+ QMediaControl* requestControl(const char *iid)
+ {
+ if (qstrcmp(iid, QCameraControl_iid) == 0)
+ return mockControl;
+
+ if (qstrcmp(iid, QCameraLocksControl_iid) == 0)
+ return mockLocksControl;
+
+ if (qstrcmp(iid, QCameraExposureControl_iid) == 0)
+ return mockExposureControl;
+
+ if (qstrcmp(iid, QCameraFlashControl_iid) == 0)
+ return mockFlashControl;
+
+ if (qstrcmp(iid, QCameraFocusControl_iid) == 0)
+ return mockFocusControl;
+
+ if (qstrcmp(iid, QCameraImageCaptureControl_iid) == 0)
+ return mockCaptureControl;
+
+ if (qstrcmp(iid, QCameraCaptureBufferFormatControl_iid) == 0)
+ return mockCaptureBufferControl;
+
+ if (qstrcmp(iid, QCameraCaptureDestinationControl_iid) == 0)
+ return mockCaptureDestinationControl;
+
+ if (qstrcmp(iid, QCameraImageProcessingControl_iid) == 0)
+ return mockImageProcessingControl;
+
+ if (qstrcmp(iid, QImageEncoderControl_iid) == 0)
+ return mockImageEncoderControl;
+
+ if (qstrcmp(iid, QVideoRendererControl_iid) == 0) {
+ if (rendererRef == 0) {
+ rendererRef += 1;
+ return rendererControl;
+ }
+ } else if (qstrcmp(iid, QVideoWindowControl_iid) == 0) {
+ if (windowRef == 0) {
+ windowRef += 1;
+ return windowControl;
+ }
+ }
+ return 0;
+ }
+
+ void releaseControl(QMediaControl *control)
+ {
+ if (control == rendererControl)
+ rendererRef -= 1;
+ else if (control == windowControl)
+ windowRef -= 1;
+ }
+
+ MockCameraControl *mockControl;
+ MockCameraLocksControl *mockLocksControl;
+ MockCaptureControl *mockCaptureControl;
+ MockCaptureBufferFormatControl *mockCaptureBufferControl;
+ MockCaptureDestinationControl *mockCaptureDestinationControl;
+ MockCameraExposureControl *mockExposureControl;
+ MockCameraFlashControl *mockFlashControl;
+ MockCameraFocusControl *mockFocusControl;
+ MockImageProcessingControl *mockImageProcessingControl;
+ MockImageEncoderControl *mockImageEncoderControl;
+ MockVideoRendererControl *rendererControl;
+ MockVideoWindowControl *windowControl;
+ int rendererRef;
+ int windowRef;
+};
+
+class MockProvider : public QMediaServiceProvider
+{
+public:
+ QMediaService *requestService(const QByteArray &, const QMediaServiceProviderHint &)
+ {
+ return service;
+ }
+
+ void releaseService(QMediaService *) {}
+
+ QMediaService *service;
+};
+
+
+class tst_QCamera: public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void testAvailableDevices();
+ void testDeviceDescription();
+ void testCtorWithDevice();
+ void testSimpleCamera();
+ void testSimpleCameraWhiteBalance();
+ void testSimpleCameraExposure();
+ void testSimpleCameraFocus();
+ void testSimpleCameraCapture();
+ void testSimpleCameraLock();
+ void testSimpleCaptureDestination();
+ void testSimpleCaptureFormat();
+
+ void testCameraWhiteBalance();
+ void testCameraExposure();
+ void testCameraFocus();
+ void testCameraCapture();
+ void testCameraCaptureMetadata();
+ void testImageSettings();
+ void testCameraLock();
+ void testCameraLockCancel();
+ void testCameraEncodingProperyChange();
+ void testCaptureDestination();
+ void testCaptureFormat();
+
+
+ void testSetVideoOutput();
+ void testSetVideoOutputNoService();
+ void testSetVideoOutputNoControl();
+ void testSetVideoOutputDestruction();
+
+ void testEnumDebug();
+
+private:
+ MockSimpleCameraService *mockSimpleCameraService;
+ MockProvider *provider;
+};
+
+void tst_QCamera::initTestCase()
+{
+ provider = new MockProvider;
+ mockSimpleCameraService = new MockSimpleCameraService;
+ provider->service = mockSimpleCameraService;
+ qRegisterMetaType<QtMultimediaKit::MetaData>("QtMultimediaKit::MetaData");
+}
+
+void tst_QCamera::cleanupTestCase()
+{
+ delete mockSimpleCameraService;
+ delete provider;
+}
+
+void tst_QCamera::testAvailableDevices()
+{
+ int deviceCount = QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA)).count();
+
+ QVERIFY(QCamera::availableDevices().count() == deviceCount);
+}
+
+void tst_QCamera::testDeviceDescription()
+{
+ int deviceCount = QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA)).count();
+
+ if (deviceCount == 0)
+ QVERIFY(QCamera::deviceDescription(QByteArray("random")).isNull());
+ else {
+ foreach (const QByteArray &device, QCamera::availableDevices())
+ QVERIFY(QCamera::deviceDescription(device).length() > 0);
+ }
+}
+
+void tst_QCamera::testCtorWithDevice()
+{
+ int deviceCount = QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA)).count();
+ QCamera *camera = 0;
+
+ if (deviceCount == 0) {
+ camera = new QCamera("random");
+ QVERIFY(camera->error() == QCamera::ServiceMissingError);
+ }
+ else {
+ camera = new QCamera(QCamera::availableDevices().first());
+ QVERIFY(camera->error() == QCamera::NoError);
+ }
+
+ delete camera;
+}
+
+void tst_QCamera::testSimpleCamera()
+{
+ QCamera camera(0, provider);
+ QCOMPARE(camera.service(), (QMediaService*)mockSimpleCameraService);
+
+ QCOMPARE(camera.state(), QCamera::UnloadedState);
+ camera.start();
+ QCOMPARE(camera.state(), QCamera::ActiveState);
+ camera.stop();
+ QCOMPARE(camera.state(), QCamera::LoadedState);
+ camera.unload();
+ QCOMPARE(camera.state(), QCamera::UnloadedState);
+ camera.load();
+ QCOMPARE(camera.state(), QCamera::LoadedState);
+}
+
+void tst_QCamera::testSimpleCameraWhiteBalance()
+{
+ QCamera camera(0, provider);
+
+ //only WhiteBalanceAuto is supported
+ QVERIFY(!camera.imageProcessing()->isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceAuto));
+ QVERIFY(!camera.imageProcessing()->isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceCloudy));
+ QCOMPARE(camera.imageProcessing()->whiteBalanceMode(), QCameraImageProcessing::WhiteBalanceAuto);
+ camera.imageProcessing()->setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceCloudy);
+ QCOMPARE(camera.imageProcessing()->whiteBalanceMode(), QCameraImageProcessing::WhiteBalanceAuto);
+ QCOMPARE(camera.imageProcessing()->manualWhiteBalance(), 0);
+ camera.imageProcessing()->setManualWhiteBalance(5000);
+ QCOMPARE(camera.imageProcessing()->manualWhiteBalance(), 0);
+}
+
+void tst_QCamera::testSimpleCameraExposure()
+{
+ QCamera camera(0, provider);
+ QCameraExposure *cameraExposure = camera.exposure();
+ QVERIFY(cameraExposure != 0);
+
+ QVERIFY(!cameraExposure->isExposureModeSupported(QCameraExposure::ExposureAuto));
+ QCOMPARE(cameraExposure->exposureMode(), QCameraExposure::ExposureAuto);
+ cameraExposure->setExposureMode(QCameraExposure::ExposureManual);//should be ignored
+ QCOMPARE(cameraExposure->exposureMode(), QCameraExposure::ExposureAuto);
+
+ QVERIFY(!cameraExposure->isFlashModeSupported(QCameraExposure::FlashOff));
+ QCOMPARE(cameraExposure->flashMode(), QCameraExposure::FlashOff);
+ QCOMPARE(cameraExposure->isFlashReady(), false);
+ cameraExposure->setFlashMode(QCameraExposure::FlashOn);
+ QCOMPARE(cameraExposure->flashMode(), QCameraExposure::FlashOff);
+
+ QVERIFY(!cameraExposure->isMeteringModeSupported(QCameraExposure::MeteringAverage));
+ QVERIFY(!cameraExposure->isMeteringModeSupported(QCameraExposure::MeteringSpot));
+ QVERIFY(!cameraExposure->isMeteringModeSupported(QCameraExposure::MeteringMatrix));
+ QCOMPARE(cameraExposure->meteringMode(), QCameraExposure::MeteringMatrix);
+ cameraExposure->setMeteringMode(QCameraExposure::MeteringSpot);
+ QCOMPARE(cameraExposure->meteringMode(), QCameraExposure::MeteringMatrix);
+
+ QCOMPARE(cameraExposure->exposureCompensation(), 0.0);
+ cameraExposure->setExposureCompensation(2.0);
+ QCOMPARE(cameraExposure->exposureCompensation(), 0.0);
+
+ QCOMPARE(cameraExposure->isoSensitivity(), -1);
+ QVERIFY(cameraExposure->supportedIsoSensitivities().isEmpty());
+ cameraExposure->setManualIsoSensitivity(100);
+ QCOMPARE(cameraExposure->isoSensitivity(), -1);
+ cameraExposure->setAutoIsoSensitivity();
+ QCOMPARE(cameraExposure->isoSensitivity(), -1);
+
+ QVERIFY(cameraExposure->aperture() < 0);
+ QVERIFY(cameraExposure->supportedApertures().isEmpty());
+ cameraExposure->setAutoAperture();
+ QVERIFY(cameraExposure->aperture() < 0);
+ cameraExposure->setManualAperture(5.6);
+ QVERIFY(cameraExposure->aperture() < 0);
+
+ QVERIFY(cameraExposure->shutterSpeed() < 0);
+ QVERIFY(cameraExposure->supportedShutterSpeeds().isEmpty());
+ cameraExposure->setAutoShutterSpeed();
+ QVERIFY(cameraExposure->shutterSpeed() < 0);
+ cameraExposure->setManualShutterSpeed(1/128.0);
+ QVERIFY(cameraExposure->shutterSpeed() < 0);
+}
+
+void tst_QCamera::testSimpleCameraFocus()
+{
+ QCamera camera(0, provider);
+
+ QCameraFocus *cameraFocus = camera.focus();
+ QVERIFY(cameraFocus != 0);
+
+ QVERIFY(!cameraFocus->isFocusModeSupported(QCameraFocus::AutoFocus));
+ QVERIFY(!cameraFocus->isFocusModeSupported(QCameraFocus::ContinuousFocus));
+ QVERIFY(!cameraFocus->isFocusModeSupported(QCameraFocus::InfinityFocus));
+
+ QCOMPARE(cameraFocus->focusMode(), QCameraFocus::AutoFocus);
+ QTest::ignoreMessage(QtWarningMsg, "Focus points mode selection is not supported");
+ cameraFocus->setFocusMode(QCameraFocus::ContinuousFocus);
+ QCOMPARE(cameraFocus->focusMode(), QCameraFocus::AutoFocus);
+
+ QCOMPARE(cameraFocus->maximumOpticalZoom(), 1.0);
+ QCOMPARE(cameraFocus->maximumDigitalZoom(), 1.0);
+ QCOMPARE(cameraFocus->opticalZoom(), 1.0);
+ QCOMPARE(cameraFocus->digitalZoom(), 1.0);
+
+ QTest::ignoreMessage(QtWarningMsg, "The camera doesn't support zooming.");
+ cameraFocus->zoomTo(100.0, 100.0);
+ QCOMPARE(cameraFocus->opticalZoom(), 1.0);
+ QCOMPARE(cameraFocus->digitalZoom(), 1.0);
+
+
+ QVERIFY(!cameraFocus->isFocusPointModeSupported(QCameraFocus::FocusPointAuto));
+ QCOMPARE(cameraFocus->focusPointMode(), QCameraFocus::FocusPointAuto);
+
+
+ cameraFocus->setFocusPointMode( QCameraFocus::FocusPointCenter );
+ QCOMPARE(cameraFocus->focusPointMode(), QCameraFocus::FocusPointAuto);
+
+ QCOMPARE(cameraFocus->customFocusPoint(), QPointF(0.5, 0.5));
+ QTest::ignoreMessage(QtWarningMsg, "Focus points selection is not supported");
+ cameraFocus->setCustomFocusPoint(QPointF(1.0, 1.0));
+ QCOMPARE(cameraFocus->customFocusPoint(), QPointF(0.5, 0.5));
+}
+
+void tst_QCamera::testSimpleCameraCapture()
+{
+ QCamera camera(0, provider);
+ QCameraImageCapture imageCapture(&camera);
+
+ QVERIFY(!imageCapture.isReadyForCapture());
+ QVERIFY(!imageCapture.isAvailable());
+
+ QCOMPARE(imageCapture.error(), QCameraImageCapture::NoError);
+ QVERIFY(imageCapture.errorString().isEmpty());
+
+ QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int, QCameraImageCapture::Error,QString)));
+ imageCapture.capture(QString::fromLatin1("/dev/null"));
+ QCOMPARE(errorSignal.size(), 1);
+ QCOMPARE(imageCapture.error(), QCameraImageCapture::NotSupportedFeatureError);
+ QVERIFY(!imageCapture.errorString().isEmpty());
+}
+
+void tst_QCamera::testSimpleCameraLock()
+{
+ QCamera camera(0, provider);
+ QCOMPARE(camera.lockStatus(), QCamera::Unlocked);
+ QCOMPARE(camera.lockStatus(QCamera::LockExposure), QCamera::Unlocked);
+ QCOMPARE(camera.lockStatus(QCamera::LockFocus), QCamera::Unlocked);
+ QCOMPARE(camera.lockStatus(QCamera::LockWhiteBalance), QCamera::Unlocked);
+
+ QSignalSpy lockedSignal(&camera, SIGNAL(locked()));
+ QSignalSpy lockFailedSignal(&camera, SIGNAL(lockFailed()));
+ QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
+
+ camera.searchAndLock();
+ QCOMPARE(camera.lockStatus(), QCamera::Locked);
+ QCOMPARE(camera.lockStatus(QCamera::LockExposure), QCamera::Locked);
+ QCOMPARE(camera.lockStatus(QCamera::LockFocus), QCamera::Locked);
+ QCOMPARE(camera.lockStatus(QCamera::LockWhiteBalance), QCamera::Locked);
+ QCOMPARE(lockedSignal.count(), 1);
+ QCOMPARE(lockFailedSignal.count(), 0);
+ QCOMPARE(lockStatusChangedSignal.count(), 1);
+
+ lockedSignal.clear();
+ lockFailedSignal.clear();
+ lockStatusChangedSignal.clear();
+
+ camera.unlock();
+ QCOMPARE(camera.lockStatus(), QCamera::Unlocked);
+ QCOMPARE(camera.lockStatus(QCamera::LockExposure), QCamera::Unlocked);
+ QCOMPARE(camera.lockStatus(QCamera::LockFocus), QCamera::Unlocked);
+ QCOMPARE(camera.lockStatus(QCamera::LockWhiteBalance), QCamera::Unlocked);
+
+ QCOMPARE(lockedSignal.count(), 0);
+ QCOMPARE(lockFailedSignal.count(), 0);
+ QCOMPARE(lockStatusChangedSignal.count(), 1);
+}
+
+void tst_QCamera::testSimpleCaptureDestination()
+{
+ QCamera camera(0, provider);
+ QCameraImageCapture imageCapture(&camera);
+
+ QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToFile));
+ QVERIFY(!imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer));
+ QVERIFY(!imageCapture.isCaptureDestinationSupported(
+ QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile));
+
+ QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToFile);
+ imageCapture.setCaptureDestination(QCameraImageCapture::CaptureToBuffer);
+ QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToFile);
+}
+
+void tst_QCamera::testSimpleCaptureFormat()
+{
+ QCamera camera(0, provider);
+ QCameraImageCapture imageCapture(&camera);
+
+ QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_Invalid);
+ QVERIFY(imageCapture.supportedBufferFormats().isEmpty());
+
+ imageCapture.setBufferFormat(QVideoFrame::Format_AdobeDng);
+ QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_Invalid);
+}
+
+void tst_QCamera::testCaptureDestination()
+{
+ MockCameraService service;
+ provider->service = &service;
+ QCamera camera(0, provider);
+ QCameraImageCapture imageCapture(&camera);
+
+ QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToFile));
+ QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer));
+ QVERIFY(!imageCapture.isCaptureDestinationSupported(
+ QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile));
+
+ QSignalSpy destinationChangedSignal(&imageCapture, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)));
+
+ QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToFile);
+ imageCapture.setCaptureDestination(QCameraImageCapture::CaptureToBuffer);
+ QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToBuffer);
+ QCOMPARE(destinationChangedSignal.size(), 1);
+ QCOMPARE(destinationChangedSignal.first().first().value<QCameraImageCapture::CaptureDestinations>(),
+ QCameraImageCapture::CaptureToBuffer);
+
+ //not supported combination
+ imageCapture.setCaptureDestination(QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile);
+ QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToBuffer);
+ QCOMPARE(destinationChangedSignal.size(), 1);
+}
+
+void tst_QCamera::testCaptureFormat()
+{
+ MockCameraService service;
+ provider->service = &service;
+ QCamera camera(0, provider);
+ QCameraImageCapture imageCapture(&camera);
+
+ QSignalSpy formatChangedSignal(&imageCapture, SIGNAL(bufferFormatChanged(QVideoFrame::PixelFormat)));
+
+ QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_Jpeg);
+ QCOMPARE(imageCapture.supportedBufferFormats().size(), 3);
+
+ imageCapture.setBufferFormat(QVideoFrame::Format_AdobeDng);
+ QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_AdobeDng);
+
+ QCOMPARE(formatChangedSignal.size(), 1);
+ QCOMPARE(formatChangedSignal.first().first().value<QVideoFrame::PixelFormat>(),
+ QVideoFrame::Format_AdobeDng);
+
+ imageCapture.setBufferFormat(QVideoFrame::Format_Y16);
+ QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_AdobeDng);
+
+ QCOMPARE(formatChangedSignal.size(), 1);
+}
+
+
+void tst_QCamera::testCameraCapture()
+{
+ MockCameraService service;
+ provider->service = &service;
+ QCamera camera(0, provider);
+ QCameraImageCapture imageCapture(&camera);
+
+
+ QVERIFY(!imageCapture.isReadyForCapture());
+
+ QSignalSpy capturedSignal(&imageCapture, SIGNAL(imageCaptured(int,QImage)));
+ QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int, QCameraImageCapture::Error,QString)));
+
+ imageCapture.capture(QString::fromLatin1("/dev/null"));
+ QCOMPARE(capturedSignal.size(), 0);
+ QCOMPARE(errorSignal.size(), 1);
+ QCOMPARE(imageCapture.error(), QCameraImageCapture::NotReadyError);
+
+ errorSignal.clear();
+
+ camera.start();
+ QVERIFY(imageCapture.isReadyForCapture());
+ QCOMPARE(errorSignal.size(), 0);
+
+ imageCapture.capture(QString::fromLatin1("/dev/null"));
+
+ for (int i=0; i<100 && capturedSignal.isEmpty(); i++)
+ QTest::qWait(10);
+
+ QCOMPARE(capturedSignal.size(), 1);
+ QCOMPARE(errorSignal.size(), 0);
+ QCOMPARE(imageCapture.error(), QCameraImageCapture::NoError);
+}
+
+void tst_QCamera::testCameraCaptureMetadata()
+{
+ MockCameraService service;
+ provider->service = &service;
+ QCamera camera(0, provider);
+ QCameraImageCapture imageCapture(&camera);
+
+ QSignalSpy metadataSignal(&imageCapture, SIGNAL(imageMetadataAvailable(int,QtMultimediaKit::MetaData,QVariant)));
+ QSignalSpy extendedMetadataSignal(&imageCapture, SIGNAL(imageMetadataAvailable(int,QString,QVariant)));
+ QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString)));
+
+ camera.start();
+ int id = imageCapture.capture(QString::fromLatin1("/dev/null"));
+
+ for (int i=0; i<100 && savedSignal.isEmpty(); i++)
+ QTest::qWait(10);
+
+ QCOMPARE(savedSignal.size(), 1);
+
+ QCOMPARE(metadataSignal.size(), 2);
+
+ QVariantList metadata = metadataSignal[0];
+ QCOMPARE(metadata[0].toInt(), id);
+ QCOMPARE(metadata[1].value<QtMultimediaKit::MetaData>(), QtMultimediaKit::FocalLengthIn35mmFilm);
+ QCOMPARE(metadata[2].value<QVariant>().toInt(), 50);
+
+ metadata = metadataSignal[1];
+ QCOMPARE(metadata[0].toInt(), id);
+ QCOMPARE(metadata[1].value<QtMultimediaKit::MetaData>(), QtMultimediaKit::DateTimeOriginal);
+ QDateTime captureTime = metadata[2].value<QVariant>().value<QDateTime>();
+ QVERIFY(qAbs(captureTime.secsTo(QDateTime::currentDateTime()) < 5)); //it should not takes more than 5 seconds for signal to arrive here
+
+ QCOMPARE(extendedMetadataSignal.size(), 1);
+ metadata = extendedMetadataSignal.first();
+ QCOMPARE(metadata[0].toInt(), id);
+ QCOMPARE(metadata[1].toString(), QLatin1String("Answer to the Ultimate Question of Life, the Universe, and Everything"));
+ QCOMPARE(metadata[2].value<QVariant>().toInt(), 42);
+}
+
+
+void tst_QCamera::testCameraWhiteBalance()
+{
+ QSet<QCameraImageProcessing::WhiteBalanceMode> whiteBalanceModes;
+ whiteBalanceModes << QCameraImageProcessing::WhiteBalanceAuto;
+ whiteBalanceModes << QCameraImageProcessing::WhiteBalanceFlash;
+ whiteBalanceModes << QCameraImageProcessing::WhiteBalanceIncandescent;
+
+ MockCameraService service;
+ service.mockImageProcessingControl->setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceFlash);
+ service.mockImageProcessingControl->setSupportedWhiteBalanceModes(whiteBalanceModes);
+ service.mockImageProcessingControl->setProcessingParameter(
+ QCameraImageProcessingControl::ColorTemperature,
+ QVariant(34));
+
+ MockProvider provider;
+ provider.service = &service;
+
+ QCamera camera(0, &provider);
+ QCameraImageProcessing *cameraImageProcessing = camera.imageProcessing();
+
+ QCOMPARE(cameraImageProcessing->whiteBalanceMode(), QCameraImageProcessing::WhiteBalanceFlash);
+ QVERIFY(camera.imageProcessing()->isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceAuto));
+ QVERIFY(camera.imageProcessing()->isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceFlash));
+ QVERIFY(camera.imageProcessing()->isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceIncandescent));
+ QVERIFY(!camera.imageProcessing()->isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceCloudy));
+
+ cameraImageProcessing->setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceIncandescent);
+ QCOMPARE(cameraImageProcessing->whiteBalanceMode(), QCameraImageProcessing::WhiteBalanceIncandescent);
+
+ cameraImageProcessing->setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceManual);
+ QCOMPARE(cameraImageProcessing->whiteBalanceMode(), QCameraImageProcessing::WhiteBalanceManual);
+ QCOMPARE(cameraImageProcessing->manualWhiteBalance(), 34);
+
+ cameraImageProcessing->setManualWhiteBalance(432);
+ QCOMPARE(cameraImageProcessing->manualWhiteBalance(), 432);
+}
+
+void tst_QCamera::testCameraExposure()
+{
+ MockCameraService service;
+ provider->service = &service;
+ QCamera camera(0, provider);
+
+ QCameraExposure *cameraExposure = camera.exposure();
+ QVERIFY(cameraExposure != 0);
+
+ QVERIFY(cameraExposure->isExposureModeSupported(QCameraExposure::ExposureAuto));
+ QCOMPARE(cameraExposure->exposureMode(), QCameraExposure::ExposureAuto);
+ cameraExposure->setExposureMode(QCameraExposure::ExposureManual);
+ QCOMPARE(cameraExposure->exposureMode(), QCameraExposure::ExposureManual);
+
+ QCOMPARE(cameraExposure->flashMode(), QCameraExposure::FlashAuto);
+ QCOMPARE(cameraExposure->isFlashReady(), true);
+ cameraExposure->setFlashMode(QCameraExposure::FlashOn);
+ QCOMPARE(cameraExposure->flashMode(), QCameraExposure::FlashOn);
+
+ cameraExposure->setFlashMode(QCameraExposure::FlashRedEyeReduction); // not expected to be supported
+ QCOMPARE(cameraExposure->flashMode(), QCameraExposure::FlashOn);
+
+ QCOMPARE(cameraExposure->meteringMode(), QCameraExposure::MeteringMatrix);
+ cameraExposure->setMeteringMode(QCameraExposure::MeteringAverage);
+ QCOMPARE(cameraExposure->meteringMode(), QCameraExposure::MeteringAverage);
+ cameraExposure->setMeteringMode(QCameraExposure::MeteringSpot);
+ QCOMPARE(cameraExposure->meteringMode(), QCameraExposure::MeteringAverage);
+
+
+ QCOMPARE(cameraExposure->exposureCompensation(), 0.0);
+ cameraExposure->setExposureCompensation(2.0);
+ QCOMPARE(cameraExposure->exposureCompensation(), 2.0);
+
+ int minIso = cameraExposure->supportedIsoSensitivities().first();
+ int maxIso = cameraExposure->supportedIsoSensitivities().last();
+ QVERIFY(cameraExposure->isoSensitivity() > 0);
+ QVERIFY(minIso > 0);
+ QVERIFY(maxIso > 0);
+ cameraExposure->setManualIsoSensitivity(minIso);
+ QCOMPARE(cameraExposure->isoSensitivity(), minIso);
+ cameraExposure->setManualIsoSensitivity(maxIso*10);
+ QCOMPARE(cameraExposure->isoSensitivity(), maxIso);
+ cameraExposure->setManualIsoSensitivity(-10);
+ QCOMPARE(cameraExposure->isoSensitivity(), minIso);
+ cameraExposure->setAutoIsoSensitivity();
+ QCOMPARE(cameraExposure->isoSensitivity(), 100);
+
+ qreal minAperture = cameraExposure->supportedApertures().first();
+ qreal maxAperture = cameraExposure->supportedApertures().last();
+ QVERIFY(minAperture > 0);
+ QVERIFY(maxAperture > 0);
+ QVERIFY(cameraExposure->aperture() >= minAperture);
+ QVERIFY(cameraExposure->aperture() <= maxAperture);
+
+ cameraExposure->setAutoAperture();
+ QVERIFY(cameraExposure->aperture() >= minAperture);
+ QVERIFY(cameraExposure->aperture() <= maxAperture);
+
+ cameraExposure->setManualAperture(0);
+ QCOMPARE(cameraExposure->aperture(), minAperture);
+
+ cameraExposure->setManualAperture(10000);
+ QCOMPARE(cameraExposure->aperture(), maxAperture);
+
+
+ qreal minShutterSpeed = cameraExposure->supportedShutterSpeeds().first();
+ qreal maxShutterSpeed = cameraExposure->supportedShutterSpeeds().last();
+ QVERIFY(minShutterSpeed > 0);
+ QVERIFY(maxShutterSpeed > 0);
+ QVERIFY(cameraExposure->shutterSpeed() >= minShutterSpeed);
+ QVERIFY(cameraExposure->shutterSpeed() <= maxShutterSpeed);
+
+ cameraExposure->setAutoShutterSpeed();
+ QVERIFY(cameraExposure->shutterSpeed() >= minShutterSpeed);
+ QVERIFY(cameraExposure->shutterSpeed() <= maxShutterSpeed);
+
+ cameraExposure->setManualShutterSpeed(0);
+ QCOMPARE(cameraExposure->shutterSpeed(), minShutterSpeed);
+
+ cameraExposure->setManualShutterSpeed(10000);
+ QCOMPARE(cameraExposure->shutterSpeed(), maxShutterSpeed);
+}
+
+void tst_QCamera::testCameraFocus()
+{
+ MockCameraService service;
+ provider->service = &service;
+ QCamera camera(0, provider);
+
+ QCameraFocus *cameraFocus = camera.focus();
+ QVERIFY(cameraFocus != 0);
+
+ QVERIFY(cameraFocus->isFocusModeSupported(QCameraFocus::AutoFocus));
+ QVERIFY(cameraFocus->isFocusModeSupported(QCameraFocus::ContinuousFocus));
+ QVERIFY(!cameraFocus->isFocusModeSupported(QCameraFocus::InfinityFocus));
+
+ QCOMPARE(cameraFocus->focusMode(), QCameraFocus::AutoFocus);
+ cameraFocus->setFocusMode(QCameraFocus::ManualFocus);
+ QCOMPARE(cameraFocus->focusMode(), QCameraFocus::AutoFocus);
+ cameraFocus->setFocusMode(QCameraFocus::ContinuousFocus);
+ QCOMPARE(cameraFocus->focusMode(), QCameraFocus::ContinuousFocus);
+
+ QVERIFY(cameraFocus->maximumOpticalZoom() >= 1.0);
+ QVERIFY(cameraFocus->maximumDigitalZoom() >= 1.0);
+ QCOMPARE(cameraFocus->opticalZoom(), 1.0);
+ QCOMPARE(cameraFocus->digitalZoom(), 1.0);
+ cameraFocus->zoomTo(0.5, 1.0);
+ QCOMPARE(cameraFocus->opticalZoom(), 1.0);
+ QCOMPARE(cameraFocus->digitalZoom(), 1.0);
+ cameraFocus->zoomTo(2.0, 0.5);
+ QCOMPARE(cameraFocus->opticalZoom(), 2.0);
+ QCOMPARE(cameraFocus->digitalZoom(), 1.0);
+ cameraFocus->zoomTo(2.0, 2.5);
+ QCOMPARE(cameraFocus->opticalZoom(), 2.0);
+ QCOMPARE(cameraFocus->digitalZoom(), 2.5);
+ cameraFocus->zoomTo(2000000.0, 1000000.0);
+ QVERIFY(qFuzzyCompare(cameraFocus->opticalZoom(), cameraFocus->maximumOpticalZoom()));
+ QVERIFY(qFuzzyCompare(cameraFocus->digitalZoom(), cameraFocus->maximumDigitalZoom()));
+
+ QVERIFY(cameraFocus->isFocusPointModeSupported(QCameraFocus::FocusPointAuto));
+ QVERIFY(cameraFocus->isFocusPointModeSupported(QCameraFocus::FocusPointCenter));
+ QVERIFY(cameraFocus->isFocusPointModeSupported(QCameraFocus::FocusPointCustom));
+ QCOMPARE(cameraFocus->focusPointMode(), QCameraFocus::FocusPointAuto);
+
+ cameraFocus->setFocusPointMode( QCameraFocus::FocusPointCenter );
+ QCOMPARE(cameraFocus->focusPointMode(), QCameraFocus::FocusPointCenter);
+
+ cameraFocus->setFocusPointMode( QCameraFocus::FocusPointFaceDetection );
+ QCOMPARE(cameraFocus->focusPointMode(), QCameraFocus::FocusPointCenter);
+
+ QCOMPARE(cameraFocus->customFocusPoint(), QPointF(0.5, 0.5));
+ cameraFocus->setCustomFocusPoint(QPointF(1.0, 1.0));
+ QCOMPARE(cameraFocus->customFocusPoint(), QPointF(1.0, 1.0));
+}
+
+void tst_QCamera::testImageSettings()
+{
+ QImageEncoderSettings settings;
+ QVERIFY(settings.isNull());
+ QVERIFY(settings == QImageEncoderSettings());
+
+ QCOMPARE(settings.codec(), QString());
+ settings.setCodec(QLatin1String("codecName"));
+ QCOMPARE(settings.codec(), QLatin1String("codecName"));
+ QVERIFY(!settings.isNull());
+ QVERIFY(settings != QImageEncoderSettings());
+
+ settings = QImageEncoderSettings();
+ QCOMPARE(settings.quality(), QtMultimediaKit::NormalQuality);
+ settings.setQuality(QtMultimediaKit::HighQuality);
+ QCOMPARE(settings.quality(), QtMultimediaKit::HighQuality);
+ QVERIFY(!settings.isNull());
+
+ settings = QImageEncoderSettings();
+ QCOMPARE(settings.resolution(), QSize());
+ settings.setResolution(QSize(320,240));
+ QCOMPARE(settings.resolution(), QSize(320,240));
+ settings.setResolution(800,600);
+ QCOMPARE(settings.resolution(), QSize(800,600));
+ QVERIFY(!settings.isNull());
+
+ settings = QImageEncoderSettings();
+ QVERIFY(settings.isNull());
+ QCOMPARE(settings.codec(), QString());
+ QCOMPARE(settings.quality(), QtMultimediaKit::NormalQuality);
+ QCOMPARE(settings.resolution(), QSize());
+
+ {
+ QImageEncoderSettings settings1;
+ QImageEncoderSettings settings2;
+ QCOMPARE(settings2, settings1);
+
+ settings2 = settings1;
+ QCOMPARE(settings2, settings1);
+ QVERIFY(settings2.isNull());
+
+ settings1.setQuality(QtMultimediaKit::HighQuality);
+
+ QVERIFY(settings2.isNull());
+ QVERIFY(!settings1.isNull());
+ QVERIFY(settings1 != settings2);
+ }
+
+ {
+ QImageEncoderSettings settings1;
+ QImageEncoderSettings settings2(settings1);
+ QCOMPARE(settings2, settings1);
+
+ settings2 = settings1;
+ QCOMPARE(settings2, settings1);
+ QVERIFY(settings2.isNull());
+
+ settings1.setQuality(QtMultimediaKit::HighQuality);
+
+ QVERIFY(settings2.isNull());
+ QVERIFY(!settings1.isNull());
+ QVERIFY(settings1 != settings2);
+ }
+
+ QImageEncoderSettings settings1;
+ QImageEncoderSettings settings2;
+
+ settings1 = QImageEncoderSettings();
+ settings1.setResolution(800,600);
+ settings2 = QImageEncoderSettings();
+ settings2.setResolution(QSize(800,600));
+ QVERIFY(settings1 == settings2);
+ settings2.setResolution(QSize(400,300));
+ QVERIFY(settings1 != settings2);
+
+ settings1 = QImageEncoderSettings();
+ settings1.setCodec("codec1");
+ settings2 = QImageEncoderSettings();
+ settings2.setCodec("codec1");
+ QVERIFY(settings1 == settings2);
+ settings2.setCodec("codec2");
+ QVERIFY(settings1 != settings2);
+
+ settings1 = QImageEncoderSettings();
+ settings1.setQuality(QtMultimediaKit::NormalQuality);
+ settings2 = QImageEncoderSettings();
+ settings2.setQuality(QtMultimediaKit::NormalQuality);
+ QVERIFY(settings1 == settings2);
+ settings2.setQuality(QtMultimediaKit::LowQuality);
+ QVERIFY(settings1 != settings2);
+}
+
+void tst_QCamera::testCameraLock()
+{
+ MockCameraService service;
+ provider->service = &service;
+ QCamera camera(0, provider);
+
+ camera.focus()->setFocusMode(QCameraFocus::AutoFocus);
+
+ QCOMPARE(camera.lockStatus(), QCamera::Unlocked);
+
+ QSignalSpy lockedSignal(&camera, SIGNAL(locked()));
+ QSignalSpy lockFailedSignal(&camera, SIGNAL(lockFailed()));
+ QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus,QCamera::LockChangeReason)));
+
+ camera.searchAndLock();
+ QCOMPARE(camera.lockStatus(), QCamera::Searching);
+ QCOMPARE(lockedSignal.count(), 0);
+ QCOMPARE(lockFailedSignal.count(), 0);
+ QCOMPARE(lockStatusChangedSignal.count(), 1);
+
+ lockedSignal.clear();
+ lockFailedSignal.clear();
+ lockStatusChangedSignal.clear();
+
+ for (int i=0; i<200 && camera.lockStatus() == QCamera::Searching; i++)
+ QTest::qWait(10);
+
+ QCOMPARE(camera.lockStatus(), QCamera::Locked);
+ QCOMPARE(lockedSignal.count(), 1);
+ QCOMPARE(lockFailedSignal.count(), 0);
+ QCOMPARE(lockStatusChangedSignal.count(), 1);
+
+ lockedSignal.clear();
+ lockFailedSignal.clear();
+ lockStatusChangedSignal.clear();
+
+ camera.searchAndLock();
+ QCOMPARE(camera.lockStatus(), QCamera::Searching);
+ QCOMPARE(lockedSignal.count(), 0);
+ QCOMPARE(lockFailedSignal.count(), 0);
+ QCOMPARE(lockStatusChangedSignal.count(), 1);
+
+ lockedSignal.clear();
+ lockFailedSignal.clear();
+ lockStatusChangedSignal.clear();
+
+ camera.unlock();
+ QCOMPARE(camera.lockStatus(), QCamera::Unlocked);
+ QCOMPARE(lockedSignal.count(), 0);
+ QCOMPARE(lockFailedSignal.count(), 0);
+ QCOMPARE(lockStatusChangedSignal.count(), 1);
+}
+
+void tst_QCamera::testCameraLockCancel()
+{
+ MockCameraService service;
+ provider->service = &service;
+ QCamera camera(0, provider);
+
+ camera.focus()->setFocusMode(QCameraFocus::AutoFocus);
+
+ QCOMPARE(camera.lockStatus(), QCamera::Unlocked);
+
+ QSignalSpy lockedSignal(&camera, SIGNAL(locked()));
+ QSignalSpy lockFailedSignal(&camera, SIGNAL(lockFailed()));
+ QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
+ camera.searchAndLock();
+ QCOMPARE(camera.lockStatus(), QCamera::Searching);
+ QCOMPARE(lockedSignal.count(), 0);
+ QCOMPARE(lockFailedSignal.count(), 0);
+ QCOMPARE(lockStatusChangedSignal.count(), 1);
+
+ lockedSignal.clear();
+ lockFailedSignal.clear();
+ lockStatusChangedSignal.clear();
+
+ camera.unlock();
+ QCOMPARE(camera.lockStatus(), QCamera::Unlocked);
+ QCOMPARE(lockedSignal.count(), 0);
+ QCOMPARE(lockFailedSignal.count(), 0);
+ QCOMPARE(lockStatusChangedSignal.count(), 1);
+}
+
+void tst_QCamera::testCameraEncodingProperyChange()
+{
+ MockCameraService service;
+ provider->service = &service;
+ QCamera camera(0, provider);
+ QCameraImageCapture imageCapture(&camera);
+
+ QSignalSpy stateChangedSignal(&camera, SIGNAL(stateChanged(QCamera::State)));
+ QSignalSpy statusChangedSignal(&camera, SIGNAL(statusChanged(QCamera::Status)));
+
+ camera.start();
+ QCOMPARE(camera.state(), QCamera::ActiveState);
+ QCOMPARE(camera.status(), QCamera::ActiveStatus);
+
+ QCOMPARE(stateChangedSignal.count(), 1);
+ QCOMPARE(statusChangedSignal.count(), 1);
+ stateChangedSignal.clear();
+ statusChangedSignal.clear();
+
+ camera.setCaptureMode(QCamera::CaptureVideo);
+ QCOMPARE(camera.state(), QCamera::ActiveState);
+ QCOMPARE(camera.status(), QCamera::LoadedStatus);
+
+ QCOMPARE(stateChangedSignal.count(), 0);
+ QCOMPARE(statusChangedSignal.count(), 1);
+ stateChangedSignal.clear();
+ statusChangedSignal.clear();
+
+ QTest::qWait(10);
+
+ QCOMPARE(camera.state(), QCamera::ActiveState);
+ QCOMPARE(camera.status(), QCamera::ActiveStatus);
+ QCOMPARE(stateChangedSignal.count(), 0);
+ QCOMPARE(statusChangedSignal.count(), 1);
+ stateChangedSignal.clear();
+ statusChangedSignal.clear();
+
+ //backens should not be stopped since the capture mode is Video
+ imageCapture.setEncodingSettings(QImageEncoderSettings());
+ QCOMPARE(stateChangedSignal.count(), 0);
+ QCOMPARE(statusChangedSignal.count(), 0);
+
+ camera.setCaptureMode(QCamera::CaptureStillImage);
+ QTest::qWait(10);
+ stateChangedSignal.clear();
+ statusChangedSignal.clear();
+
+ //the settings change should trigger camera stop/start
+ imageCapture.setEncodingSettings(QImageEncoderSettings());
+ QCOMPARE(camera.state(), QCamera::ActiveState);
+ QCOMPARE(camera.status(), QCamera::LoadedStatus);
+
+ QCOMPARE(stateChangedSignal.count(), 0);
+ QCOMPARE(statusChangedSignal.count(), 1);
+ stateChangedSignal.clear();
+ statusChangedSignal.clear();
+
+ QTest::qWait(10);
+
+ QCOMPARE(camera.state(), QCamera::ActiveState);
+ QCOMPARE(camera.status(), QCamera::ActiveStatus);
+ QCOMPARE(stateChangedSignal.count(), 0);
+ QCOMPARE(statusChangedSignal.count(), 1);
+ stateChangedSignal.clear();
+ statusChangedSignal.clear();
+
+ //the settings change should trigger camera stop/start only once
+ camera.setCaptureMode(QCamera::CaptureVideo);
+ camera.setCaptureMode(QCamera::CaptureStillImage);
+ imageCapture.setEncodingSettings(QImageEncoderSettings());
+ imageCapture.setEncodingSettings(QImageEncoderSettings());
+
+ QCOMPARE(camera.state(), QCamera::ActiveState);
+ QCOMPARE(camera.status(), QCamera::LoadedStatus);
+
+ QCOMPARE(stateChangedSignal.count(), 0);
+ QCOMPARE(statusChangedSignal.count(), 1);
+ stateChangedSignal.clear();
+ statusChangedSignal.clear();
+
+ QTest::qWait(10);
+
+ QCOMPARE(camera.state(), QCamera::ActiveState);
+ QCOMPARE(camera.status(), QCamera::ActiveStatus);
+ QCOMPARE(stateChangedSignal.count(), 0);
+ QCOMPARE(statusChangedSignal.count(), 1);
+ stateChangedSignal.clear();
+ statusChangedSignal.clear();
+
+ //setting the viewfinder should also trigget backend to be restarted:
+ camera.setViewfinder(new QGraphicsVideoItem());
+ QCOMPARE(camera.state(), QCamera::ActiveState);
+ QCOMPARE(camera.status(), QCamera::LoadedStatus);
+
+ QCOMPARE(stateChangedSignal.count(), 0);
+ QCOMPARE(statusChangedSignal.count(), 1);
+
+ QTest::qWait(10);
+
+ service.mockControl->m_propertyChangesSupported = true;
+ //the changes to encoding settings,
+ //capture mode and encoding parameters should not trigger service restart
+ stateChangedSignal.clear();
+ statusChangedSignal.clear();
+
+ camera.setCaptureMode(QCamera::CaptureVideo);
+ camera.setCaptureMode(QCamera::CaptureStillImage);
+ imageCapture.setEncodingSettings(QImageEncoderSettings());
+ imageCapture.setEncodingSettings(QImageEncoderSettings());
+ camera.setViewfinder(new QGraphicsVideoItem());
+
+ QCOMPARE(stateChangedSignal.count(), 0);
+ QCOMPARE(statusChangedSignal.count(), 0);
+
+}
+
+void tst_QCamera::testSetVideoOutput()
+{
+ QVideoWidget widget;
+ QGraphicsVideoItem item;
+ MockVideoSurface surface;
+
+ MockCameraService service;
+ MockProvider provider;
+ provider.service = &service;
+ QCamera camera(0, &provider);
+
+ camera.setViewfinder(&widget);
+ QVERIFY(widget.mediaObject() == &camera);
+
+ camera.setViewfinder(&item);
+ QVERIFY(widget.mediaObject() == 0);
+ QVERIFY(item.mediaObject() == &camera);
+
+ camera.setViewfinder(reinterpret_cast<QVideoWidget *>(0));
+ QVERIFY(item.mediaObject() == 0);
+
+ camera.setViewfinder(&widget);
+ QVERIFY(widget.mediaObject() == &camera);
+
+ camera.setViewfinder(reinterpret_cast<QGraphicsVideoItem *>(0));
+ QVERIFY(widget.mediaObject() == 0);
+
+ camera.setViewfinder(&surface);
+ QVERIFY(service.rendererControl->surface() == &surface);
+
+ camera.setViewfinder(reinterpret_cast<QAbstractVideoSurface *>(0));
+ QVERIFY(service.rendererControl->surface() == 0);
+
+ camera.setViewfinder(&surface);
+ QVERIFY(service.rendererControl->surface() == &surface);
+
+ camera.setViewfinder(&widget);
+ QVERIFY(service.rendererControl->surface() == 0);
+ QVERIFY(widget.mediaObject() == &camera);
+
+ camera.setViewfinder(&surface);
+ QVERIFY(service.rendererControl->surface() == &surface);
+ QVERIFY(widget.mediaObject() == 0);
+}
+
+
+void tst_QCamera::testSetVideoOutputNoService()
+{
+ QVideoWidget widget;
+ QGraphicsVideoItem item;
+ MockVideoSurface surface;
+
+ MockProvider provider;
+ provider.service = 0;
+ QCamera camera(0, &provider);
+
+ camera.setViewfinder(&widget);
+ QVERIFY(widget.mediaObject() == 0);
+
+ camera.setViewfinder(&item);
+ QVERIFY(item.mediaObject() == 0);
+
+ camera.setViewfinder(&surface);
+ // Nothing we can verify here other than it doesn't assert.
+}
+
+void tst_QCamera::testSetVideoOutputNoControl()
+{
+ QVideoWidget widget;
+ QGraphicsVideoItem item;
+ MockVideoSurface surface;
+
+ MockCameraService service;
+ service.rendererRef = 1;
+ service.windowRef = 1;
+
+ MockProvider provider;
+ provider.service = &service;
+ QCamera camera(0, &provider);
+
+ camera.setViewfinder(&widget);
+ QVERIFY(widget.mediaObject() == 0);
+
+ camera.setViewfinder(&item);
+ QVERIFY(item.mediaObject() == 0);
+
+ camera.setViewfinder(&surface);
+ QVERIFY(service.rendererControl->surface() == 0);
+}
+
+void tst_QCamera::testSetVideoOutputDestruction()
+{
+ MockVideoSurface surface;
+
+ MockCameraService service;
+ MockProvider provider;
+ provider.service = &service;
+
+ {
+ QCamera camera(0, &provider);
+ camera.setViewfinder(&surface);
+ QVERIFY(service.rendererControl->surface() == &surface);
+ QCOMPARE(service.rendererRef, 1);
+ }
+ QVERIFY(service.rendererControl->surface() == 0);
+ QCOMPARE(service.rendererRef, 0);
+}
+
+void tst_QCamera::testEnumDebug()
+{
+ QTest::ignoreMessage(QtDebugMsg, "QCamera::ActiveState ");
+ qDebug() << QCamera::ActiveState;
+ QTest::ignoreMessage(QtDebugMsg, "QCamera::ActiveStatus ");
+ qDebug() << QCamera::ActiveStatus;
+ QTest::ignoreMessage(QtDebugMsg, "QCamera::CaptureVideo ");
+ qDebug() << QCamera::CaptureVideo;
+ QTest::ignoreMessage(QtDebugMsg, "QCamera::CameraError ");
+ qDebug() << QCamera::CameraError;
+ QTest::ignoreMessage(QtDebugMsg, "QCamera::Unlocked ");
+ qDebug() << QCamera::Unlocked;
+ QTest::ignoreMessage(QtDebugMsg, "QCamera::LockAcquired ");
+ qDebug() << QCamera::LockAcquired;
+ QTest::ignoreMessage(QtDebugMsg, "QCamera::NoLock ");
+ qDebug() << QCamera::NoLock;
+ QTest::ignoreMessage(QtDebugMsg, "QCamera::LockExposure ");
+ qDebug() << QCamera::LockExposure;
+}
+
+QTEST_MAIN(tst_QCamera)
+
+#include "tst_qcamera.moc"
diff --git a/tests/auto/qcamerabackend/qcamerabackend.pro b/tests/auto/qcamerabackend/qcamerabackend.pro
new file mode 100644
index 000000000..80e853d8b
--- /dev/null
+++ b/tests/auto/qcamerabackend/qcamerabackend.pro
@@ -0,0 +1,15 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qcamerabackend
+# CONFIG += testcase
+
+SOURCES += tst_qcamerabackend.cpp
+
+symbian {
+ TARGET.CAPABILITY = ALL -TCB
+ TARGET.EPOCHEAPSIZE = 0x20000 0x3000000
+}
+
+maemo*:CONFIG += insignificant_test
diff --git a/tests/auto/qcamerabackend/tst_qcamerabackend.cpp b/tests/auto/qcamerabackend/tst_qcamerabackend.cpp
new file mode 100644
index 000000000..3fe3c7520
--- /dev/null
+++ b/tests/auto/qcamerabackend/tst_qcamerabackend.cpp
@@ -0,0 +1,633 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <QtTest/QtTest>
+#include <QtGui/QImageReader>
+#include <QDebug>
+
+#include <qabstractvideosurface.h>
+#include <qcameracontrol.h>
+#include <qcameralockscontrol.h>
+#include <qcameraexposurecontrol.h>
+#include <qcameraflashcontrol.h>
+#include <qcamerafocuscontrol.h>
+#include <qcameraimagecapturecontrol.h>
+#include <qimageencodercontrol.h>
+#include <qcameraimageprocessingcontrol.h>
+#include <qcameracapturebufferformatcontrol.h>
+#include <qcameracapturedestinationcontrol.h>
+#include <qmediaservice.h>
+#include <qcamera.h>
+#include <qcameraimagecapture.h>
+#include <qgraphicsvideoitem.h>
+#include <qvideorenderercontrol.h>
+#include <qvideowidget.h>
+#include <qvideowindowcontrol.h>
+
+QT_USE_NAMESPACE
+
+// Eventually these will make it into qtestcase.h
+// but we might need to tweak the timeout values here.
+#ifndef QTRY_COMPARE
+#define QTRY_COMPARE(__expr, __expected) \
+ do { \
+ const int __step = 50; \
+ const int __timeout = 10000; \
+ if ((__expr) != (__expected)) { \
+ QTest::qWait(0); \
+ } \
+ for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \
+ QTest::qWait(__step); \
+ } \
+ QCOMPARE(__expr, __expected); \
+ } while(0)
+#endif
+
+#ifndef QTRY_VERIFY
+#define QTRY_VERIFY(__expr) \
+ do { \
+ const int __step = 50; \
+ const int __timeout = 10000; \
+ if (!(__expr)) { \
+ QTest::qWait(0); \
+ } \
+ for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \
+ QTest::qWait(__step); \
+ } \
+ QVERIFY(__expr); \
+ } while(0)
+#endif
+
+
+#define QTRY_WAIT(code, __expr) \
+ do { \
+ const int __step = 50; \
+ const int __timeout = 10000; \
+ if (!(__expr)) { \
+ QTest::qWait(0); \
+ } \
+ for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \
+ do { code } while(0); \
+ QTest::qWait(__step); \
+ } \
+ } while(0)
+
+
+/*
+ This is the backend conformance test.
+
+ Since it relies on platform media framework and sound hardware
+ it may be less stable.
+*/
+
+
+Q_DECLARE_METATYPE(QtMultimediaKit::MetaData)
+Q_DECLARE_METATYPE(QVideoFrame)
+
+class tst_QCameraBackend: public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void testAvailableDevices();
+ void testDeviceDescription();
+ void testCtorWithDevice();
+
+ void testCameraStates();
+ void testCaptureMode();
+ void testCameraCapture();
+ void testCaptureToBuffer();
+ void testCameraCaptureMetadata();
+ void testExposureCompensation();
+ void testExposureMode();
+private:
+};
+
+void tst_QCameraBackend::initTestCase()
+{
+ qRegisterMetaType<QtMultimediaKit::MetaData>("QtMultimediaKit::MetaData");
+
+ QCamera camera;
+ if (!camera.isAvailable())
+ QSKIP("Camera is not available", SkipAll);
+}
+
+void tst_QCameraBackend::cleanupTestCase()
+{
+}
+
+void tst_QCameraBackend::testAvailableDevices()
+{
+ int deviceCount = QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA)).count();
+ QCOMPARE(QCamera::availableDevices().count(), deviceCount);
+}
+
+void tst_QCameraBackend::testDeviceDescription()
+{
+ int deviceCount = QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA)).count();
+
+ if (deviceCount == 0)
+ QVERIFY(QCamera::deviceDescription(QByteArray("random")).isNull());
+ else {
+ foreach (const QByteArray &device, QCamera::availableDevices())
+ QVERIFY(QCamera::deviceDescription(device).length() > 0);
+ }
+}
+
+void tst_QCameraBackend::testCtorWithDevice()
+{
+ int deviceCount = QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA)).count();
+ QCamera *camera = 0;
+
+ if (deviceCount == 0) {
+ camera = new QCamera("random");
+ QCOMPARE(camera->error(), QCamera::ServiceMissingError);
+ }
+ else {
+ camera = new QCamera(QCamera::availableDevices().first());
+ QCOMPARE(camera->error(), QCamera::NoError);
+ }
+
+ delete camera;
+}
+
+void tst_QCameraBackend::testCameraStates()
+{
+ QCamera camera;
+ QCameraImageCapture imageCapture(&camera);
+
+ QSignalSpy errorSignal(&camera, SIGNAL(error(QCamera::Error)));
+ QSignalSpy stateChangedSignal(&camera, SIGNAL(stateChanged(QCamera::State)));
+ QSignalSpy statusChangedSignal(&camera, SIGNAL(statusChanged(QCamera::Status)));
+
+ QCOMPARE(camera.state(), QCamera::UnloadedState);
+ QCOMPARE(camera.status(), QCamera::UnloadedStatus);
+
+ camera.load();
+ QCOMPARE(camera.state(), QCamera::LoadedState);
+ QCOMPARE(stateChangedSignal.count(), 1);
+ QCOMPARE(stateChangedSignal.last().first().value<QCamera::State>(), QCamera::LoadedState);
+ QVERIFY(stateChangedSignal.count() > 0);
+
+ QTRY_COMPARE(camera.status(), QCamera::LoadedStatus);
+ QCOMPARE(statusChangedSignal.last().first().value<QCamera::Status>(), QCamera::LoadedStatus);
+
+ camera.unload();
+ QCOMPARE(camera.state(), QCamera::UnloadedState);
+ QCOMPARE(stateChangedSignal.last().first().value<QCamera::State>(), QCamera::UnloadedState);
+ QTRY_COMPARE(camera.status(), QCamera::UnloadedStatus);
+ QCOMPARE(statusChangedSignal.last().first().value<QCamera::Status>(), QCamera::UnloadedStatus);
+
+ camera.start();
+ QCOMPARE(camera.state(), QCamera::ActiveState);
+ QCOMPARE(stateChangedSignal.last().first().value<QCamera::State>(), QCamera::ActiveState);
+ QTRY_COMPARE(camera.status(), QCamera::ActiveStatus);
+ QCOMPARE(statusChangedSignal.last().first().value<QCamera::Status>(), QCamera::ActiveStatus);
+
+ camera.stop();
+ QCOMPARE(camera.state(), QCamera::LoadedState);
+ QCOMPARE(stateChangedSignal.last().first().value<QCamera::State>(), QCamera::LoadedState);
+ QTRY_COMPARE(camera.status(), QCamera::LoadedStatus);
+ QCOMPARE(statusChangedSignal.last().first().value<QCamera::Status>(), QCamera::LoadedStatus);
+
+ camera.unload();
+ QCOMPARE(camera.state(), QCamera::UnloadedState);
+ QCOMPARE(stateChangedSignal.last().first().value<QCamera::State>(), QCamera::UnloadedState);
+ QTRY_COMPARE(camera.status(), QCamera::UnloadedStatus);
+ QCOMPARE(statusChangedSignal.last().first().value<QCamera::Status>(), QCamera::UnloadedStatus);
+
+ QCOMPARE(camera.errorString(), QString());
+ QCOMPARE(errorSignal.count(), 0);
+}
+
+void tst_QCameraBackend::testCaptureMode()
+{
+ QCamera camera;
+
+ QSignalSpy errorSignal(&camera, SIGNAL(error(QCamera::Error)));
+ QSignalSpy stateChangedSignal(&camera, SIGNAL(stateChanged(QCamera::State)));
+ QSignalSpy captureModeSignal(&camera, SIGNAL(captureModeChanged(QCamera::CaptureMode)));
+
+ QCOMPARE(camera.captureMode(), QCamera::CaptureStillImage);
+
+ if (!camera.isCaptureModeSupported(QCamera::CaptureVideo)) {
+ camera.setCaptureMode(QCamera::CaptureVideo);
+ QCOMPARE(camera.captureMode(), QCamera::CaptureStillImage);
+ QSKIP("Video capture not supported", SkipAll);
+ }
+
+ camera.setCaptureMode(QCamera::CaptureVideo);
+ QCOMPARE(camera.captureMode(), QCamera::CaptureVideo);
+ QTRY_COMPARE(captureModeSignal.size(), 1);
+ QCOMPARE(captureModeSignal.last().first().value<QCamera::CaptureMode>(), QCamera::CaptureVideo);
+ captureModeSignal.clear();
+
+ camera.load();
+ QTRY_COMPARE(camera.status(), QCamera::LoadedStatus);
+ //capture mode should still be video
+ QCOMPARE(camera.captureMode(), QCamera::CaptureVideo);
+
+ //it should be possible to switch capture mode in Loaded state
+ camera.setCaptureMode(QCamera::CaptureStillImage);
+ QTRY_COMPARE(captureModeSignal.size(), 1);
+ QCOMPARE(captureModeSignal.last().first().value<QCamera::CaptureMode>(), QCamera::CaptureStillImage);
+ captureModeSignal.clear();
+
+ camera.setCaptureMode(QCamera::CaptureVideo);
+ QTRY_COMPARE(captureModeSignal.size(), 1);
+ QCOMPARE(captureModeSignal.last().first().value<QCamera::CaptureMode>(), QCamera::CaptureVideo);
+ captureModeSignal.clear();
+
+ camera.start();
+ QTRY_COMPARE(camera.status(), QCamera::ActiveStatus);
+ //capture mode should still be video
+ QCOMPARE(camera.captureMode(), QCamera::CaptureVideo);
+
+ stateChangedSignal.clear();
+ //it should be possible to switch capture mode in Active state
+ camera.setCaptureMode(QCamera::CaptureStillImage);
+ //camera may leave Active status, but should return to Active
+ QTest::qWait(10); //camera may leave Active status async
+ QTRY_COMPARE(camera.status(), QCamera::ActiveStatus);
+ QCOMPARE(camera.captureMode(), QCamera::CaptureStillImage);
+ QVERIFY2(stateChangedSignal.isEmpty(), "camera should not change the state during capture mode changes");
+
+ QCOMPARE(captureModeSignal.size(), 1);
+ QCOMPARE(captureModeSignal.last().first().value<QCamera::CaptureMode>(), QCamera::CaptureStillImage);
+ captureModeSignal.clear();
+
+ camera.setCaptureMode(QCamera::CaptureVideo);
+ //camera may leave Active status, but should return to Active
+ QTest::qWait(10); //camera may leave Active status async
+ QTRY_COMPARE(camera.status(), QCamera::ActiveStatus);
+ QCOMPARE(camera.captureMode(), QCamera::CaptureVideo);
+
+ QVERIFY2(stateChangedSignal.isEmpty(), "camera should not change the state during capture mode changes");
+
+ QCOMPARE(captureModeSignal.size(), 1);
+ QCOMPARE(captureModeSignal.last().first().value<QCamera::CaptureMode>(), QCamera::CaptureVideo);
+ captureModeSignal.clear();
+
+ camera.stop();
+ QCOMPARE(camera.captureMode(), QCamera::CaptureVideo);
+ camera.unload();
+ QCOMPARE(camera.captureMode(), QCamera::CaptureVideo);
+
+ QVERIFY2(errorSignal.isEmpty(), QString("Camera error: %1").arg(camera.errorString()).toLocal8Bit());
+}
+
+void tst_QCameraBackend::testCameraCapture()
+{
+ QCamera camera;
+ QCameraImageCapture imageCapture(&camera);
+ //prevents camera to flash during the test
+ camera.exposure()->setFlashMode(QCameraExposure::FlashOff);
+
+ QVERIFY(!imageCapture.isReadyForCapture());
+
+ QSignalSpy capturedSignal(&imageCapture, SIGNAL(imageCaptured(int,QImage)));
+ QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString)));
+ QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int, QCameraImageCapture::Error,QString)));
+
+ imageCapture.capture();
+ QTRY_COMPARE(errorSignal.size(), 1);
+ QCOMPARE(imageCapture.error(), QCameraImageCapture::NotReadyError);
+ QCOMPARE(capturedSignal.size(), 0);
+ errorSignal.clear();
+
+ camera.start();
+
+ QTRY_VERIFY(imageCapture.isReadyForCapture());
+ QCOMPARE(camera.status(), QCamera::ActiveStatus);
+ QCOMPARE(errorSignal.size(), 0);
+
+ int id = imageCapture.capture();
+
+ QTRY_VERIFY(!savedSignal.isEmpty());
+
+ QCOMPARE(capturedSignal.size(), 1);
+ QCOMPARE(capturedSignal.last().first().toInt(), id);
+ QCOMPARE(errorSignal.size(), 0);
+ QCOMPARE(imageCapture.error(), QCameraImageCapture::NoError);
+
+ QCOMPARE(savedSignal.last().first().toInt(), id);
+ QString location = savedSignal.last().last().toString();
+ QVERIFY(!location.isEmpty());
+ QVERIFY(QFileInfo(location).exists());
+ QImageReader reader(location);
+ reader.setScaledSize(QSize(320,240));
+ QVERIFY(!reader.read().isNull());
+
+ QFile(location).remove();
+}
+
+
+void tst_QCameraBackend::testCaptureToBuffer()
+{
+ QCamera camera;
+ QCameraImageCapture imageCapture(&camera);
+ camera.exposure()->setFlashMode(QCameraExposure::FlashOff);
+
+ camera.load();
+
+#ifdef Q_WS_MAEMO_6
+ QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer));
+#endif
+
+ if (!imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer))
+ QSKIP("Buffer capture not supported", SkipAll);
+
+ QTRY_COMPARE(camera.status(), QCamera::LoadedStatus);
+
+ QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_Jpeg);
+
+ QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToFile));
+ QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer));
+ QVERIFY(imageCapture.isCaptureDestinationSupported(
+ QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile));
+
+ QSignalSpy destinationChangedSignal(&imageCapture, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations)));
+
+ QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToFile);
+ imageCapture.setCaptureDestination(QCameraImageCapture::CaptureToBuffer);
+ QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToBuffer);
+ QCOMPARE(destinationChangedSignal.size(), 1);
+ QCOMPARE(destinationChangedSignal.first().first().value<QCameraImageCapture::CaptureDestinations>(),
+ QCameraImageCapture::CaptureToBuffer);
+
+ QSignalSpy capturedSignal(&imageCapture, SIGNAL(imageCaptured(int,QImage)));
+ QSignalSpy imageAvailableSignal(&imageCapture, SIGNAL(imageAvailable(int,QVideoFrame)));
+ QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString)));
+ QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int, QCameraImageCapture::Error,QString)));
+
+ camera.start();
+ QTRY_VERIFY(imageCapture.isReadyForCapture());
+
+ int id = imageCapture.capture();
+ QTRY_VERIFY(!imageAvailableSignal.isEmpty());
+
+ QVERIFY(errorSignal.isEmpty());
+ QVERIFY(!capturedSignal.isEmpty());
+ QVERIFY(!imageAvailableSignal.isEmpty());
+
+ QTest::qWait(2000);
+ QVERIFY(savedSignal.isEmpty());
+
+ QCOMPARE(capturedSignal.first().first().toInt(), id);
+ QCOMPARE(imageAvailableSignal.first().first().toInt(), id);
+
+ QVideoFrame frame = imageAvailableSignal.first().last().value<QVideoFrame>();
+ QVERIFY(frame.isValid());
+ QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_Jpeg);
+ QVERIFY(!frame.size().isEmpty());
+ QVERIFY(frame.map(QAbstractVideoBuffer::ReadOnly));
+ QByteArray data((const char *)frame.bits(), frame.mappedBytes());
+ frame.unmap();
+ frame = QVideoFrame();
+
+ QVERIFY(!data.isEmpty());
+ QBuffer buffer;
+ buffer.setData(data);
+ buffer.open(QIODevice::ReadOnly);
+ QImageReader reader(&buffer, "JPG");
+ reader.setScaledSize(QSize(640,480));
+ QImage img(reader.read());
+ QVERIFY(!img.isNull());
+
+ capturedSignal.clear();
+ imageAvailableSignal.clear();
+ savedSignal.clear();
+
+ //Capture to yuv buffer
+#ifdef Q_WS_MAEMO_6
+ QVERIFY(imageCapture.supportedBufferFormats().contains(QVideoFrame::Format_UYVY));
+#endif
+
+ if (imageCapture.supportedBufferFormats().contains(QVideoFrame::Format_UYVY)) {
+ imageCapture.setBufferFormat(QVideoFrame::Format_UYVY);
+ QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_UYVY);
+
+ id = imageCapture.capture();
+ QTRY_VERIFY(!imageAvailableSignal.isEmpty());
+
+ QVERIFY(errorSignal.isEmpty());
+ QVERIFY(!capturedSignal.isEmpty());
+ QVERIFY(!imageAvailableSignal.isEmpty());
+ QVERIFY(savedSignal.isEmpty());
+
+ QTest::qWait(2000);
+ QVERIFY(savedSignal.isEmpty());
+
+ frame = imageAvailableSignal.first().last().value<QVideoFrame>();
+ QVERIFY(frame.isValid());
+
+ qDebug() << frame.pixelFormat();
+ QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_UYVY);
+ QVERIFY(!frame.size().isEmpty());
+ frame = QVideoFrame();
+
+ capturedSignal.clear();
+ imageAvailableSignal.clear();
+ savedSignal.clear();
+
+ imageCapture.setBufferFormat(QVideoFrame::Format_Jpeg);
+ QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_Jpeg);
+ }
+
+ //Try to capture to both buffer and file
+#ifdef Q_WS_MAEMO_6
+ QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile));
+#endif
+ if (imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile)) {
+ imageCapture.setCaptureDestination(QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile);
+
+ int oldId = id;
+ id = imageCapture.capture();
+ QVERIFY(id != oldId);
+ QTRY_VERIFY(!savedSignal.isEmpty());
+
+ QVERIFY(errorSignal.isEmpty());
+ QVERIFY(!capturedSignal.isEmpty());
+ QVERIFY(!imageAvailableSignal.isEmpty());
+ QVERIFY(!savedSignal.isEmpty());
+
+ QCOMPARE(capturedSignal.first().first().toInt(), id);
+ QCOMPARE(imageAvailableSignal.first().first().toInt(), id);
+
+ frame = imageAvailableSignal.first().last().value<QVideoFrame>();
+ QVERIFY(frame.isValid());
+ QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_Jpeg);
+ QVERIFY(!frame.size().isEmpty());
+
+ QString fileName = savedSignal.first().last().toString();
+ QVERIFY(QFileInfo(fileName).exists());
+ }
+}
+
+void tst_QCameraBackend::testCameraCaptureMetadata()
+{
+#ifndef Q_WS_MAEMO_6
+ QSKIP("Capture metadata is supported only on harmattan", SkipAll);
+#endif
+
+ QCamera camera;
+ QCameraImageCapture imageCapture(&camera);
+ camera.exposure()->setFlashMode(QCameraExposure::FlashOff);
+
+ QSignalSpy metadataSignal(&imageCapture, SIGNAL(imageMetadataAvailable(int,QtMultimediaKit::MetaData,QVariant)));
+ QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString)));
+
+ camera.start();
+
+ QTRY_VERIFY(imageCapture.isReadyForCapture());
+
+ int id = imageCapture.capture(QString::fromLatin1("/dev/null"));
+ QTRY_VERIFY(!savedSignal.isEmpty());
+ QVERIFY(!metadataSignal.isEmpty());
+ QCOMPARE(metadataSignal.first().first().toInt(), id);
+}
+
+void tst_QCameraBackend::testExposureCompensation()
+{
+#if !defined(Q_WS_MAEMO_6) && !defined(Q_WS_MAEMO_5) && !defined(Q_OS_SYMBIAN)
+ QSKIP("Capture exposure parameters are supported only on mobile platforms", SkipAll);
+#endif
+
+ QCamera camera;
+ QCameraExposure *exposure = camera.exposure();
+
+ QSignalSpy exposureCompensationSignal(exposure, SIGNAL(exposureCompensationChanged(qreal)));
+
+#ifdef Q_OS_SYMBIAN
+ // Camera needs to be started, see: QTMOBILITY-1566
+ camera.load();
+ QTRY_COMPARE(camera.status(), QCamera::LoadedStatus);
+#endif // Q_OS_SYMBIAN
+
+ //it should be possible to set exposure parameters in Unloaded state
+ QCOMPARE(exposure->exposureCompensation()+1.0, 1.0);
+ exposure->setExposureCompensation(1.0);
+ QCOMPARE(exposure->exposureCompensation(), 1.0);
+ QTRY_COMPARE(exposureCompensationSignal.count(), 1);
+ QCOMPARE(exposureCompensationSignal.last().first().toReal(), 1.0);
+
+ //exposureCompensationChanged should not be emitted when value is not changed
+ exposure->setExposureCompensation(1.0);
+ QTest::qWait(50);
+ QCOMPARE(exposureCompensationSignal.count(), 1);
+
+ //exposure compensation should be preserved during load/start
+ camera.load();
+ QTRY_COMPARE(camera.status(), QCamera::LoadedStatus);
+
+ QCOMPARE(exposure->exposureCompensation(), 1.0);
+
+ exposureCompensationSignal.clear();
+ exposure->setExposureCompensation(-1.0);
+ QCOMPARE(exposure->exposureCompensation(), -1.0);
+ QTRY_COMPARE(exposureCompensationSignal.count(), 1);
+ QCOMPARE(exposureCompensationSignal.last().first().toReal(), -1.0);
+
+ camera.start();
+ QTRY_COMPARE(camera.status(), QCamera::ActiveStatus);
+
+ QCOMPARE(exposure->exposureCompensation(), -1.0);
+
+ exposureCompensationSignal.clear();
+ exposure->setExposureCompensation(1.0);
+ QCOMPARE(exposure->exposureCompensation(), 1.0);
+ QTRY_COMPARE(exposureCompensationSignal.count(), 1);
+ QCOMPARE(exposureCompensationSignal.last().first().toReal(), 1.0);
+}
+
+void tst_QCameraBackend::testExposureMode()
+{
+#if !defined(Q_WS_MAEMO_6) && !defined(Q_WS_MAEMO_5) && !defined(Q_OS_SYMBIAN)
+ QSKIP("Capture exposure parameters are supported only on mobile platforms", SkipAll);
+#endif
+
+ QCamera camera;
+ QCameraExposure *exposure = camera.exposure();
+
+#ifdef Q_WS_MAEMO_6
+ QEXPECT_FAIL("", "Camerabin reports Manual exposure instead of Auto", Continue);
+#endif
+ QCOMPARE(exposure->exposureMode(), QCameraExposure::ExposureAuto);
+
+#ifdef Q_OS_SYMBIAN
+ // Camera needs to be started, see: QTMOBILITY-1566
+ camera.load();
+ QTRY_COMPARE(camera.status(), QCamera::LoadedStatus);
+#endif // Q_OS_SYMBIAN
+
+ // Night
+ exposure->setExposureMode(QCameraExposure::ExposureNight);
+ QCOMPARE(exposure->exposureMode(), QCameraExposure::ExposureNight);
+ camera.start();
+ QTRY_COMPARE(camera.status(), QCamera::ActiveStatus);
+ QCOMPARE(exposure->exposureMode(), QCameraExposure::ExposureNight);
+
+ camera.unload();
+ QTRY_COMPARE(camera.status(), QCamera::UnloadedStatus);
+
+#ifdef Q_OS_SYMBIAN
+ // Camera needs to be started, see: QTMOBILITY-1566
+ camera.load();
+ QTRY_COMPARE(camera.status(), QCamera::LoadedStatus);
+#endif // Q_OS_SYMBIAN
+
+ // Auto
+ exposure->setExposureMode(QCameraExposure::ExposureAuto);
+ QCOMPARE(exposure->exposureMode(), QCameraExposure::ExposureAuto);
+ camera.start();
+ QTRY_COMPARE(camera.status(), QCamera::ActiveStatus);
+ QCOMPARE(exposure->exposureMode(), QCameraExposure::ExposureAuto);
+}
+
+QTEST_MAIN(tst_QCameraBackend)
+
+#include "tst_qcamerabackend.moc"
diff --git a/tests/auto/qdeclarativeaudio/qdeclarativeaudio.pro b/tests/auto/qdeclarativeaudio/qdeclarativeaudio.pro
new file mode 100644
index 000000000..a7ab28581
--- /dev/null
+++ b/tests/auto/qdeclarativeaudio/qdeclarativeaudio.pro
@@ -0,0 +1,18 @@
+load(qttest_p4)
+
+QT += multimediakit-private declarative
+
+# TARGET = tst_qdeclarativeaudio
+# CONFIG += testcase
+
+HEADERS += \
+ $$QT.multimediakit.sources/../imports/multimedia/qdeclarativeaudio_p.h \
+ $$QT.multimediakit.sources/../imports/multimedia/qdeclarativemediabase_p.h \
+ $$QT.multimediakit.sources/../imports/multimedia/qdeclarativemediametadata_p.h
+
+SOURCES += \
+ tst_qdeclarativeaudio.cpp \
+ $$QT.multimediakit.sources/../imports/multimedia/qdeclarativeaudio.cpp \
+ $$QT.multimediakit.sources/../imports/multimedia/qdeclarativemediabase.cpp
+
+INCLUDEPATH += $$QT.multimediakit.sources/../imports/multimedia
diff --git a/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp b/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp
new file mode 100644
index 000000000..df7025f6f
--- /dev/null
+++ b/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp
@@ -0,0 +1,1302 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=plugins/declarative/multimedia
+
+#include <QtTest/QtTest>
+
+#include "qdeclarativeaudio_p.h"
+#include "qdeclarativemediametadata_p.h"
+
+#include <qmediaplayercontrol.h>
+#include <qmediaservice.h>
+#include <qmediaserviceprovider.h>
+#include <qmetadatareadercontrol.h>
+
+#include <QtGui/qapplication.h>
+
+class tst_QDeclarativeAudio : public QObject
+{
+ Q_OBJECT
+public slots:
+ void initTestCase();
+
+private slots:
+ void nullPlayerControl();
+ void nullMetaDataControl();
+ void nullService();
+
+ void source();
+ void autoLoad();
+ void playing();
+ void paused();
+ void duration();
+ void position();
+ void volume();
+ void muted();
+ void bufferProgress();
+ void seekable();
+ void playbackRate();
+ void status();
+ void metaData_data();
+ void metaData();
+ void error();
+ void loops();
+};
+
+Q_DECLARE_METATYPE(QtMultimediaKit::MetaData);
+Q_DECLARE_METATYPE(QDeclarativeAudio::Error);
+
+class QtTestMediaPlayerControl : public QMediaPlayerControl
+{
+ Q_OBJECT
+public:
+ QtTestMediaPlayerControl(QObject *parent = 0)
+ : QMediaPlayerControl(parent)
+ , m_state(QMediaPlayer::StoppedState)
+ , m_mediaStatus(QMediaPlayer::NoMedia)
+ , m_duration(0)
+ , m_position(0)
+ , m_playbackRate(1.0)
+ , m_volume(50)
+ , m_bufferStatus(0)
+ , m_muted(false)
+ , m_audioAvailable(false)
+ , m_videoAvailable(false)
+ , m_seekable(false)
+ {
+ }
+
+ QMediaPlayer::State state() const { return m_state; }
+ void updateState(QMediaPlayer::State state) { emit stateChanged(m_state = state); }
+
+ QMediaPlayer::MediaStatus mediaStatus() const { return m_mediaStatus; }
+ void updateMediaStatus(QMediaPlayer::MediaStatus status) {
+ emit mediaStatusChanged(m_mediaStatus = status); }
+ void updateMediaStatus(QMediaPlayer::MediaStatus status, QMediaPlayer::State state)
+ {
+ m_mediaStatus = status;
+ m_state = state;
+
+ emit mediaStatusChanged(m_mediaStatus);
+ emit stateChanged(m_state);
+ }
+
+ qint64 duration() const { return m_duration; }
+ void setDuration(qint64 duration) { emit durationChanged(m_duration = duration); }
+
+ qint64 position() const { return m_position; }
+ void setPosition(qint64 position) { emit positionChanged(m_position = position); }
+
+ int volume() const { return m_volume; }
+ void setVolume(int volume) { emit volumeChanged(m_volume = volume); }
+
+ bool isMuted() const { return m_muted; }
+ void setMuted(bool muted) { emit mutedChanged(m_muted = muted); }
+
+ int bufferStatus() const { return m_bufferStatus; }
+ void setBufferStatus(int status) { emit bufferStatusChanged(m_bufferStatus = status); }
+
+ bool isAudioAvailable() const { return m_audioAvailable; }
+ void setAudioAvailable(bool available) {
+ emit audioAvailableChanged(m_audioAvailable = available); }
+ bool isVideoAvailable() const { return m_videoAvailable; }
+ void setVideoAvailable(bool available) {
+ emit videoAvailableChanged(m_videoAvailable = available); }
+
+ bool isSeekable() const { return m_seekable; }
+ void setSeekable(bool seekable) { emit seekableChanged(m_seekable = seekable); }
+
+ QMediaTimeRange availablePlaybackRanges() const { return QMediaTimeRange(); }
+
+ qreal playbackRate() const { return m_playbackRate; }
+ void setPlaybackRate(qreal rate) { emit playbackRateChanged(m_playbackRate = rate); }
+
+ QMediaContent media() const { return m_media; }
+ const QIODevice *mediaStream() const { return 0; }
+ void setMedia(const QMediaContent &media, QIODevice *)
+ {
+ m_media = media;
+
+ m_mediaStatus = m_media.isNull()
+ ? QMediaPlayer::NoMedia
+ : QMediaPlayer::LoadingMedia;
+
+ emit mediaChanged(m_media);
+ emit mediaStatusChanged(m_mediaStatus);
+ }
+
+ void play()
+ {
+ m_state = QMediaPlayer::PlayingState;
+ if (m_mediaStatus == QMediaPlayer::EndOfMedia)
+ updateMediaStatus(QMediaPlayer::LoadedMedia);
+ emit stateChanged(m_state);
+ }
+ void pause() { emit stateChanged(m_state = QMediaPlayer::PausedState); }
+ void stop() { emit stateChanged(m_state = QMediaPlayer::StoppedState); }
+
+ void emitError(QMediaPlayer::Error err, const QString &errorString) {
+ emit error(err, errorString); }
+
+private:
+ QMediaPlayer::State m_state;
+ QMediaPlayer::MediaStatus m_mediaStatus;
+ qint64 m_duration;
+ qint64 m_position;
+ qreal m_playbackRate;
+ int m_volume;
+ int m_bufferStatus;
+ bool m_muted;
+ bool m_audioAvailable;
+ bool m_videoAvailable;
+ bool m_seekable;
+ QMediaContent m_media;
+};
+
+class QtTestMetaDataControl : public QMetaDataReaderControl
+{
+ Q_OBJECT
+public:
+ QtTestMetaDataControl(QObject *parent = 0)
+ : QMetaDataReaderControl(parent)
+ {
+ }
+
+ bool isMetaDataAvailable() const { return true; }
+
+ QVariant metaData(QtMultimediaKit::MetaData key) const { return m_metaData.value(key); }
+ void setMetaData(QtMultimediaKit::MetaData key, const QVariant &value) {
+ m_metaData.insert(key, value); emit metaDataChanged(); }
+
+ QList<QtMultimediaKit::MetaData> availableMetaData() const { return m_metaData.keys(); }
+
+ QVariant extendedMetaData(const QString &) const { return QVariant(); }
+ QStringList availableExtendedMetaData() const { return QStringList(); }
+
+private:
+ QMap<QtMultimediaKit::MetaData, QVariant> m_metaData;
+};
+
+class QtTestMediaService : public QMediaService
+{
+ Q_OBJECT
+public:
+ QtTestMediaService(
+ QtTestMediaPlayerControl *playerControl,
+ QtTestMetaDataControl *metaDataControl,
+ QObject *parent)
+ : QMediaService(parent)
+ , playerControl(playerControl)
+ , metaDataControl(metaDataControl)
+ {
+ }
+
+ QMediaControl *requestControl(const char *name)
+ {
+ if (qstrcmp(name, QMediaPlayerControl_iid) == 0)
+ return playerControl;
+ else if (qstrcmp(name, QMetaDataReaderControl_iid) == 0)
+ return metaDataControl;
+ else
+ return 0;
+ }
+
+ void releaseControl(QMediaControl *) {}
+
+ QtTestMediaPlayerControl *playerControl;
+ QtTestMetaDataControl *metaDataControl;
+};
+
+class QtTestMediaServiceProvider : public QMediaServiceProvider
+{
+ Q_OBJECT
+public:
+ QtTestMediaServiceProvider()
+ : service(new QtTestMediaService(
+ new QtTestMediaPlayerControl(this), new QtTestMetaDataControl(this), this))
+ {
+ setDefaultServiceProvider(this);
+ }
+
+ QtTestMediaServiceProvider(QtTestMediaService *service)
+ : service(service)
+ {
+ setDefaultServiceProvider(this);
+ }
+
+ QtTestMediaServiceProvider(
+ QtTestMediaPlayerControl *playerControl, QtTestMetaDataControl *metaDataControl)
+ : service(new QtTestMediaService(playerControl, metaDataControl, this))
+ {
+ setDefaultServiceProvider(this);
+ }
+
+ ~QtTestMediaServiceProvider()
+ {
+ setDefaultServiceProvider(0);
+ }
+
+ QMediaService *requestService(
+ const QByteArray &type,
+ const QMediaServiceProviderHint & = QMediaServiceProviderHint())
+ {
+ requestedService = type;
+
+ return service;
+ }
+
+ void releaseService(QMediaService *) {}
+
+ inline QtTestMediaPlayerControl *playerControl() { return service->playerControl; }
+ inline QtTestMetaDataControl *metaDataControl() { return service->metaDataControl; }
+
+ QtTestMediaService *service;
+ QByteArray requestedService;
+};
+
+void tst_QDeclarativeAudio::initTestCase()
+{
+ qRegisterMetaType<QDeclarativeAudio::Error>();
+}
+
+void tst_QDeclarativeAudio::nullPlayerControl()
+{
+ QtTestMetaDataControl metaDataControl;
+ QtTestMediaServiceProvider provider(0, &metaDataControl);
+
+ QDeclarativeAudio audio;
+ audio.classBegin();
+
+ QCOMPARE(audio.source(), QUrl());
+ audio.setSource(QUrl("http://example.com"));
+ QCOMPARE(audio.source(), QUrl("http://example.com"));
+
+ QCOMPARE(audio.isPlaying(), false);
+ audio.setPlaying(true);
+ QCOMPARE(audio.isPlaying(), true);
+ audio.setPlaying(false);
+ audio.play();
+ QCOMPARE(audio.isPlaying(), false);
+
+ QCOMPARE(audio.isPaused(), false);
+ audio.pause();
+ QCOMPARE(audio.isPaused(), false);
+ audio.setPaused(true);
+ QCOMPARE(audio.isPaused(), true);
+
+ QCOMPARE(audio.duration(), 0);
+
+ QCOMPARE(audio.position(), 0);
+ audio.setPosition(10000);
+ QCOMPARE(audio.position(), 10000);
+
+ QCOMPARE(audio.volume(), qreal(1.0));
+ audio.setVolume(0.5);
+ QCOMPARE(audio.volume(), qreal(0.5));
+
+ QCOMPARE(audio.isMuted(), false);
+ audio.setMuted(true);
+ QCOMPARE(audio.isMuted(), true);
+
+ QCOMPARE(audio.bufferProgress(), qreal(0));
+
+ QCOMPARE(audio.isSeekable(), false);
+
+ QCOMPARE(audio.playbackRate(), qreal(1.0));
+
+ QCOMPARE(audio.status(), QDeclarativeAudio::NoMedia);
+
+ QCOMPARE(audio.error(), QDeclarativeAudio::ServiceMissing);
+}
+
+void tst_QDeclarativeAudio::nullMetaDataControl()
+{
+ QtTestMediaPlayerControl playerControl;
+ QtTestMediaServiceProvider provider(&playerControl, 0);
+
+ QDeclarativeAudio audio;
+ audio.classBegin();
+ audio.componentComplete();
+
+ QVERIFY(audio.metaData());
+}
+
+void tst_QDeclarativeAudio::nullService()
+{
+ QtTestMediaServiceProvider provider(0);
+
+ QDeclarativeAudio audio;
+ audio.classBegin();
+
+ QCOMPARE(audio.source(), QUrl());
+ audio.setSource(QUrl("http://example.com"));
+ QCOMPARE(audio.source(), QUrl("http://example.com"));
+
+ QCOMPARE(audio.isPlaying(), false);
+ audio.setPlaying(true);
+ QCOMPARE(audio.isPlaying(), true);
+ audio.setPlaying(false);
+ audio.play();
+ QCOMPARE(audio.isPlaying(), false);
+
+ QCOMPARE(audio.isPaused(), false);
+ audio.pause();
+ QCOMPARE(audio.isPaused(), false);
+ audio.setPaused(true);
+ QCOMPARE(audio.isPaused(), true);
+
+ QCOMPARE(audio.duration(), 0);
+
+ QCOMPARE(audio.position(), 0);
+ audio.setPosition(10000);
+ QCOMPARE(audio.position(), 10000);
+
+ QCOMPARE(audio.volume(), qreal(1.0));
+ audio.setVolume(0.5);
+ QCOMPARE(audio.volume(), qreal(0.5));
+
+ QCOMPARE(audio.isMuted(), false);
+ audio.setMuted(true);
+ QCOMPARE(audio.isMuted(), true);
+
+ QCOMPARE(audio.bufferProgress(), qreal(0));
+
+ QCOMPARE(audio.isSeekable(), false);
+
+ QCOMPARE(audio.playbackRate(), qreal(1.0));
+
+ QCOMPARE(audio.status(), QDeclarativeAudio::NoMedia);
+
+ QCOMPARE(audio.error(), QDeclarativeAudio::ServiceMissing);
+
+ QVERIFY(audio.metaData());
+}
+
+void tst_QDeclarativeAudio::source()
+{
+ const QUrl url1("http://example.com");
+ const QUrl url2("file:///local/path");
+ const QUrl url3;
+
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+ audio.componentComplete();
+
+ QSignalSpy spy(&audio, SIGNAL(sourceChanged()));
+
+ audio.setSource(url1);
+ QCOMPARE(audio.source(), url1);
+ QCOMPARE(provider.playerControl()->media().canonicalUrl(), url1);
+ QCOMPARE(spy.count(), 1);
+
+ audio.setSource(url2);
+ QCOMPARE(audio.source(), url2);
+ QCOMPARE(provider.playerControl()->media().canonicalUrl(), url2);
+ QCOMPARE(spy.count(), 2);
+
+ audio.setSource(url3);
+ QCOMPARE(audio.source(), url3);
+ QCOMPARE(provider.playerControl()->media().canonicalUrl(), url3);
+ QCOMPARE(spy.count(), 3);
+}
+
+void tst_QDeclarativeAudio::autoLoad()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+ audio.componentComplete();
+
+ QSignalSpy spy(&audio, SIGNAL(autoLoadChanged()));
+
+ QCOMPARE(audio.isAutoLoad(), true);
+
+ audio.setAutoLoad(false);
+ QCOMPARE(audio.isAutoLoad(), false);
+ QCOMPARE(spy.count(), 1);
+
+ audio.setSource(QUrl("http://example.com"));
+ QCOMPARE(audio.source(), QUrl("http://example.com"));
+ audio.play();
+ QCOMPARE(audio.isPlaying(), true);
+ audio.stop();
+
+ audio.setAutoLoad(true);
+ audio.setSource(QUrl("http://example.com"));
+ audio.setPaused(true);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(audio.isPaused(), true);
+}
+
+void tst_QDeclarativeAudio::playing()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+
+ QSignalSpy playingChangedSpy(&audio, SIGNAL(playingChanged()));
+ QSignalSpy startedSpy(&audio, SIGNAL(started()));
+ QSignalSpy stoppedSpy(&audio, SIGNAL(stopped()));
+
+ int playingChanged = 0;
+ int started = 0;
+ int stopped = 0;
+
+ audio.componentComplete();
+ audio.setSource(QUrl("http://example.com"));
+
+ QCOMPARE(audio.isPlaying(), false);
+
+ // setPlaying(true) when stopped.
+ audio.setPlaying(true);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(false) when playing.
+ audio.setPlaying(false);
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ // play() when stopped.
+ audio.play();
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // stop() when playing.
+ audio.stop();
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ // stop() when stopped.
+ audio.stop();
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(false) when stopped.
+ audio.setPlaying(false);
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ audio.setPlaying(true);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(true) when playing.
+ audio.setPlaying(true);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // play() when playing.
+ audio.play();
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+}
+
+void tst_QDeclarativeAudio::paused()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+
+ QSignalSpy playingChangedSpy(&audio, SIGNAL(playingChanged()));
+ QSignalSpy pausedChangedSpy(&audio, SIGNAL(pausedChanged()));
+ QSignalSpy startedSpy(&audio, SIGNAL(started()));
+ QSignalSpy pausedSpy(&audio, SIGNAL(paused()));
+ QSignalSpy resumedSpy(&audio, SIGNAL(resumed()));
+ QSignalSpy stoppedSpy(&audio, SIGNAL(stopped()));
+
+ int playingChanged = 0;
+ int pausedChanged = 0;
+ int started = 0;
+ int paused = 0;
+ int resumed = 0;
+ int stopped = 0;
+
+ audio.componentComplete();
+ audio.setSource(QUrl("http://example.com"));
+
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(audio.isPaused(), false);
+
+ // setPlaying(true) when stopped.
+ audio.setPlaying(true);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(audio.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(true) when playing.
+ audio.setPaused(true);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), ++paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(true) when paused.
+ audio.setPaused(true);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // pause() when paused.
+ audio.pause();
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(false) when paused.
+ audio.setPaused(false);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(audio.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), ++resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(false) when playing.
+ audio.setPaused(false);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(audio.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // pause() when playing.
+ audio.pause();
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), ++paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(false) when paused.
+ audio.setPlaying(false);
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ // setPaused(true) when stopped and paused.
+ audio.setPaused(true);
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(false) when stopped and paused.
+ audio.setPaused(false);
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(audio.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(true) when stopped.
+ audio.setPaused(true);
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(true) when stopped and paused.
+ audio.setPlaying(true);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(pausedSpy.count(), ++paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // play() when paused.
+ audio.play();
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(audio.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), ++resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(true) when playing.
+ audio.setPaused(true);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), ++paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // stop() when paused.
+ audio.stop();
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(audio.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ // setPaused(true) when stopped.
+ audio.setPaused(true);
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // stop() when stopped and paused.
+ audio.stop();
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(audio.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // pause() when stopped.
+ audio.pause();
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(pausedSpy.count(), ++paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(false) when paused.
+ audio.setPlaying(false);
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ // pause() when stopped and paused.
+ audio.pause();
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(pausedSpy.count(), ++paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(false) when paused.
+ audio.setPlaying(false);
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(audio.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ // play() when stopped and paused.
+ audio.play();
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(audio.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+}
+
+void tst_QDeclarativeAudio::duration()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+ audio.componentComplete();
+
+ QSignalSpy spy(&audio, SIGNAL(durationChanged()));
+
+ QCOMPARE(audio.duration(), 0);
+
+ provider.playerControl()->setDuration(4040);
+ QCOMPARE(audio.duration(), 4040);
+ QCOMPARE(spy.count(), 1);
+
+ provider.playerControl()->setDuration(-129);
+ QCOMPARE(audio.duration(), -129);
+ QCOMPARE(spy.count(), 2);
+
+ provider.playerControl()->setDuration(0);
+ QCOMPARE(audio.duration(), 0);
+ QCOMPARE(spy.count(), 3);
+
+ // Unnecessary duration changed signals aren't filtered.
+ provider.playerControl()->setDuration(0);
+ QCOMPARE(audio.duration(), 0);
+ QCOMPARE(spy.count(), 4);
+}
+
+void tst_QDeclarativeAudio::position()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+ audio.componentComplete();
+
+ QSignalSpy spy(&audio, SIGNAL(positionChanged()));
+
+ QCOMPARE(audio.position(), 0);
+
+ // QDeclarativeAudio won't bound set positions to the duration. A media service may though.
+ QCOMPARE(audio.duration(), 0);
+
+ audio.setPosition(450);
+ QCOMPARE(audio.position(), 450);
+ QCOMPARE(provider.playerControl()->position(), qint64(450));
+ QCOMPARE(spy.count(), 1);
+
+ audio.setPosition(-5403);
+ QCOMPARE(audio.position(), -5403);
+ QCOMPARE(provider.playerControl()->position(), qint64(-5403));
+ QCOMPARE(spy.count(), 2);
+
+ audio.setPosition(-5403);
+ QCOMPARE(audio.position(), -5403);
+ QCOMPARE(provider.playerControl()->position(), qint64(-5403));
+ QCOMPARE(spy.count(), 2);
+
+ // Check the signal change signal is emitted if the change originates from the media service.
+ provider.playerControl()->setPosition(0);
+ QCOMPARE(audio.position(), 0);
+ QCOMPARE(spy.count(), 3);
+
+ connect(&audio, SIGNAL(positionChanged()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ provider.playerControl()->updateState(QMediaPlayer::PlayingState);
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(spy.count() > 3 && spy.count() < 6); // 4 or 5
+
+ provider.playerControl()->updateState(QMediaPlayer::PausedState);
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(spy.count() < 6);
+}
+
+void tst_QDeclarativeAudio::volume()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+ audio.componentComplete();
+
+ QSignalSpy spy(&audio, SIGNAL(volumeChanged()));
+
+ QCOMPARE(audio.volume(), qreal(1.0));
+
+ audio.setVolume(0.7);
+ QCOMPARE(audio.volume(), qreal(0.7));
+ QCOMPARE(provider.playerControl()->volume(), 70);
+ QCOMPARE(spy.count(), 1);
+
+ audio.setVolume(0.7);
+ QCOMPARE(audio.volume(), qreal(0.7));
+ QCOMPARE(provider.playerControl()->volume(), 70);
+ QCOMPARE(spy.count(), 1);
+
+ provider.playerControl()->setVolume(30);
+ QCOMPARE(audio.volume(), qreal(0.3));
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_QDeclarativeAudio::muted()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+ audio.componentComplete();
+
+ QSignalSpy spy(&audio, SIGNAL(mutedChanged()));
+
+ QCOMPARE(audio.isMuted(), false);
+
+ audio.setMuted(true);
+ QCOMPARE(audio.isMuted(), true);
+ QCOMPARE(provider.playerControl()->isMuted(), true);
+ QCOMPARE(spy.count(), 1);
+
+ provider.playerControl()->setMuted(false);
+ QCOMPARE(audio.isMuted(), false);
+ QCOMPARE(spy.count(), 2);
+
+ audio.setMuted(false);
+ QCOMPARE(audio.isMuted(), false);
+ QCOMPARE(provider.playerControl()->isMuted(), false);
+ QCOMPARE(spy.count(), 3);
+}
+
+void tst_QDeclarativeAudio::bufferProgress()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+ audio.componentComplete();
+
+ QSignalSpy spy(&audio, SIGNAL(bufferProgressChanged()));
+
+ QCOMPARE(audio.bufferProgress(), qreal(0.0));
+
+ provider.playerControl()->setBufferStatus(20);
+ QCOMPARE(audio.bufferProgress(), qreal(0.2));
+ QCOMPARE(spy.count(), 1);
+
+ provider.playerControl()->setBufferStatus(20);
+ QCOMPARE(audio.bufferProgress(), qreal(0.2));
+ QCOMPARE(spy.count(), 2);
+
+ provider.playerControl()->setBufferStatus(40);
+ QCOMPARE(audio.bufferProgress(), qreal(0.4));
+ QCOMPARE(spy.count(), 3);
+
+ connect(&audio, SIGNAL(positionChanged()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ provider.playerControl()->updateMediaStatus(
+ QMediaPlayer::BufferingMedia, QMediaPlayer::PlayingState);
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(spy.count() > 3 && spy.count() < 6); // 4 or 5
+
+ provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferedMedia);
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(spy.count() < 6);
+}
+
+void tst_QDeclarativeAudio::seekable()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+ audio.componentComplete();
+
+ QSignalSpy spy(&audio, SIGNAL(seekableChanged()));
+
+ QCOMPARE(audio.isSeekable(), false);
+
+ provider.playerControl()->setSeekable(true);
+ QCOMPARE(audio.isSeekable(), true);
+ QCOMPARE(spy.count(), 1);
+
+ provider.playerControl()->setSeekable(true);
+ QCOMPARE(audio.isSeekable(), true);
+ QCOMPARE(spy.count(), 2);
+
+ provider.playerControl()->setSeekable(false);
+ QCOMPARE(audio.isSeekable(), false);
+ QCOMPARE(spy.count(), 3);
+}
+
+void tst_QDeclarativeAudio::playbackRate()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+ audio.componentComplete();
+
+ QSignalSpy spy(&audio, SIGNAL(playbackRateChanged()));
+
+ QCOMPARE(audio.playbackRate(), qreal(1.0));
+
+ audio.setPlaybackRate(0.5);
+ QCOMPARE(audio.playbackRate(), qreal(0.5));
+ QCOMPARE(provider.playerControl()->playbackRate(), qreal(0.5));
+ QCOMPARE(spy.count(), 1);
+
+ provider.playerControl()->setPlaybackRate(2.0);
+ QCOMPARE(provider.playerControl()->playbackRate(), qreal(2.0));
+ QCOMPARE(spy.count(), 2);
+
+ audio.setPlaybackRate(2.0);
+ QCOMPARE(audio.playbackRate(), qreal(2.0));
+ QCOMPARE(provider.playerControl()->playbackRate(), qreal(2.0));
+ QCOMPARE(spy.count(), 3);
+}
+
+void tst_QDeclarativeAudio::status()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+ audio.componentComplete();
+
+ QSignalSpy statusChangedSpy(&audio, SIGNAL(statusChanged()));
+
+ QCOMPARE(audio.status(), QDeclarativeAudio::NoMedia);
+
+ // Set media, start loading.
+ provider.playerControl()->updateMediaStatus(QMediaPlayer::LoadingMedia);
+ QCOMPARE(audio.status(), QDeclarativeAudio::Loading);
+ QCOMPARE(statusChangedSpy.count(), 1);
+
+ // Finish loading.
+ provider.playerControl()->updateMediaStatus(QMediaPlayer::LoadedMedia);
+ QCOMPARE(audio.status(), QDeclarativeAudio::Loaded);
+ QCOMPARE(statusChangedSpy.count(), 2);
+
+ // Play, start buffering.
+ provider.playerControl()->updateMediaStatus(
+ QMediaPlayer::StalledMedia, QMediaPlayer::PlayingState);
+ QCOMPARE(audio.status(), QDeclarativeAudio::Stalled);
+ QCOMPARE(statusChangedSpy.count(), 3);
+
+ // Enough data buffered to proceed.
+ provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferingMedia);
+ QCOMPARE(audio.status(), QDeclarativeAudio::Buffering);
+ QCOMPARE(statusChangedSpy.count(), 4);
+
+ // Errant second buffering status changed.
+ provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferingMedia);
+ QCOMPARE(audio.status(), QDeclarativeAudio::Buffering);
+ QCOMPARE(statusChangedSpy.count(), 4);
+
+ // Buffer full.
+ provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferedMedia);
+ QCOMPARE(audio.status(), QDeclarativeAudio::Buffered);
+ QCOMPARE(statusChangedSpy.count(), 5);
+
+ // Buffer getting low.
+ provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferingMedia);
+ QCOMPARE(audio.status(), QDeclarativeAudio::Buffering);
+ QCOMPARE(statusChangedSpy.count(), 6);
+
+ // Buffer full.
+ provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferedMedia);
+ QCOMPARE(audio.status(), QDeclarativeAudio::Buffered);
+ QCOMPARE(statusChangedSpy.count(), 7);
+
+ // Finished.
+ provider.playerControl()->updateMediaStatus(
+ QMediaPlayer::EndOfMedia, QMediaPlayer::StoppedState);
+ QCOMPARE(audio.status(), QDeclarativeAudio::EndOfMedia);
+ QCOMPARE(statusChangedSpy.count(), 8);
+}
+
+void tst_QDeclarativeAudio::metaData_data()
+{
+ QTest::addColumn<QByteArray>("propertyName");
+ QTest::addColumn<QtMultimediaKit::MetaData>("propertyKey");
+ QTest::addColumn<QVariant>("value");
+
+ QTest::newRow("title")
+ << QByteArray("title")
+ << QtMultimediaKit::Title
+ << QVariant(QString::fromLatin1("This is a title"));
+
+ QTest::newRow("genre")
+ << QByteArray("genre")
+ << QtMultimediaKit::Genre
+ << QVariant(QString::fromLatin1("rock"));
+
+ QTest::newRow("trackNumber")
+ << QByteArray("trackNumber")
+ << QtMultimediaKit::TrackNumber
+ << QVariant(8);
+}
+
+void tst_QDeclarativeAudio::metaData()
+{
+ QFETCH(QByteArray, propertyName);
+ QFETCH(QtMultimediaKit::MetaData, propertyKey);
+ QFETCH(QVariant, value);
+
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+ audio.componentComplete();
+
+ QSignalSpy spy(audio.metaData(), SIGNAL(metaDataChanged()));
+
+ const int index = audio.metaData()->metaObject()->indexOfProperty(propertyName.constData());
+ QVERIFY(index != -1);
+
+ QMetaProperty property = audio.metaData()->metaObject()->property(index);
+ QCOMPARE(property.read(&audio), QVariant());
+
+ property.write(audio.metaData(), value);
+ QCOMPARE(property.read(audio.metaData()), QVariant());
+ QCOMPARE(provider.metaDataControl()->metaData(propertyKey), QVariant());
+ QCOMPARE(spy.count(), 0);
+
+ provider.metaDataControl()->setMetaData(propertyKey, value);
+ QCOMPARE(property.read(audio.metaData()), value);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QDeclarativeAudio::error()
+{
+ const QString errorString = QLatin1String("Failed to open device.");
+
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+ audio.classBegin();
+ audio.componentComplete();
+
+ QSignalSpy errorSpy(&audio, SIGNAL(error(QDeclarativeAudio::Error,QString)));
+ QSignalSpy errorChangedSpy(&audio, SIGNAL(errorChanged()));
+
+ QCOMPARE(audio.error(), QDeclarativeAudio::NoError);
+ QCOMPARE(audio.errorString(), QString());
+
+ provider.playerControl()->emitError(QMediaPlayer::ResourceError, errorString);
+
+ QCOMPARE(audio.error(), QDeclarativeAudio::ResourceError);
+ QCOMPARE(audio.errorString(), errorString);
+ QCOMPARE(errorSpy.count(), 1);
+ QCOMPARE(errorChangedSpy.count(), 1);
+
+ // Changing the source resets the error properties.
+ audio.setSource(QUrl("http://example.com"));
+ QCOMPARE(audio.error(), QDeclarativeAudio::NoError);
+ QCOMPARE(audio.errorString(), QString());
+ QCOMPARE(errorSpy.count(), 1);
+ QCOMPARE(errorChangedSpy.count(), 2);
+
+ // But isn't noisy.
+ audio.setSource(QUrl("file:///file/path"));
+ QCOMPARE(audio.error(), QDeclarativeAudio::NoError);
+ QCOMPARE(audio.errorString(), QString());
+ QCOMPARE(errorSpy.count(), 1);
+ QCOMPARE(errorChangedSpy.count(), 2);
+}
+
+void tst_QDeclarativeAudio::loops()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeAudio audio;
+
+ QSignalSpy loopsChangedSpy(&audio, SIGNAL(loopCountChanged()));
+ QSignalSpy playingChangedSpy(&audio, SIGNAL(playingChanged()));
+ QSignalSpy stoppedSpy(&audio, SIGNAL(stopped()));
+
+ int playingChanged = 0;
+ int stopped = 0;
+ int loopsChanged = 0;
+
+ audio.classBegin();
+ audio.componentComplete();
+
+ QCOMPARE(audio.isPlaying(), false);
+
+ //setLoopCount(3) when stopped.
+ audio.setLoopCount(3);
+ QCOMPARE(audio.loopCount(), 3);
+ QCOMPARE(loopsChangedSpy.count(), ++loopsChanged);
+
+ //play till end
+ audio.play();
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+
+ // setPlaying(true) when playing.
+ audio.setPlaying(true);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ provider.playerControl()->updateMediaStatus(QMediaPlayer::EndOfMedia, QMediaPlayer::StoppedState);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+
+ //play to end
+ provider.playerControl()->updateMediaStatus(QMediaPlayer::EndOfMedia, QMediaPlayer::StoppedState);
+ //play to end
+ provider.playerControl()->updateMediaStatus(QMediaPlayer::EndOfMedia, QMediaPlayer::StoppedState);
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ // stop when playing
+ audio.play();
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ provider.playerControl()->updateMediaStatus(QMediaPlayer::EndOfMedia, QMediaPlayer::StoppedState);
+ audio.stop();
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ //setPlaying(true) with infinite loop
+ audio.setLoopCount(-1);
+ QCOMPARE(audio.loopCount(), -1);
+ QCOMPARE(loopsChangedSpy.count(), ++loopsChanged);
+ audio.setPlaying(true);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ provider.playerControl()->updateMediaStatus(QMediaPlayer::EndOfMedia, QMediaPlayer::StoppedState);
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+
+ // play() when playing.
+ audio.play();
+ QCOMPARE(audio.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(false) when playing in infinite loop.
+ audio.setPlaying(false);
+ QCOMPARE(audio.isPlaying(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+}
+
+QTEST_MAIN(tst_QDeclarativeAudio)
+
+#include "tst_qdeclarativeaudio.moc"
diff --git a/tests/auto/qdeclarativevideo/qdeclarativevideo.pro b/tests/auto/qdeclarativevideo/qdeclarativevideo.pro
new file mode 100644
index 000000000..15e58d8a5
--- /dev/null
+++ b/tests/auto/qdeclarativevideo/qdeclarativevideo.pro
@@ -0,0 +1,18 @@
+load(qttest_p4)
+
+QT += multimediakit-private declarative
+
+# TARGET = tst_qdeclarativevideo
+# CONFIG += testcase
+
+HEADERS += \
+ $$QT.multimediakit.sources/../imports/multimedia/qdeclarativevideo_p.h \
+ $$QT.multimediakit.sources/../imports/multimedia/qdeclarativemediabase_p.h \
+ $$QT.multimediakit.sources/../imports/multimedia/qdeclarativemediametadata_p.h
+
+SOURCES += \
+ tst_qdeclarativevideo.cpp \
+ $$QT.multimediakit.sources/../imports/multimedia/qdeclarativevideo.cpp \
+ $$QT.multimediakit.sources/../imports/multimedia/qdeclarativemediabase.cpp
+
+INCLUDEPATH += $$QT.multimediakit.sources/../imports/multimedia
diff --git a/tests/auto/qdeclarativevideo/tst_qdeclarativevideo.cpp b/tests/auto/qdeclarativevideo/tst_qdeclarativevideo.cpp
new file mode 100644
index 000000000..1f48a5c11
--- /dev/null
+++ b/tests/auto/qdeclarativevideo/tst_qdeclarativevideo.cpp
@@ -0,0 +1,992 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=plugins/declarative/multimedia
+
+#include <QtTest/QtTest>
+
+#include "qdeclarativevideo_p.h"
+
+
+#include <qabstractvideosurface.h>
+#include <qgraphicsvideoitem.h>
+#include <qmediaplayercontrol.h>
+#include <qmediaservice.h>
+#include <qmediaserviceprovider.h>
+#include <qvideorenderercontrol.h>
+#include <qvideowindowcontrol.h>
+#include <qvideosurfaceformat.h>
+
+#include <QtGui/qapplication.h>
+#include <QtGui/qpainter.h>
+
+class tst_QDeclarativeVideo : public QObject
+{
+ Q_OBJECT
+public slots:
+ void initTestCase();
+
+private slots:
+ void nullPlayerControl();
+ void nullService();
+
+ void playing();
+ void paused();
+ void error();
+
+ void hasAudio();
+ void hasVideo();
+ void fillMode();
+ void geometry();
+};
+
+Q_DECLARE_METATYPE(QtMultimediaKit::MetaData);
+Q_DECLARE_METATYPE(QDeclarativeVideo::Error);
+
+class QtTestMediaPlayerControl : public QMediaPlayerControl
+{
+ Q_OBJECT
+public:
+ QtTestMediaPlayerControl(QObject *parent = 0)
+ : QMediaPlayerControl(parent)
+ , m_state(QMediaPlayer::StoppedState)
+ , m_mediaStatus(QMediaPlayer::NoMedia)
+ , m_duration(0)
+ , m_position(0)
+ , m_playbackRate(1.0)
+ , m_volume(50)
+ , m_bufferStatus(0)
+ , m_muted(false)
+ , m_audioAvailable(false)
+ , m_videoAvailable(false)
+ , m_seekable(false)
+ {
+ }
+
+ QMediaPlayer::State state() const { return m_state; }
+ void updateState(QMediaPlayer::State state) { emit stateChanged(m_state = state); }
+
+ QMediaPlayer::MediaStatus mediaStatus() const { return m_mediaStatus; }
+ void updateMediaStatus(QMediaPlayer::MediaStatus status) {
+ emit mediaStatusChanged(m_mediaStatus = status); }
+ void updateMediaStatus(QMediaPlayer::MediaStatus status, QMediaPlayer::State state)
+ {
+ m_mediaStatus = status;
+ m_state = state;
+
+ emit mediaStatusChanged(m_mediaStatus);
+ emit stateChanged(m_state);
+ }
+
+ qint64 duration() const { return m_duration; }
+ void setDuration(qint64 duration) { emit durationChanged(m_duration = duration); }
+
+ qint64 position() const { return m_position; }
+ void setPosition(qint64 position) { emit positionChanged(m_position = position); }
+
+ int volume() const { return m_volume; }
+ void setVolume(int volume) { emit volumeChanged(m_volume = volume); }
+
+ bool isMuted() const { return m_muted; }
+ void setMuted(bool muted) { emit mutedChanged(m_muted = muted); }
+
+ int bufferStatus() const { return m_bufferStatus; }
+ void setBufferStatus(int status) { emit bufferStatusChanged(m_bufferStatus = status); }
+
+ bool isAudioAvailable() const { return m_audioAvailable; }
+ void setAudioAvailable(bool available) {
+ emit audioAvailableChanged(m_audioAvailable = available); }
+ bool isVideoAvailable() const { return m_videoAvailable; }
+ void setVideoAvailable(bool available) {
+ emit videoAvailableChanged(m_videoAvailable = available); }
+
+ bool isSeekable() const { return m_seekable; }
+ void setSeekable(bool seekable) { emit seekableChanged(m_seekable = seekable); }
+
+ QMediaTimeRange availablePlaybackRanges() const { return QMediaTimeRange(); }
+
+ qreal playbackRate() const { return m_playbackRate; }
+ void setPlaybackRate(qreal rate) { emit playbackRateChanged(m_playbackRate = rate); }
+
+ QMediaContent media() const { return m_media; }
+ const QIODevice *mediaStream() const { return 0; }
+ void setMedia(const QMediaContent &media, QIODevice *)
+ {
+ m_media = media;
+
+ m_mediaStatus = m_media.isNull()
+ ? QMediaPlayer::NoMedia
+ : QMediaPlayer::LoadingMedia;
+
+ emit mediaChanged(m_media);
+ emit mediaStatusChanged(m_mediaStatus);
+ }
+
+ void play() { emit stateChanged(m_state = QMediaPlayer::PlayingState); }
+ void pause() { emit stateChanged(m_state = QMediaPlayer::PausedState); }
+ void stop() { emit stateChanged(m_state = QMediaPlayer::StoppedState); }
+
+ void emitError(QMediaPlayer::Error err, const QString &errorString) {
+ emit error(err, errorString); }
+
+private:
+ QMediaPlayer::State m_state;
+ QMediaPlayer::MediaStatus m_mediaStatus;
+ qint64 m_duration;
+ qint64 m_position;
+ qreal m_playbackRate;
+ int m_volume;
+ int m_bufferStatus;
+ bool m_muted;
+ bool m_audioAvailable;
+ bool m_videoAvailable;
+ bool m_seekable;
+ QMediaContent m_media;
+};
+
+class QtTestRendererControl : public QVideoRendererControl
+{
+public:
+ QtTestRendererControl(QObject *parent ) : QVideoRendererControl(parent), m_surface(0) {}
+
+ QAbstractVideoSurface *surface() const { return m_surface; }
+ void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; }
+
+private:
+ QAbstractVideoSurface *m_surface;
+};
+
+class QtTestWindowControl : public QVideoWindowControl
+{
+public:
+ QtTestWindowControl(QObject *parent)
+ : QVideoWindowControl(parent)
+ , m_winId(0)
+ , m_repaintCount(0)
+ , m_brightness(0)
+ , m_contrast(0)
+ , m_saturation(0)
+ , m_aspectRatioMode(Qt::KeepAspectRatio)
+ , m_fullScreen(0)
+ {
+ }
+
+ WId winId() const { return m_winId; }
+ void setWinId(WId id) { m_winId = id; }
+
+ QRect displayRect() const { return m_displayRect; }
+ void setDisplayRect(const QRect &rect) { m_displayRect = rect; }
+
+ bool isFullScreen() const { return m_fullScreen; }
+ void setFullScreen(bool fullScreen) { emit fullScreenChanged(m_fullScreen = fullScreen); }
+
+ int repaintCount() const { return m_repaintCount; }
+ void setRepaintCount(int count) { m_repaintCount = count; }
+ void repaint() { ++m_repaintCount; }
+
+ QSize nativeSize() const { return m_nativeSize; }
+ void setNativeSize(const QSize &size) { m_nativeSize = size; emit nativeSizeChanged(); }
+
+ Qt::AspectRatioMode aspectRatioMode() const { return m_aspectRatioMode; }
+ void setAspectRatioMode(Qt::AspectRatioMode mode) { m_aspectRatioMode = mode; }
+
+ int brightness() const { return m_brightness; }
+ void setBrightness(int brightness) { emit brightnessChanged(m_brightness = brightness); }
+
+ int contrast() const { return m_contrast; }
+ void setContrast(int contrast) { emit contrastChanged(m_contrast = contrast); }
+
+ int hue() const { return m_hue; }
+ void setHue(int hue) { emit hueChanged(m_hue = hue); }
+
+ int saturation() const { return m_saturation; }
+ void setSaturation(int saturation) { emit saturationChanged(m_saturation = saturation); }
+
+private:
+ WId m_winId;
+ int m_repaintCount;
+ int m_brightness;
+ int m_contrast;
+ int m_hue;
+ int m_saturation;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QRect m_displayRect;
+ QSize m_nativeSize;
+ bool m_fullScreen;
+};
+
+class QtTestMediaService : public QMediaService
+{
+ Q_OBJECT
+public:
+ QtTestMediaService(
+ QtTestMediaPlayerControl *playerControl,
+ QtTestRendererControl *rendererControl,
+ QtTestWindowControl *windowControl,
+ QObject *parent)
+ : QMediaService(parent)
+ , playerControl(playerControl)
+ , rendererControl(rendererControl)
+ , windowControl(windowControl)
+ {
+ }
+
+ QMediaControl *requestControl(const char *name)
+ {
+ if (qstrcmp(name, QMediaPlayerControl_iid) == 0)
+ return playerControl;
+ else if (qstrcmp(name, QVideoRendererControl_iid) == 0)
+ return rendererControl;
+ else if (qstrcmp(name, QVideoWindowControl_iid) == 0)
+ return windowControl;
+ else
+ return 0;
+ }
+
+ void releaseControl(QMediaControl *) {}
+
+ QtTestMediaPlayerControl *playerControl;
+ QtTestRendererControl *rendererControl;
+ QtTestWindowControl *windowControl;
+};
+
+class QtTestMediaServiceProvider : public QMediaServiceProvider
+{
+ Q_OBJECT
+public:
+ QtTestMediaServiceProvider()
+ : service(
+ new QtTestMediaService(
+ new QtTestMediaPlayerControl(this),
+ new QtTestRendererControl(this),
+ new QtTestWindowControl(this),
+ this))
+ {
+ setDefaultServiceProvider(this);
+ }
+
+ QtTestMediaServiceProvider(QtTestMediaService *service)
+ : service(service)
+ {
+ setDefaultServiceProvider(this);
+ }
+
+ QtTestMediaServiceProvider(
+ QtTestMediaPlayerControl *playerControl,
+ QtTestRendererControl *rendererControl,
+ QtTestWindowControl *windowControl)
+ : service(new QtTestMediaService(playerControl, rendererControl, windowControl, this))
+ {
+ setDefaultServiceProvider(this);
+ }
+
+ ~QtTestMediaServiceProvider()
+ {
+ setDefaultServiceProvider(0);
+ }
+
+ QMediaService *requestService(
+ const QByteArray &type,
+ const QMediaServiceProviderHint & = QMediaServiceProviderHint())
+ {
+ requestedService = type;
+
+ return service;
+ }
+
+ void releaseService(QMediaService *) {}
+
+ inline QtTestMediaPlayerControl *playerControl() { return service->playerControl; }
+ inline QtTestRendererControl *rendererControl() { return service->rendererControl; }
+
+ QtTestMediaService *service;
+ QByteArray requestedService;
+};
+
+
+void tst_QDeclarativeVideo::initTestCase()
+{
+ qRegisterMetaType<QDeclarativeVideo::Error>();
+}
+
+void tst_QDeclarativeVideo::nullPlayerControl()
+{
+ QtTestMediaServiceProvider provider(0, 0, 0);
+
+ QDeclarativeVideo video;
+ video.classBegin();
+
+ QCOMPARE(video.source(), QUrl());
+ video.setSource(QUrl("http://example.com"));
+ QCOMPARE(video.source(), QUrl("http://example.com"));
+
+ QCOMPARE(video.isPlaying(), false);
+ video.setPlaying(true);
+ QCOMPARE(video.isPlaying(), true);
+ video.setPlaying(false);
+ video.play();
+ QCOMPARE(video.isPlaying(), false);
+
+ QCOMPARE(video.isPaused(), false);
+ video.pause();
+ QCOMPARE(video.isPaused(), false);
+ video.setPaused(true);
+ QCOMPARE(video.isPaused(), true);
+
+ QCOMPARE(video.duration(), 0);
+
+ QCOMPARE(video.position(), 0);
+ video.setPosition(10000);
+ QCOMPARE(video.position(), 10000);
+
+ QCOMPARE(video.volume(), qreal(1.0));
+ video.setVolume(0.5);
+ QCOMPARE(video.volume(), qreal(0.5));
+
+ QCOMPARE(video.isMuted(), false);
+ video.setMuted(true);
+ QCOMPARE(video.isMuted(), true);
+
+ QCOMPARE(video.bufferProgress(), qreal(0));
+
+ QCOMPARE(video.isSeekable(), false);
+
+ QCOMPARE(video.playbackRate(), qreal(1.0));
+
+ QCOMPARE(video.hasAudio(), false);
+ QCOMPARE(video.hasVideo(), false);
+
+ QCOMPARE(video.status(), QDeclarativeVideo::NoMedia);
+
+ QCOMPARE(video.error(), QDeclarativeVideo::ServiceMissing);
+}
+
+void tst_QDeclarativeVideo::nullService()
+{
+ QtTestMediaServiceProvider provider(0);
+
+ QDeclarativeVideo video;
+ video.classBegin();
+
+ QCOMPARE(video.source(), QUrl());
+ video.setSource(QUrl("http://example.com"));
+ QCOMPARE(video.source(), QUrl("http://example.com"));
+
+ QCOMPARE(video.isPlaying(), false);
+ video.setPlaying(true);
+ QCOMPARE(video.isPlaying(), true);
+ video.setPlaying(false);
+ video.play();
+ QCOMPARE(video.isPlaying(), false);
+
+ QCOMPARE(video.isPaused(), false);
+ video.pause();
+ QCOMPARE(video.isPaused(), false);
+ video.setPaused(true);
+ QCOMPARE(video.isPaused(), true);
+
+ QCOMPARE(video.duration(), 0);
+
+ QCOMPARE(video.position(), 0);
+ video.setPosition(10000);
+ QCOMPARE(video.position(), 10000);
+
+ QCOMPARE(video.volume(), qreal(1.0));
+ video.setVolume(0.5);
+ QCOMPARE(video.volume(), qreal(0.5));
+
+ QCOMPARE(video.isMuted(), false);
+ video.setMuted(true);
+ QCOMPARE(video.isMuted(), true);
+
+ QCOMPARE(video.bufferProgress(), qreal(0));
+
+ QCOMPARE(video.isSeekable(), false);
+
+ QCOMPARE(video.playbackRate(), qreal(1.0));
+
+ QCOMPARE(video.hasAudio(), false);
+ QCOMPARE(video.hasVideo(), false);
+
+ QCOMPARE(video.status(), QDeclarativeVideo::NoMedia);
+
+ QCOMPARE(video.error(), QDeclarativeVideo::ServiceMissing);
+
+ QCOMPARE(video.metaObject()->indexOfProperty("title"), -1);
+ QCOMPARE(video.metaObject()->indexOfProperty("genre"), -1);
+ QCOMPARE(video.metaObject()->indexOfProperty("description"), -1);
+}
+
+void tst_QDeclarativeVideo::playing()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeVideo video;
+ video.classBegin();
+ video.componentComplete();
+ video.setSource(QUrl("http://example.com"));
+
+ QSignalSpy playingChangedSpy(&video, SIGNAL(playingChanged()));
+ QSignalSpy startedSpy(&video, SIGNAL(started()));
+ QSignalSpy stoppedSpy(&video, SIGNAL(stopped()));
+
+ int playingChanged = 0;
+ int started = 0;
+ int stopped = 0;
+
+ QCOMPARE(video.isPlaying(), false);
+
+ // setPlaying(true) when stopped.
+ video.setPlaying(true);
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(false) when playing.
+ video.setPlaying(false);
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ // play() when stopped.
+ video.play();
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // stop() when playing.
+ video.stop();
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ // stop() when stopped.
+ video.stop();
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(false) when stopped.
+ video.setPlaying(false);
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ video.setPlaying(true);
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(true) when playing.
+ video.setPlaying(true);
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // play() when playing.
+ video.play();
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(stoppedSpy.count(), stopped);
+}
+
+void tst_QDeclarativeVideo::paused()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeVideo video;
+ video.classBegin();
+ video.componentComplete();
+ video.setSource(QUrl("http://example.com"));
+
+ QSignalSpy playingChangedSpy(&video, SIGNAL(playingChanged()));
+ QSignalSpy pausedChangedSpy(&video, SIGNAL(pausedChanged()));
+ QSignalSpy startedSpy(&video, SIGNAL(started()));
+ QSignalSpy pausedSpy(&video, SIGNAL(paused()));
+ QSignalSpy resumedSpy(&video, SIGNAL(resumed()));
+ QSignalSpy stoppedSpy(&video, SIGNAL(stopped()));
+
+ int playingChanged = 0;
+ int pausedChanged = 0;
+ int started = 0;
+ int paused = 0;
+ int resumed = 0;
+ int stopped = 0;
+
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(video.isPaused(), false);
+
+ // setPlaying(true) when stopped.
+ video.setPlaying(true);
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(video.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(true) when playing.
+ video.setPaused(true);
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), ++paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(true) when paused.
+ video.setPaused(true);
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // pause() when paused.
+ video.pause();
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(false) when paused.
+ video.setPaused(false);
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(video.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), ++resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(false) when playing.
+ video.setPaused(false);
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(video.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // pause() when playing.
+ video.pause();
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), ++paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(false) when paused.
+ video.setPlaying(false);
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ // setPaused(true) when stopped and paused.
+ video.setPaused(true);
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(false) when stopped and paused.
+ video.setPaused(false);
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(video.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(true) when stopped.
+ video.setPaused(true);
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(true) when stopped and paused.
+ video.setPlaying(true);
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(pausedSpy.count(), ++paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // play() when paused.
+ video.play();
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(video.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), ++resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPaused(true) when playing.
+ video.setPaused(true);
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), ++paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // stop() when paused.
+ video.stop();
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(video.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ // setPaused(true) when stopped.
+ video.setPaused(true);
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // stop() when stopped and paused.
+ video.stop();
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(video.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // pause() when stopped.
+ video.pause();
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(pausedSpy.count(), ++paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(false) when paused.
+ video.setPlaying(false);
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ // pause() when stopped and paused.
+ video.pause();
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(pausedSpy.count(), ++paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+
+ // setPlaying(false) when paused.
+ video.setPlaying(false);
+ QCOMPARE(video.isPlaying(), false);
+ QCOMPARE(video.isPaused(), true);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), pausedChanged);
+ QCOMPARE(startedSpy.count(), started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), ++stopped);
+
+ // play() when stopped and paused.
+ video.play();
+ QCOMPARE(video.isPlaying(), true);
+ QCOMPARE(video.isPaused(), false);
+ QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(playingChangedSpy.count(), ++playingChanged);
+ QCOMPARE(pausedChangedSpy.count(), ++pausedChanged);
+ QCOMPARE(startedSpy.count(), ++started);
+ QCOMPARE(pausedSpy.count(), paused);
+ QCOMPARE(resumedSpy.count(), resumed);
+ QCOMPARE(stoppedSpy.count(), stopped);
+}
+
+void tst_QDeclarativeVideo::error()
+{
+ const QString errorString = QLatin1String("Failed to open device.");
+
+ QtTestMediaServiceProvider provider;
+ QDeclarativeVideo video;
+ video.classBegin();
+ video.componentComplete();
+
+ QSignalSpy errorSpy(&video, SIGNAL(error(QDeclarativeVideo::Error,QString)));
+ QSignalSpy errorChangedSpy(&video, SIGNAL(errorChanged()));
+
+ QCOMPARE(video.error(), QDeclarativeVideo::NoError);
+ QCOMPARE(video.errorString(), QString());
+
+ provider.playerControl()->emitError(QMediaPlayer::ResourceError, errorString);
+
+ QCOMPARE(video.error(), QDeclarativeVideo::ResourceError);
+ QCOMPARE(video.errorString(), errorString);
+ QCOMPARE(errorSpy.count(), 1);
+ QCOMPARE(errorChangedSpy.count(), 1);
+
+ // Changing the source resets the error properties.
+ video.setSource(QUrl("http://example.com"));
+ QCOMPARE(video.error(), QDeclarativeVideo::NoError);
+ QCOMPARE(video.errorString(), QString());
+ QCOMPARE(errorSpy.count(), 1);
+ QCOMPARE(errorChangedSpy.count(), 2);
+
+ // But isn't noisy.
+ video.setSource(QUrl("file:///file/path"));
+ QCOMPARE(video.error(), QDeclarativeVideo::NoError);
+ QCOMPARE(video.errorString(), QString());
+ QCOMPARE(errorSpy.count(), 1);
+ QCOMPARE(errorChangedSpy.count(), 2);
+}
+
+
+void tst_QDeclarativeVideo::hasAudio()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeVideo video;
+ video.classBegin();
+ video.componentComplete();
+
+ QSignalSpy spy(&video, SIGNAL(hasAudioChanged()));
+
+ QCOMPARE(video.hasAudio(), false);
+
+ provider.playerControl()->setAudioAvailable(true);
+ QCOMPARE(video.hasAudio(), true);
+ QCOMPARE(spy.count(), 1);
+
+ provider.playerControl()->setAudioAvailable(true);
+ QCOMPARE(video.hasAudio(), true);
+ QCOMPARE(spy.count(), 2);
+
+ provider.playerControl()->setAudioAvailable(false);
+ QCOMPARE(video.hasAudio(), false);
+ QCOMPARE(spy.count(), 3);
+}
+
+void tst_QDeclarativeVideo::hasVideo()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeVideo video;
+ video.classBegin();
+ video.componentComplete();
+
+ QSignalSpy spy(&video, SIGNAL(hasVideoChanged()));
+
+ QCOMPARE(video.hasVideo(), false);
+
+ provider.playerControl()->setVideoAvailable(true);
+ QCOMPARE(video.hasVideo(), true);
+ QCOMPARE(spy.count(), 1);
+
+ provider.playerControl()->setVideoAvailable(true);
+ QCOMPARE(video.hasVideo(), true);
+ QCOMPARE(spy.count(), 2);
+
+ provider.playerControl()->setVideoAvailable(false);
+ QCOMPARE(video.hasVideo(), false);
+ QCOMPARE(spy.count(), 3);
+}
+
+void tst_QDeclarativeVideo::fillMode()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeVideo video;
+ video.classBegin();
+ video.componentComplete();
+
+ QList<QGraphicsItem *> children = video.childItems();
+ QCOMPARE(children.count(), 1);
+ QGraphicsVideoItem *videoItem = qgraphicsitem_cast<QGraphicsVideoItem *>(children.first());
+ QVERIFY(videoItem != 0);
+
+ QCOMPARE(video.fillMode(), QDeclarativeVideo::PreserveAspectFit);
+
+ video.setFillMode(QDeclarativeVideo::PreserveAspectCrop);
+ QCOMPARE(video.fillMode(), QDeclarativeVideo::PreserveAspectCrop);
+ QCOMPARE(videoItem->aspectRatioMode(), Qt::KeepAspectRatioByExpanding);
+
+ video.setFillMode(QDeclarativeVideo::Stretch);
+ QCOMPARE(video.fillMode(), QDeclarativeVideo::Stretch);
+ QCOMPARE(videoItem->aspectRatioMode(), Qt::IgnoreAspectRatio);
+
+ video.setFillMode(QDeclarativeVideo::PreserveAspectFit);
+ QCOMPARE(video.fillMode(), QDeclarativeVideo::PreserveAspectFit);
+ QCOMPARE(videoItem->aspectRatioMode(), Qt::KeepAspectRatio);
+}
+
+void tst_QDeclarativeVideo::geometry()
+{
+ QtTestMediaServiceProvider provider;
+ QDeclarativeVideo video;
+ video.classBegin();
+ video.componentComplete();
+
+ QList<QGraphicsItem *> children = video.childItems();
+ QCOMPARE(children.count(), 1);
+ QGraphicsVideoItem *videoItem = qgraphicsitem_cast<QGraphicsVideoItem *>(children.first());
+ QVERIFY(videoItem != 0);
+
+ { // Surface setup is deferred until after the first paint.
+ QImage image(320, 240, QImage::Format_RGB32);
+ QPainter painter(&image);
+
+ videoItem->paint(&painter, 0);
+ }
+
+ QAbstractVideoSurface *surface = provider.rendererControl()->surface();
+
+ //video item can use overlay, QAbstractVideoSurface is not used than.
+ if (surface) {
+ QVideoSurfaceFormat format(QSize(640, 480), QVideoFrame::Format_RGB32);
+
+ QVERIFY(surface->start(format));
+ QCoreApplication::processEvents();
+
+ QCOMPARE(video.implicitWidth(), qreal(640));
+ QCOMPARE(video.implicitHeight(), qreal(480));
+ }
+
+ video.setWidth(560);
+ video.setHeight(328);
+
+ QCOMPARE(videoItem->size().width(), qreal(560));
+ QCOMPARE(videoItem->size().height(), qreal(328));
+}
+
+QTEST_MAIN(tst_QDeclarativeVideo)
+
+#include "tst_qdeclarativevideo.moc"
diff --git a/tests/auto/qgraphicsvideoitem/qgraphicsvideoitem.pro b/tests/auto/qgraphicsvideoitem/qgraphicsvideoitem.pro
new file mode 100644
index 000000000..1d8735d42
--- /dev/null
+++ b/tests/auto/qgraphicsvideoitem/qgraphicsvideoitem.pro
@@ -0,0 +1,12 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qgraphicsvideoitem
+# CONFIG += testcase
+
+SOURCES += tst_qgraphicsvideoitem.cpp
+
+symbian: TARGET.CAPABILITY = ReadDeviceData WriteDeviceData
+
+maemo*:CONFIG += insignificant_test
diff --git a/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp b/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp
new file mode 100644
index 000000000..2e7b97df8
--- /dev/null
+++ b/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp
@@ -0,0 +1,675 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <qmobilityglobal.h>
+#include "qgraphicsvideoitem.h"
+#include <QtTest/QtTest>
+#include "qmediaobject.h"
+#include "qmediaservice.h"
+#include <private/qpaintervideosurface_p.h>
+#include "qvideorenderercontrol.h"
+
+#include <qabstractvideosurface.h>
+#include <qvideosurfaceformat.h>
+
+#include <QtGui/qapplication.h>
+#include <QtGui/qgraphicsscene.h>
+#include <QtGui/qgraphicsview.h>
+
+QT_USE_NAMESPACE
+class tst_QGraphicsVideoItem : public QObject
+{
+ Q_OBJECT
+public slots:
+ void initTestCase();
+
+private slots:
+ void nullObject();
+ void nullService();
+ void noOutputs();
+ void serviceDestroyed();
+ void mediaObjectDestroyed();
+ void setMediaObject();
+
+ void show();
+
+ void aspectRatioMode();
+ void offset();
+ void size();
+ void nativeSize_data();
+ void nativeSize();
+
+ void boundingRect_data();
+ void boundingRect();
+
+ void paint();
+};
+
+Q_DECLARE_METATYPE(const uchar *)
+Q_DECLARE_METATYPE(Qt::AspectRatioMode)
+
+class QtTestRendererControl : public QVideoRendererControl
+{
+public:
+ QtTestRendererControl()
+ : m_surface(0)
+ {
+ }
+
+ QAbstractVideoSurface *surface() const { return m_surface; }
+ void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; }
+
+private:
+ QAbstractVideoSurface *m_surface;
+};
+
+class QtTestVideoService : public QMediaService
+{
+ Q_OBJECT
+public:
+ QtTestVideoService(
+ QtTestRendererControl *renderer)
+ : QMediaService(0)
+ , rendererRef(0)
+ , rendererControl(renderer)
+ {
+ }
+
+ ~QtTestVideoService()
+ {
+ delete rendererControl;
+ }
+
+ QMediaControl *requestControl(const char *name)
+ {
+ if (qstrcmp(name, QVideoRendererControl_iid) == 0 && rendererControl) {
+ rendererRef += 1;
+
+ return rendererControl;
+ } else {
+ return 0;
+ }
+ }
+
+ void releaseControl(QMediaControl *control)
+ {
+ Q_ASSERT(control);
+
+ if (control == rendererControl) {
+ rendererRef -= 1;
+
+ if (rendererRef == 0)
+ rendererControl->setSurface(0);
+ }
+ }
+
+ int rendererRef;
+ QtTestRendererControl *rendererControl;
+};
+
+class QtTestVideoObject : public QMediaObject
+{
+ Q_OBJECT
+public:
+ QtTestVideoObject(QtTestRendererControl *renderer)
+ : QMediaObject(0, new QtTestVideoService(renderer))
+ {
+ testService = qobject_cast<QtTestVideoService*>(service());
+ }
+
+ QtTestVideoObject(QtTestVideoService *service):
+ QMediaObject(0, service),
+ testService(service)
+ {
+ }
+
+ ~QtTestVideoObject()
+ {
+ delete testService;
+ }
+
+ QtTestVideoService *testService;
+};
+
+class QtTestGraphicsVideoItem : public QGraphicsVideoItem
+{
+public:
+ QtTestGraphicsVideoItem(QGraphicsItem *parent = 0)
+ : QGraphicsVideoItem(parent)
+ , m_paintCount(0)
+ {
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ ++m_paintCount;
+
+ QTestEventLoop::instance().exitLoop();
+
+ QGraphicsVideoItem::paint(painter, option, widget);
+ }
+
+ bool waitForPaint(int secs)
+ {
+ const int paintCount = m_paintCount;
+
+ QTestEventLoop::instance().enterLoop(secs);
+
+ return m_paintCount != paintCount;
+ }
+
+ int paintCount() const
+ {
+ return m_paintCount;
+ }
+
+private:
+ int m_paintCount;
+};
+
+void tst_QGraphicsVideoItem::initTestCase()
+{
+ qRegisterMetaType<Qt::AspectRatioMode>();
+}
+
+void tst_QGraphicsVideoItem::nullObject()
+{
+ QGraphicsVideoItem item(0);
+
+ QVERIFY(item.boundingRect().isEmpty());
+}
+
+void tst_QGraphicsVideoItem::nullService()
+{
+ QtTestVideoService *service = 0;
+
+ QtTestVideoObject object(service);
+
+ QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem;
+ object.bind(item);
+
+ QVERIFY(item->boundingRect().isEmpty());
+
+ item->hide();
+ item->show();
+
+ QGraphicsScene graphicsScene;
+ graphicsScene.addItem(item);
+ QGraphicsView graphicsView(&graphicsScene);
+ graphicsView.show();
+}
+
+void tst_QGraphicsVideoItem::noOutputs()
+{
+ QtTestRendererControl *control = 0;
+ QtTestVideoObject object(control);
+
+ QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem;
+ object.bind(item);
+
+ QVERIFY(item->boundingRect().isEmpty());
+
+ item->hide();
+ item->show();
+
+ QGraphicsScene graphicsScene;
+ graphicsScene.addItem(item);
+ QGraphicsView graphicsView(&graphicsScene);
+ graphicsView.show();
+}
+
+void tst_QGraphicsVideoItem::serviceDestroyed()
+{
+ QtTestVideoObject object(new QtTestRendererControl);
+
+ QGraphicsVideoItem item;
+ object.bind(&item);
+
+ QCOMPARE(object.testService->rendererRef, 1);
+
+ QtTestVideoService *service = object.testService;
+ object.testService = 0;
+
+ delete service;
+
+ QCOMPARE(item.mediaObject(), static_cast<QMediaObject *>(&object));
+ QVERIFY(item.boundingRect().isEmpty());
+}
+
+void tst_QGraphicsVideoItem::mediaObjectDestroyed()
+{
+ QtTestVideoObject *object = new QtTestVideoObject(new QtTestRendererControl);
+
+ QGraphicsVideoItem item;
+ object->bind(&item);
+
+ QCOMPARE(object->testService->rendererRef, 1);
+
+ delete object;
+ object = 0;
+
+ QCOMPARE(item.mediaObject(), static_cast<QMediaObject *>(object));
+ QVERIFY(item.boundingRect().isEmpty());
+}
+
+void tst_QGraphicsVideoItem::setMediaObject()
+{
+ QMediaObject *nullObject = 0;
+ QtTestVideoObject object(new QtTestRendererControl);
+
+ QGraphicsVideoItem item;
+
+ QCOMPARE(item.mediaObject(), nullObject);
+ QCOMPARE(object.testService->rendererRef, 0);
+
+ object.bind(&item);
+ QCOMPARE(item.mediaObject(), static_cast<QMediaObject *>(&object));
+ QCOMPARE(object.testService->rendererRef, 1);
+ QVERIFY(object.testService->rendererControl->surface() == 0);
+
+ { // Surface setup is deferred until after the first paint.
+ QImage image(320, 240, QImage::Format_RGB32);
+ QPainter painter(&image);
+
+ item.paint(&painter, 0);
+ }
+ QVERIFY(object.testService->rendererControl->surface() != 0);
+
+ object.unbind(&item);
+ QCOMPARE(item.mediaObject(), nullObject);
+
+ QCOMPARE(object.testService->rendererRef, 0);
+ QVERIFY(object.testService->rendererControl->surface() == 0);
+
+ item.setVisible(false);
+
+ object.bind(&item);
+ QCOMPARE(item.mediaObject(), static_cast<QMediaObject *>(&object));
+ QCOMPARE(object.testService->rendererRef, 1);
+ QVERIFY(object.testService->rendererControl->surface() != 0);
+}
+
+void tst_QGraphicsVideoItem::show()
+{
+ QtTestVideoObject object(new QtTestRendererControl);
+ QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem;
+ object.bind(item);
+
+ // Graphics items are visible by default
+ QCOMPARE(object.testService->rendererRef, 1);
+ QVERIFY(object.testService->rendererControl->surface() == 0);
+
+ item->hide();
+ QCOMPARE(object.testService->rendererRef, 1);
+
+ item->show();
+ QCOMPARE(object.testService->rendererRef, 1);
+ QVERIFY(object.testService->rendererControl->surface() == 0);
+
+ QGraphicsScene graphicsScene;
+ graphicsScene.addItem(item);
+ QGraphicsView graphicsView(&graphicsScene);
+ graphicsView.show();
+
+ QVERIFY(item->paintCount() || item->waitForPaint(1));
+ QVERIFY(object.testService->rendererControl->surface() != 0);
+
+ QVERIFY(item->boundingRect().isEmpty());
+
+ QVideoSurfaceFormat format(QSize(320,240),QVideoFrame::Format_RGB32);
+ QVERIFY(object.testService->rendererControl->surface()->start(format));
+
+ QCoreApplication::processEvents();
+ QVERIFY(!item->boundingRect().isEmpty());
+}
+
+void tst_QGraphicsVideoItem::aspectRatioMode()
+{
+ QGraphicsVideoItem item;
+
+ QCOMPARE(item.aspectRatioMode(), Qt::KeepAspectRatio);
+
+ item.setAspectRatioMode(Qt::IgnoreAspectRatio);
+ QCOMPARE(item.aspectRatioMode(), Qt::IgnoreAspectRatio);
+
+ item.setAspectRatioMode(Qt::KeepAspectRatioByExpanding);
+ QCOMPARE(item.aspectRatioMode(), Qt::KeepAspectRatioByExpanding);
+
+ item.setAspectRatioMode(Qt::KeepAspectRatio);
+ QCOMPARE(item.aspectRatioMode(), Qt::KeepAspectRatio);
+}
+
+void tst_QGraphicsVideoItem::offset()
+{
+ QGraphicsVideoItem item;
+
+ QCOMPARE(item.offset(), QPointF(0, 0));
+
+ item.setOffset(QPointF(-32.4, 43.0));
+ QCOMPARE(item.offset(), QPointF(-32.4, 43.0));
+
+ item.setOffset(QPointF(1, 1));
+ QCOMPARE(item.offset(), QPointF(1, 1));
+
+ item.setOffset(QPointF(12, -30.4));
+ QCOMPARE(item.offset(), QPointF(12, -30.4));
+
+ item.setOffset(QPointF(-90.4, -75));
+ QCOMPARE(item.offset(), QPointF(-90.4, -75));
+}
+
+void tst_QGraphicsVideoItem::size()
+{
+ QGraphicsVideoItem item;
+
+ QCOMPARE(item.size(), QSizeF(320, 240));
+
+ item.setSize(QSizeF(542.5, 436.3));
+ QCOMPARE(item.size(), QSizeF(542.5, 436.3));
+
+ item.setSize(QSizeF(-43, 12));
+ QCOMPARE(item.size(), QSizeF(0, 0));
+
+ item.setSize(QSizeF(54, -9));
+ QCOMPARE(item.size(), QSizeF(0, 0));
+
+ item.setSize(QSizeF(-90, -65));
+ QCOMPARE(item.size(), QSizeF(0, 0));
+
+ item.setSize(QSizeF(1000, 1000));
+ QCOMPARE(item.size(), QSizeF(1000, 1000));
+}
+
+void tst_QGraphicsVideoItem::nativeSize_data()
+{
+ QTest::addColumn<QSize>("frameSize");
+ QTest::addColumn<QRect>("viewport");
+ QTest::addColumn<QSize>("pixelAspectRatio");
+ QTest::addColumn<QSizeF>("nativeSize");
+
+ QTest::newRow("640x480")
+ << QSize(640, 480)
+ << QRect(0, 0, 640, 480)
+ << QSize(1, 1)
+ << QSizeF(640, 480);
+
+ QTest::newRow("800x600, (80,60, 640x480) viewport")
+ << QSize(800, 600)
+ << QRect(80, 60, 640, 480)
+ << QSize(1, 1)
+ << QSizeF(640, 480);
+
+ QTest::newRow("800x600, (80,60, 640x480) viewport, 4:3")
+ << QSize(800, 600)
+ << QRect(80, 60, 640, 480)
+ << QSize(4, 3)
+ << QSizeF(853, 480);
+}
+
+void tst_QGraphicsVideoItem::nativeSize()
+{
+ QFETCH(QSize, frameSize);
+ QFETCH(QRect, viewport);
+ QFETCH(QSize, pixelAspectRatio);
+ QFETCH(QSizeF, nativeSize);
+
+ QtTestVideoObject object(new QtTestRendererControl);
+ QGraphicsVideoItem item;
+ object.bind(&item);
+
+ QCOMPARE(item.nativeSize(), QSizeF());
+
+ QSignalSpy spy(&item, SIGNAL(nativeSizeChanged(QSizeF)));
+
+ QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_ARGB32);
+ format.setViewport(viewport);
+ format.setPixelAspectRatio(pixelAspectRatio);
+
+ { // Surface setup is deferred until after the first paint.
+ QImage image(320, 240, QImage::Format_RGB32);
+ QPainter painter(&image);
+
+ item.paint(&painter, 0);
+ }
+ QVERIFY(object.testService->rendererControl->surface() != 0);
+ QVERIFY(object.testService->rendererControl->surface()->start(format));
+
+ QCoreApplication::processEvents();
+ QCOMPARE(item.nativeSize(), nativeSize);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.last().first().toSizeF(), nativeSize);
+
+ object.testService->rendererControl->surface()->stop();
+
+ QCoreApplication::processEvents();
+ QVERIFY(item.nativeSize().isEmpty());
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(spy.last().first().toSizeF().isEmpty());
+}
+
+void tst_QGraphicsVideoItem::boundingRect_data()
+{
+ QTest::addColumn<QSize>("frameSize");
+ QTest::addColumn<QPointF>("offset");
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<Qt::AspectRatioMode>("aspectRatioMode");
+ QTest::addColumn<QRectF>("expectedRect");
+
+
+ QTest::newRow("640x480: (0,0 640x480), Keep")
+ << QSize(640, 480)
+ << QPointF(0, 0)
+ << QSizeF(640, 480)
+ << Qt::KeepAspectRatio
+ << QRectF(0, 0, 640, 480);
+
+ QTest::newRow("800x600, (0,0, 640x480), Keep")
+ << QSize(800, 600)
+ << QPointF(0, 0)
+ << QSizeF(640, 480)
+ << Qt::KeepAspectRatio
+ << QRectF(0, 0, 640, 480);
+
+ QTest::newRow("800x600, (0,0, 640x480), KeepByExpanding")
+ << QSize(800, 600)
+ << QPointF(0, 0)
+ << QSizeF(640, 480)
+ << Qt::KeepAspectRatioByExpanding
+ << QRectF(0, 0, 640, 480);
+
+ QTest::newRow("800x600, (0,0, 640x480), Ignore")
+ << QSize(800, 600)
+ << QPointF(0, 0)
+ << QSizeF(640, 480)
+ << Qt::IgnoreAspectRatio
+ << QRectF(0, 0, 640, 480);
+
+ QTest::newRow("800x600, (100,100, 640x480), Keep")
+ << QSize(800, 600)
+ << QPointF(100, 100)
+ << QSizeF(640, 480)
+ << Qt::KeepAspectRatio
+ << QRectF(100, 100, 640, 480);
+
+ QTest::newRow("800x600, (100,-100, 640x480), KeepByExpanding")
+ << QSize(800, 600)
+ << QPointF(100, -100)
+ << QSizeF(640, 480)
+ << Qt::KeepAspectRatioByExpanding
+ << QRectF(100, -100, 640, 480);
+
+ QTest::newRow("800x600, (-100,-100, 640x480), Ignore")
+ << QSize(800, 600)
+ << QPointF(-100, -100)
+ << QSizeF(640, 480)
+ << Qt::IgnoreAspectRatio
+ << QRectF(-100, -100, 640, 480);
+
+ QTest::newRow("800x600, (0,0, 1920x1024), Keep")
+ << QSize(800, 600)
+ << QPointF(0, 0)
+ << QSizeF(1920, 1024)
+ << Qt::KeepAspectRatio
+ << QRectF(832.0 / 3, 0, 4096.0 / 3, 1024);
+
+ QTest::newRow("800x600, (0,0, 1920x1024), KeepByExpanding")
+ << QSize(800, 600)
+ << QPointF(0, 0)
+ << QSizeF(1920, 1024)
+ << Qt::KeepAspectRatioByExpanding
+ << QRectF(0, 0, 1920, 1024);
+
+ QTest::newRow("800x600, (0,0, 1920x1024), Ignore")
+ << QSize(800, 600)
+ << QPointF(0, 0)
+ << QSizeF(1920, 1024)
+ << Qt::IgnoreAspectRatio
+ << QRectF(0, 0, 1920, 1024);
+
+ QTest::newRow("800x600, (100,100, 1920x1024), Keep")
+ << QSize(800, 600)
+ << QPointF(100, 100)
+ << QSizeF(1920, 1024)
+ << Qt::KeepAspectRatio
+ << QRectF(100 + 832.0 / 3, 100, 4096.0 / 3, 1024);
+
+ QTest::newRow("800x600, (100,-100, 1920x1024), KeepByExpanding")
+ << QSize(800, 600)
+ << QPointF(100, -100)
+ << QSizeF(1920, 1024)
+ << Qt::KeepAspectRatioByExpanding
+ << QRectF(100, -100, 1920, 1024);
+
+ QTest::newRow("800x600, (-100,-100, 1920x1024), Ignore")
+ << QSize(800, 600)
+ << QPointF(-100, -100)
+ << QSizeF(1920, 1024)
+ << Qt::IgnoreAspectRatio
+ << QRectF(-100, -100, 1920, 1024);
+}
+
+void tst_QGraphicsVideoItem::boundingRect()
+{
+ QFETCH(QSize, frameSize);
+ QFETCH(QPointF, offset);
+ QFETCH(QSizeF, size);
+ QFETCH(Qt::AspectRatioMode, aspectRatioMode);
+ QFETCH(QRectF, expectedRect);
+
+ QtTestVideoObject object(new QtTestRendererControl);
+ QGraphicsVideoItem item;
+ object.bind(&item);
+
+ item.setOffset(offset);
+ item.setSize(size);
+ item.setAspectRatioMode(aspectRatioMode);
+
+ QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_ARGB32);
+
+ { // Surface setup is deferred until after the first paint.
+ QImage image(320, 240, QImage::Format_RGB32);
+ QPainter painter(&image);
+
+ item.paint(&painter, 0);
+ }
+ QVERIFY(object.testService->rendererControl->surface() != 0);
+ QVERIFY(object.testService->rendererControl->surface()->start(format));
+
+ QCoreApplication::processEvents();
+ QCOMPARE(item.boundingRect(), expectedRect);
+}
+
+static const uchar rgb32ImageData[] =
+{
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00
+};
+
+void tst_QGraphicsVideoItem::paint()
+{
+ QtTestVideoObject object(new QtTestRendererControl);
+ QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem;
+ object.bind(item);
+
+ QGraphicsScene graphicsScene;
+ graphicsScene.addItem(item);
+ QGraphicsView graphicsView(&graphicsScene);
+ graphicsView.show();
+ QVERIFY(item->waitForPaint(1));
+
+ QPainterVideoSurface *surface = qobject_cast<QPainterVideoSurface *>(
+ object.testService->rendererControl->surface());
+ if (!surface)
+ QSKIP("QGraphicsVideoItem is not QPainterVideoSurface based", SkipAll);
+
+ QVideoSurfaceFormat format(QSize(2, 2), QVideoFrame::Format_RGB32);
+
+ QVERIFY(surface->start(format));
+ QCOMPARE(surface->isActive(), true);
+ QCOMPARE(surface->isReady(), true);
+
+ QVERIFY(item->waitForPaint(1));
+
+ QCOMPARE(surface->isActive(), true);
+ QCOMPARE(surface->isReady(), true);
+
+ QVideoFrame frame(sizeof(rgb32ImageData), QSize(2, 2), 8, QVideoFrame::Format_RGB32);
+
+ frame.map(QAbstractVideoBuffer::WriteOnly);
+ memcpy(frame.bits(), rgb32ImageData, frame.mappedBytes());
+ frame.unmap();
+
+ QVERIFY(surface->present(frame));
+ QCOMPARE(surface->isActive(), true);
+ QCOMPARE(surface->isReady(), false);
+
+ QVERIFY(item->waitForPaint(1));
+
+ QCOMPARE(surface->isActive(), true);
+ QCOMPARE(surface->isReady(), true);
+}
+
+
+QTEST_MAIN(tst_QGraphicsVideoItem)
+
+#include "tst_qgraphicsvideoitem.moc"
diff --git a/tests/auto/qmediacontent/qmediacontent.pro b/tests/auto/qmediacontent/qmediacontent.pro
new file mode 100644
index 000000000..47d9cea67
--- /dev/null
+++ b/tests/auto/qmediacontent/qmediacontent.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+QT += multimediakit-private network
+# TARGET = tst_qmediacontent
+# CONFIG += testcase
+
+SOURCES += tst_qmediacontent.cpp
diff --git a/tests/auto/qmediacontent/tst_qmediacontent.cpp b/tests/auto/qmediacontent/tst_qmediacontent.cpp
new file mode 100644
index 000000000..b350cf175
--- /dev/null
+++ b/tests/auto/qmediacontent/tst_qmediacontent.cpp
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 <QtTest/QtTest>
+#include <QtNetwork/qnetworkrequest.h>
+
+#include <qmediacontent.h>
+
+//TESTED_COMPONENT=src/multimedia
+
+QT_USE_NAMESPACE
+class tst_QMediaContent : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testNull();
+ void testUrlCtor();
+ void testRequestCtor();
+ void testResourceCtor();
+ void testResourceListCtor();
+ void testCopy();
+ void testAssignment();
+ void testEquality();
+ void testResources();
+};
+
+void tst_QMediaContent::testNull()
+{
+ QMediaContent media;
+
+ QCOMPARE(media.isNull(), true);
+ QCOMPARE(media.canonicalUrl(), QUrl());
+ QCOMPARE(media.canonicalResource(), QMediaResource());
+ QCOMPARE(media.resources(), QMediaResourceList());
+}
+
+void tst_QMediaContent::testUrlCtor()
+{
+ QMediaContent media(QUrl("http://example.com/movie.mov"));
+
+ QCOMPARE(media.canonicalUrl(), QUrl("http://example.com/movie.mov"));
+ QCOMPARE(media.canonicalResource().url(), QUrl("http://example.com/movie.mov"));
+}
+
+void tst_QMediaContent::testRequestCtor()
+{
+ QNetworkRequest request(QUrl("http://example.com/movie.mov"));
+ request.setAttribute(QNetworkRequest::User, QVariant(1234));
+
+ QMediaContent media(request);
+
+ QCOMPARE(media.canonicalUrl(), QUrl("http://example.com/movie.mov"));
+ QCOMPARE(media.canonicalResource().request(), request);
+ QCOMPARE(media.canonicalResource().url(), QUrl("http://example.com/movie.mov"));
+}
+
+void tst_QMediaContent::testResourceCtor()
+{
+ QMediaContent media(QMediaResource(QUrl("http://example.com/movie.mov")));
+
+ QCOMPARE(media.canonicalResource(), QMediaResource(QUrl("http://example.com/movie.mov")));
+}
+
+void tst_QMediaContent::testResourceListCtor()
+{
+ QMediaResourceList resourceList;
+ resourceList << QMediaResource(QUrl("http://example.com/movie.mov"));
+
+ QMediaContent media(resourceList);
+
+ QCOMPARE(media.canonicalUrl(), QUrl("http://example.com/movie.mov"));
+ QCOMPARE(media.canonicalResource().url(), QUrl("http://example.com/movie.mov"));
+}
+
+void tst_QMediaContent::testCopy()
+{
+ QMediaContent media1(QMediaResource(QUrl("http://example.com/movie.mov")));
+ QMediaContent media2(media1);
+
+ QVERIFY(media1 == media2);
+}
+
+void tst_QMediaContent::testAssignment()
+{
+ QMediaContent media1(QMediaResource(QUrl("http://example.com/movie.mov")));
+ QMediaContent media2;
+ QMediaContent media3;
+
+ media2 = media1;
+ QVERIFY(media2 == media1);
+
+ media2 = media3;
+ QVERIFY(media2 == media3);
+}
+
+void tst_QMediaContent::testEquality()
+{
+ QMediaContent media1;
+ QMediaContent media2;
+ QMediaContent media3(QMediaResource(QUrl("http://example.com/movie.mov")));
+ QMediaContent media4(QMediaResource(QUrl("http://example.com/movie.mov")));
+ QMediaContent media5(QMediaResource(QUrl("file:///some/where/over/the/rainbow.mp3")));
+
+ // null == null
+ QCOMPARE(media1 == media2, true);
+ QCOMPARE(media1 != media2, false);
+
+ // null != something
+ QCOMPARE(media1 == media3, false);
+ QCOMPARE(media1 != media3, true);
+
+ // equiv
+ QCOMPARE(media3 == media4, true);
+ QCOMPARE(media3 != media4, false);
+
+ // not equiv
+ QCOMPARE(media4 == media5, false);
+ QCOMPARE(media4 != media5, true);
+}
+
+void tst_QMediaContent::testResources()
+{
+ QMediaResourceList resourceList;
+
+ resourceList << QMediaResource(QUrl("http://example.com/movie-main.mov"));
+ resourceList << QMediaResource(QUrl("http://example.com/movie-big.mov"));
+ QMediaContent media(resourceList);
+
+ QMediaResourceList res = media.resources();
+ QCOMPARE(res.size(), 2);
+ QCOMPARE(res[0], QMediaResource(QUrl("http://example.com/movie-main.mov")));
+ QCOMPARE(res[1], QMediaResource(QUrl("http://example.com/movie-big.mov")));
+}
+
+QTEST_MAIN(tst_QMediaContent)
+
+#include "tst_qmediacontent.moc"
diff --git a/tests/auto/qmediaimageviewer/images.qrc b/tests/auto/qmediaimageviewer/images.qrc
new file mode 100644
index 000000000..508de1369
--- /dev/null
+++ b/tests/auto/qmediaimageviewer/images.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/coverart.png</file>
+ <file>images/image.jpg</file>
+ <file>images/image.png</file>
+ <file>images/invalid.png</file>
+ <file>images/poster.png</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/qmediaimageviewer/images/coverart.png b/tests/auto/qmediaimageviewer/images/coverart.png
new file mode 100644
index 000000000..a24db1b13
--- /dev/null
+++ b/tests/auto/qmediaimageviewer/images/coverart.png
Binary files differ
diff --git a/tests/auto/qmediaimageviewer/images/image.jpg b/tests/auto/qmediaimageviewer/images/image.jpg
new file mode 100644
index 000000000..8771224cb
--- /dev/null
+++ b/tests/auto/qmediaimageviewer/images/image.jpg
Binary files differ
diff --git a/tests/auto/qmediaimageviewer/images/image.png b/tests/auto/qmediaimageviewer/images/image.png
new file mode 100644
index 000000000..a24db1b13
--- /dev/null
+++ b/tests/auto/qmediaimageviewer/images/image.png
Binary files differ
diff --git a/tests/auto/qmediaimageviewer/images/invalid.png b/tests/auto/qmediaimageviewer/images/invalid.png
new file mode 100644
index 000000000..3aba327ee
--- /dev/null
+++ b/tests/auto/qmediaimageviewer/images/invalid.png
@@ -0,0 +1,2 @@
+This is not really a PNG file.
+
diff --git a/tests/auto/qmediaimageviewer/images/poster.png b/tests/auto/qmediaimageviewer/images/poster.png
new file mode 100644
index 000000000..a24db1b13
--- /dev/null
+++ b/tests/auto/qmediaimageviewer/images/poster.png
Binary files differ
diff --git a/tests/auto/qmediaimageviewer/qmediaimageviewer.pro b/tests/auto/qmediaimageviewer/qmediaimageviewer.pro
new file mode 100644
index 000000000..dab1d2462
--- /dev/null
+++ b/tests/auto/qmediaimageviewer/qmediaimageviewer.pro
@@ -0,0 +1,17 @@
+load(qttest_p4)
+
+QT += multimediakit-private network
+
+# TARGET = tst_qmediaimageviewer
+# CONFIG += testcase
+
+SOURCES += tst_qmediaimageviewer.cpp
+
+RESOURCES += \
+ images.qrc
+
+!contains(QT_CONFIG, no-jpeg):DEFINES += QTEST_HAVE_JPEG
+
+wince* {
+ !contains(QT_CONFIG, no-jpeg): DEPLOYMENT_PLUGIN += qjpeg
+}
diff --git a/tests/auto/qmediaimageviewer/tst_qmediaimageviewer.cpp b/tests/auto/qmediaimageviewer/tst_qmediaimageviewer.cpp
new file mode 100644
index 000000000..2bd56cf39
--- /dev/null
+++ b/tests/auto/qmediaimageviewer/tst_qmediaimageviewer.cpp
@@ -0,0 +1,1036 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <qmobilityglobal.h>
+#include <QtTest/QtTest>
+
+#include <QtCore/qdir.h>
+
+#include <qgraphicsvideoitem.h>
+#include <qmediaimageviewer.h>
+#include <private/qmediaimageviewerservice_p.h>
+#include <qmediaplaylist.h>
+#include <qmediaservice.h>
+#include <qvideorenderercontrol.h>
+#include <qvideowidget.h>
+#include <qvideowidgetcontrol.h>
+
+#include <QtCore/qfile.h>
+#include <QtNetwork/qnetworkaccessmanager.h>
+#include <QtNetwork/qnetworkreply.h>
+
+#include <qabstractvideosurface.h>
+#include <qvideosurfaceformat.h>
+
+QT_USE_NAMESPACE
+class QtTestNetworkAccessManager;
+
+class tst_QMediaImageViewer : public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase();
+
+ void isValid();
+ void timeout();
+ void setMedia_data();
+ void setMedia();
+ void setConsecutiveMedia();
+ void setInvalidMedia();
+ void playlist();
+ void multiplePlaylists();
+ void invalidPlaylist();
+ void elapsedTime();
+ void rendererControl();
+ void setVideoOutput();
+ void debugEnums();
+
+public:
+ tst_QMediaImageViewer() : m_network(0) {}
+
+private:
+ QUrl imageUrl(const char *fileName) const {
+ return QUrl(QLatin1String("qrc:///images/") + QLatin1String(fileName)); }
+ QString imageFileName(const char *fileName) {
+ return QLatin1String(":/images/") + QLatin1String(fileName); }
+
+ QtTestNetworkAccessManager *m_network;
+ QString m_fileProtocol;
+};
+
+class QtTestVideoSurface : public QAbstractVideoSurface
+{
+public:
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const {
+ QList<QVideoFrame::PixelFormat> formats;
+ if (handleType == QAbstractVideoBuffer::NoHandle) {
+ formats << QVideoFrame::Format_RGB32;
+ }
+ return formats;
+ }
+
+ QVideoFrame frame() const { return m_frame; }
+
+ bool present(const QVideoFrame &frame) { m_frame = frame; return true; }
+
+private:
+ QVideoFrame m_frame;
+};
+
+class QtTestNetworkReply : public QNetworkReply
+{
+public:
+ QtTestNetworkReply(
+ const QNetworkRequest &request,
+ const QByteArray &mimeType,
+ QObject *parent)
+ : QNetworkReply(parent)
+ {
+ setRequest(request);
+ setOperation(QNetworkAccessManager::HeadOperation);
+ setRawHeader("content-type", mimeType);
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ }
+
+ QtTestNetworkReply(
+ const QNetworkRequest &request,
+ const QByteArray &mimeType,
+ const QString &fileName,
+ QObject *parent)
+ : QNetworkReply(parent)
+ , m_file(fileName)
+ {
+ setRequest(request);
+ setOperation(QNetworkAccessManager::GetOperation);
+ setRawHeader("content-type", mimeType);
+
+ if (m_file.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) {
+ setOpenMode(QIODevice::ReadOnly);
+ }
+
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ }
+
+ void abort() { m_file.close(); }
+
+ bool atEnd () const { return m_file.atEnd(); }
+ qint64 bytesAvailable() const { return m_file.bytesAvailable() + QIODevice::bytesAvailable(); }
+ void close() { m_file.close(); setOpenMode(QIODevice::NotOpen); }
+ bool isSequential() const { return true; }
+ bool open(OpenMode) { return false; }
+ qint64 pos() const { return 0; }
+ bool seek(qint64) { return false; }
+ qint64 size() const { return m_file.size(); }
+ qint64 readData(char * data, qint64 maxSize) { return m_file.read(data, maxSize); }
+ qint64 writeData(const char *, qint64) { return -1; }
+
+protected:
+ void customEvent(QEvent *event)
+ {
+ if (event->type() == QEvent::User) {
+ event->accept();
+ emit finished();
+ }
+ }
+
+private:
+ QFile m_file;
+};
+
+class QtTestNetworkAccessManager : public QNetworkAccessManager
+{
+public:
+ QtTestNetworkAccessManager(QObject *parent = 0)
+ : QNetworkAccessManager(parent)
+ {
+ }
+
+ void appendDocument(const QUrl &url, const QByteArray &mimeType, const QString &fileName)
+ {
+ m_documents.append(Document(url, mimeType, fileName));
+ }
+
+protected:
+ QNetworkReply *createRequest(
+ Operation op, const QNetworkRequest &request, QIODevice *outgoingData = 0)
+ {
+ foreach (const Document &document, m_documents) {
+ if (document.url == request.url()) {
+ if (op == GetOperation) {
+ return new QtTestNetworkReply(
+ request, document.mimeType, document.fileName, this);
+ } else if (op == HeadOperation) {
+ return new QtTestNetworkReply(request, document.mimeType, this);
+ }
+ }
+ }
+ return QNetworkAccessManager::createRequest(op, request, outgoingData);
+ }
+
+private:
+ struct Document
+ {
+ Document(const QUrl url, const QByteArray mimeType, const QString &fileName)
+ : url(url), mimeType(mimeType), fileName(fileName)
+ {
+ }
+
+ QUrl url;
+ QByteArray mimeType;
+ QString fileName;
+ };
+
+ QList<Document> m_documents;
+};
+
+void tst_QMediaImageViewer::initTestCase()
+{
+ qRegisterMetaType<QMediaImageViewer::State>();
+ qRegisterMetaType<QMediaImageViewer::MediaStatus>();
+
+ m_network = new QtTestNetworkAccessManager(this);
+
+ m_network->appendDocument(
+ QUrl(QLatin1String("test://image/png?id=1")),
+ "image/png",
+ imageFileName("image.png"));
+ m_network->appendDocument(
+ QUrl(QLatin1String("test://image/png?id=2")),
+ QByteArray(),
+ imageFileName("image.png"));
+ m_network->appendDocument(
+ QUrl(QLatin1String("test://image/invalid?id=1")),
+ "image/png",
+ imageFileName("invalid.png"));
+ m_network->appendDocument(
+ QUrl(QLatin1String("test://image/invalid?id=2")),
+ QByteArray(),
+ imageFileName("invalid.png"));
+#ifdef QTEST_HAVE_JPEG
+ m_network->appendDocument(
+ QUrl(QLatin1String("test://image/jpeg?id=1")),
+ "image/jpeg",
+ imageFileName("image.jpg"));
+#endif
+ m_network->appendDocument(
+ QUrl(QLatin1String("test://music/songs/mp3?id=1")),
+ "audio/mpeg",
+ QString());
+ m_network->appendDocument(
+ QUrl(QLatin1String("test://music/covers/small?id=1")),
+ "image/png",
+ imageFileName("coverart.png"));
+ m_network->appendDocument(
+ QUrl(QLatin1String("test://music/covers/large?id=1")),
+ "image/png",
+ imageFileName("coverart.png"));
+ m_network->appendDocument(
+ QUrl(QLatin1String("test://video/movies/mp4?id=1")),
+ "video/mp4",
+ QString());
+ m_network->appendDocument(
+ QUrl(QLatin1String("test://video/posters/png?id=1")),
+ "image/png",
+ imageFileName("poster.png"));
+}
+
+void tst_QMediaImageViewer::isValid()
+{
+ QMediaImageViewer viewer;
+
+ QVERIFY(viewer.service() != 0);
+}
+
+void tst_QMediaImageViewer::timeout()
+{
+ QMediaImageViewer viewer;
+
+ QCOMPARE(viewer.timeout(), 3000);
+
+ viewer.setTimeout(0);
+ QCOMPARE(viewer.timeout(), 0);
+
+ viewer.setTimeout(45);
+ QCOMPARE(viewer.timeout(), 45);
+
+ viewer.setTimeout(-3000);
+ QCOMPARE(viewer.timeout(), 0);
+}
+
+void tst_QMediaImageViewer::setMedia_data()
+{
+ QTest::addColumn<QMediaContent>("media");
+
+ {
+ QMediaContent media(imageUrl("image.png"));
+
+ QTest::newRow("file: png image")
+ << media;
+ } {
+ QMediaContent media(QUrl(QLatin1String("test://image/png?id=1")));
+
+ QTest::newRow("network: png image")
+ << media;
+ } {
+ QMediaContent media(QMediaResource(
+ QUrl(QLatin1String("test://image/png?id=1")), QLatin1String("image/png")));
+
+ QTest::newRow("network: png image, explicit mime type")
+ << media;
+ } {
+ QMediaContent media(QUrl(QLatin1String("test://image/png?id=2")));
+
+ QTest::newRow("network: png image, no mime type")
+ << media;
+#ifdef QTEST_HAVE_JPEG
+ } {
+ QMediaContent media(imageUrl("image.jpg"));
+
+ QTest::newRow("file: jpg image")
+ << media;
+ } {
+ QMediaContent media(QUrl(QLatin1String("test://image/jpeg?id=1")));
+
+ QTest::newRow("network: jpg image")
+ << media;
+#endif
+ }
+}
+
+void tst_QMediaImageViewer::setMedia()
+{
+ QFETCH(QMediaContent, media);
+
+ QMediaImageViewer viewer;
+
+ QMediaImageViewerService *service = qobject_cast<QMediaImageViewerService *>(viewer.service());
+ service->setNetworkManager(m_network);
+
+ connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)),
+ &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ viewer.setMedia(media);
+ QCOMPARE(viewer.media(), media);
+
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ QTestEventLoop::instance().enterLoop(2);
+
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+}
+
+void tst_QMediaImageViewer::setConsecutiveMedia()
+{
+ QMediaContent fileMedia1(imageUrl("image.png"));
+ QMediaContent fileMedia2(imageUrl("coverart.png"));
+ QMediaContent networkMedia1(QUrl(QLatin1String("test://image/png?id=1")));
+ QMediaContent networkMedia2(QUrl(QLatin1String("test://image/png?id=2")));
+
+ QMediaImageViewer viewer;
+
+ connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)),
+ &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ viewer.setMedia(fileMedia1);
+ viewer.setMedia(fileMedia2);
+
+ QCOMPARE(viewer.media(), fileMedia2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.media(), fileMedia2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+
+ QMediaImageViewerService *service = qobject_cast<QMediaImageViewerService *>(viewer.service());
+ service->setNetworkManager(m_network);
+
+ viewer.setMedia(networkMedia1);
+ viewer.setMedia(networkMedia2);
+
+ QCOMPARE(viewer.media(), networkMedia2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.media(), networkMedia2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+
+ viewer.setMedia(fileMedia1);
+ viewer.setMedia(networkMedia2);
+
+ QCOMPARE(viewer.media(), networkMedia2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.media(), networkMedia2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+
+ viewer.setMedia(networkMedia1);
+ viewer.setMedia(fileMedia2);
+
+ QCOMPARE(viewer.media(), fileMedia2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.media(), fileMedia2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+}
+
+void tst_QMediaImageViewer::setInvalidMedia()
+{
+ QMediaImageViewer viewer;
+
+ QMediaImageViewerService *service = qobject_cast<QMediaImageViewerService *>(viewer.service());
+ service->setNetworkManager(m_network);
+
+ connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)),
+ &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ {
+ QMediaContent media(imageUrl("invalid.png"));
+
+ viewer.setMedia(media);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia);
+ QCOMPARE(viewer.media(), media);
+ } {
+ QMediaContent media(imageUrl("deleted.png"));
+
+ viewer.setMedia(media);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia);
+ QCOMPARE(viewer.media(), media);
+ } {
+ QMediaResource invalidResource(imageUrl("invalid.png"));
+ QMediaResource deletedResource(imageUrl("deleted.png"));
+ QMediaContent media(QMediaResourceList() << invalidResource << deletedResource);
+
+ viewer.setMedia(media);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia);
+ QCOMPARE(viewer.media(), media);
+ } {
+ QMediaResource resource(imageUrl("image.png"), QLatin1String("audio/mpeg"));
+ QMediaContent media(resource);
+
+ viewer.setMedia(media);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia);
+ QCOMPARE(viewer.media(), media);
+ } {
+ QMediaResource audioResource(imageUrl("image.png"), QLatin1String("audio/mpeg"));
+ QMediaResource invalidResource(imageUrl("invalid.png"));
+ QMediaContent media(QMediaResourceList() << audioResource << invalidResource);
+
+ viewer.setMedia(media);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia);
+ QCOMPARE(viewer.media(), media);
+ } {
+ QMediaContent media(QUrl(QLatin1String("test://image/invalid?id=1")));
+
+ viewer.setMedia(media);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia);
+ QCOMPARE(viewer.media(), media);
+ } {
+ QMediaContent media(QUrl(QLatin1String("test://image/invalid?id=2")));
+
+ viewer.setMedia(media);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia);
+ QCOMPARE(viewer.media(), media);
+ } {
+ QMediaContent media(QUrl(QLatin1String("test://image/invalid?id=3")));
+
+ viewer.setMedia(media);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia);
+ QCOMPARE(viewer.media(), media);
+ }
+}
+
+void tst_QMediaImageViewer::playlist()
+{
+ QMediaContent imageMedia(imageUrl("image.png"));
+ QMediaContent posterMedia(imageUrl("poster.png"));
+ QMediaContent coverArtMedia(imageUrl("coverart.png"));
+
+ QMediaImageViewer viewer;
+ viewer.setTimeout(250);
+
+ connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)),
+ &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QSignalSpy stateSpy(&viewer, SIGNAL(stateChanged(QMediaImageViewer::State)));
+
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+
+ // No playlist so can't exit stopped state.
+ viewer.play();
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+ QCOMPARE(stateSpy.count(), 0);
+ viewer.pause();
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+ QCOMPARE(stateSpy.count(), 0);
+
+ QMediaPlaylist playlist;
+ viewer.setPlaylist(&playlist);
+
+ // Empty playlist so can't exit stopped state.
+ viewer.play();
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+ QCOMPARE(stateSpy.count(), 0);
+ viewer.pause();
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+ QCOMPARE(stateSpy.count(), 0);
+
+ playlist.addMedia(imageMedia);
+ playlist.addMedia(posterMedia);
+ playlist.addMedia(coverArtMedia);
+
+ // Play progresses immediately to the first image and starts loading.
+ viewer.play();
+ QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState);
+ QCOMPARE(stateSpy.count(), 1);
+ QCOMPARE(qvariant_cast<QMediaImageViewer::State>(stateSpy.last().value(0)),
+ QMediaImageViewer::PlayingState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+ QCOMPARE(playlist.currentIndex(), 0);
+ QCOMPARE(viewer.media(), imageMedia);
+
+ // Image is loaded asynchronously.
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+ QCOMPARE(playlist.currentIndex(), 0);
+
+ // Time out causes progression to second image, which starts loading.
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+ QCOMPARE(playlist.currentIndex(), 1);
+ QCOMPARE(viewer.media(), posterMedia);
+
+ // Image is loaded asynchronously.
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+ QCOMPARE(playlist.currentIndex(), 1);
+
+ // Pausing stops progression at current image.
+ viewer.pause();
+ QCOMPARE(viewer.state(), QMediaImageViewer::PausedState);
+ QCOMPARE(stateSpy.count(), 2);
+ QCOMPARE(qvariant_cast<QMediaImageViewer::State>(stateSpy.last().value(0)),
+ QMediaImageViewer::PausedState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+ QCOMPARE(playlist.currentIndex(), 1);
+
+ // No time out.
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.state(), QMediaImageViewer::PausedState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+ QCOMPARE(playlist.currentIndex(), 1);
+
+ // Resuming playback does not immediately progress to the next item
+ viewer.play();
+ QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+ QCOMPARE(playlist.currentIndex(), 1);
+
+ // Time out causes progression to next image, which starts loading.
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+ QCOMPARE(playlist.currentIndex(), 2);
+ QCOMPARE(viewer.media(), coverArtMedia);
+
+ // Image is loaded asynchronously.
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+ QCOMPARE(playlist.currentIndex(), 2);
+
+ // Time out causes progression to end of list
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+ QCOMPARE(stateSpy.count(), 4);
+ QCOMPARE(qvariant_cast<QMediaImageViewer::State>(stateSpy.last().value(0)),
+ QMediaImageViewer::StoppedState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::NoMedia);
+ QCOMPARE(playlist.currentIndex(), -1);
+ QCOMPARE(viewer.media(), QMediaContent());
+
+ // Stopped, no time out.
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::NoMedia);
+ QCOMPARE(playlist.currentIndex(), -1);
+
+ // Play progresses immediately to the first image and starts loading.
+ viewer.play();
+ QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState);
+ QCOMPARE(stateSpy.count(), 5);
+ QCOMPARE(qvariant_cast<QMediaImageViewer::State>(stateSpy.last().value(0)),
+ QMediaImageViewer::PlayingState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+ QCOMPARE(playlist.currentIndex(), 0);
+ QCOMPARE(viewer.media(), imageMedia);
+
+ // Image is loaded asynchronously.
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+ QCOMPARE(playlist.currentIndex(), 0);
+
+ // Stop ends progress, but retains current index.
+ viewer.stop();
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+ QCOMPARE(stateSpy.count(), 6);
+ QCOMPARE(qvariant_cast<QMediaImageViewer::State>(stateSpy.last().value(0)),
+ QMediaImageViewer::StoppedState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+ QCOMPARE(playlist.currentIndex(), 0);
+ QCOMPARE(viewer.media(), imageMedia);
+
+ // Stoppped, No time out.
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+ QCOMPARE(playlist.currentIndex(), 0);
+ QCOMPARE(viewer.media(), imageMedia);
+
+ // Stop when already stopped doesn't emit additional signals.
+ viewer.stop();
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+ QCOMPARE(stateSpy.count(), 6);
+
+ viewer.play();
+ QCOMPARE(stateSpy.count(), 7);
+
+ // Play when already playing doesn't emit additional signals.
+ viewer.play();
+ QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState);
+ QCOMPARE(stateSpy.count(), 7);
+
+ playlist.next();
+ QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ // Pausing while loading, doesn't stop loading.
+ viewer.pause();
+ QCOMPARE(viewer.state(), QMediaImageViewer::PausedState);
+ QCOMPARE(stateSpy.count(), 8);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.state(), QMediaImageViewer::PausedState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia);
+
+ // Pause while paused doesn't emit additional signals.
+ viewer.pause();
+ QCOMPARE(viewer.state(), QMediaImageViewer::PausedState);
+ QCOMPARE(stateSpy.count(), 8);
+
+ // Calling setMedia stops the playlist.
+ viewer.setMedia(imageMedia);
+ QCOMPARE(viewer.media(), imageMedia);
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+ QCOMPARE(stateSpy.count(), 9);
+ QCOMPARE(qvariant_cast<QMediaImageViewer::State>(stateSpy.last().value(0)),
+ QMediaImageViewer::StoppedState);
+
+}
+
+void tst_QMediaImageViewer::multiplePlaylists()
+{
+ QMediaContent imageMedia(imageUrl("image.png"));
+ QMediaContent posterMedia(imageUrl("poster.png"));
+ QMediaContent coverArtMedia(imageUrl("coverart.png"));
+
+ QMediaImageViewer viewer;
+
+ QMediaPlaylist *playlist1 = new QMediaPlaylist;
+ viewer.setPlaylist(playlist1);
+ playlist1->addMedia(imageMedia);
+ playlist1->addMedia(posterMedia);
+
+ playlist1->setCurrentIndex(0);
+ QCOMPARE(viewer.media(), imageMedia);
+
+ QMediaPlaylist *playlist2 = new QMediaPlaylist;
+
+ viewer.setPlaylist(playlist2);
+ playlist2->addMedia(coverArtMedia);
+
+ QVERIFY(viewer.media().isNull());
+
+ playlist2->setCurrentIndex(0);
+ QCOMPARE(viewer.media(), coverArtMedia);
+
+ delete playlist2;
+ QVERIFY(viewer.media().isNull());
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+
+ viewer.setPlaylist(playlist1);
+ playlist1->setCurrentIndex(0);
+ QCOMPARE(viewer.media(), imageMedia);
+
+ viewer.play();
+ QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState);
+
+ delete playlist1;
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+}
+
+
+void tst_QMediaImageViewer::invalidPlaylist()
+{
+ QMediaContent imageMedia(imageUrl("image.png"));
+ QMediaContent invalidMedia(imageUrl("invalid.png"));
+
+ QMediaImageViewer viewer;
+ viewer.setTimeout(250);
+
+ connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)),
+ &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QSignalSpy stateSpy(&viewer, SIGNAL(stateChanged(QMediaImageViewer::State)));
+ QSignalSpy statusSpy(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)));
+
+ QMediaPlaylist playlist;
+ viewer.setPlaylist(&playlist);
+ playlist.addMedia(invalidMedia);
+ playlist.addMedia(imageMedia);
+ playlist.addMedia(invalidMedia);
+
+ // Test play initially tries to load the first invalid image.
+ viewer.play();
+ QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+ QCOMPARE(viewer.media(), invalidMedia);
+ QCOMPARE(playlist.currentIndex(), 0);
+ QCOMPARE(statusSpy.count(), 1);
+ QCOMPARE(qvariant_cast<QMediaImageViewer::MediaStatus>(statusSpy.value(0).value(0)),
+ QMediaImageViewer::LoadingMedia);
+
+ // Test status is changed to InvalidMedia, and loading of the next image is started immediately.
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia);
+ QCOMPARE(viewer.media(), imageMedia);
+ QCOMPARE(playlist.currentIndex(), 1);
+ QCOMPARE(statusSpy.count(), 3);
+ QCOMPARE(qvariant_cast<QMediaImageViewer::MediaStatus>(statusSpy.value(1).value(0)),
+ QMediaImageViewer::InvalidMedia);
+ QCOMPARE(qvariant_cast<QMediaImageViewer::MediaStatus>(statusSpy.value(2).value(0)),
+ QMediaImageViewer::LoadingMedia);
+
+ // Test if the last image is invalid, the image viewer is stopped.
+ playlist.next();
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::NoMedia);
+ QCOMPARE(playlist.currentIndex(), -1);
+ QCOMPARE(stateSpy.count(), 2);
+
+ playlist.setCurrentIndex(2);
+ QTestEventLoop::instance().enterLoop(2);
+
+ // Test play immediately moves to the next item if the current one is invalid, and no state
+ // change signals are emitted if the viewer never effectively moves from the StoppedState.
+ viewer.play();
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+ QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::NoMedia);
+ QCOMPARE(playlist.currentIndex(), -1);
+ QCOMPARE(stateSpy.count(), 2);
+}
+
+void tst_QMediaImageViewer::elapsedTime()
+{
+ QMediaContent imageMedia(imageUrl("image.png"));
+
+ QMediaImageViewer viewer;
+ viewer.setTimeout(250);
+ viewer.setNotifyInterval(150);
+
+ QSignalSpy spy(&viewer, SIGNAL(elapsedTimeChanged(int)));
+
+ connect(&viewer, SIGNAL(elapsedTimeChanged(int)),
+ &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+
+ QMediaPlaylist playlist;
+ viewer.setPlaylist(&playlist);
+ playlist.addMedia(imageMedia);
+
+ QCOMPARE(viewer.elapsedTime(), 0);
+
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(spy.count(), 0);
+
+ viewer.play();
+ QCOMPARE(viewer.elapsedTime(), 0);
+
+ // Emits an initial elapsed time at 0 milliseconds signal when the image is loaded.
+ QTestEventLoop::instance().enterLoop(1);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.last().value(0).toInt(), 0);
+
+ // Emits a scheduled signal after the notify interval is up. The exact time will be a little
+ // fuzzy.
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(spy.last().value(0).toInt() != 0);
+
+ // Pausing will emit a signal with the elapsed time when paused.
+ viewer.pause();
+ QCOMPARE(spy.count(), 3);
+ QCOMPARE(viewer.elapsedTime(), spy.last().value(0).toInt());
+
+ // No elapsed time signals will be emitted while paused.
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(spy.count(), 3);
+
+ // Stopping a paused viewer resets the elapsed time to 0 with signals emitted.
+ viewer.stop();
+ QCOMPARE(viewer.elapsedTime(), 0);
+ QCOMPARE(spy.count(), 4);
+ QCOMPARE(spy.last().value(0).toInt(), 0);
+
+ disconnect(&viewer, SIGNAL(elapsedTimeChanged(int)),
+ &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)),
+ &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ // Play until end.
+ viewer.play();
+ QTestEventLoop::instance().enterLoop(2);
+
+ // Verify at least two more signals are emitted.
+ // The second to last at the instant the timeout expired, and the last as it's reset when the
+ // current media is cleared.
+ QVERIFY(spy.count() >= 5);
+ QCOMPARE(spy.value(spy.count() - 2).value(0).toInt(), 250);
+ QCOMPARE(spy.value(spy.count() - 1).value(0).toInt(), 0);
+
+ viewer.play();
+ QTestEventLoop::instance().enterLoop(2);
+
+ // Test extending the timeout applies to an already loaded image.
+ viewer.setTimeout(10000);
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState);
+
+ // Test reducing the timeout applies to an already loaded image.
+ viewer.setTimeout(1000);
+ QTestEventLoop::instance().enterLoop(2);
+ QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState);
+
+}
+
+void tst_QMediaImageViewer::rendererControl()
+{
+ QtTestVideoSurface surfaceA;
+ QtTestVideoSurface surfaceB;
+ QAbstractVideoSurface *nullSurface = 0;
+
+ QMediaImageViewer viewer;
+
+ QMediaService *service = viewer.service();
+ if (service == 0)
+ QSKIP("Image viewer object has no service.", SkipSingle);
+
+ QMediaControl *mediaControl = service->requestControl(QVideoRendererControl_iid);
+ QVERIFY(mediaControl != 0);
+
+ QVideoRendererControl *rendererControl = qobject_cast<QVideoRendererControl *>(mediaControl);
+ QVERIFY(rendererControl != 0);
+
+ rendererControl->setSurface(&surfaceA);
+ QCOMPARE(rendererControl->surface(), (QAbstractVideoSurface *)&surfaceA);
+
+ // Load an image so the viewer has some dimensions to work with.
+ viewer.setMedia(QMediaContent(imageUrl("image.png")));
+
+ connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)),
+ &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(2);
+
+ if (viewer.mediaStatus() != QMediaImageViewer::LoadedMedia)
+ QSKIP("failed to load test image", SkipSingle);
+
+ QCOMPARE(surfaceA.isActive(), true);
+
+ {
+ QVideoSurfaceFormat format = surfaceA.surfaceFormat();
+ QCOMPARE(format.handleType(), QAbstractVideoBuffer::NoHandle);
+ QCOMPARE(format.pixelFormat(), QVideoFrame::Format_RGB32);
+ QCOMPARE(format.frameSize(), QSize(75, 50));
+
+ QVideoFrame frame = surfaceA.frame();
+ QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle);
+ QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_RGB32);
+ QCOMPARE(frame.size(), QSize(75, 50));
+ }
+ // Test clearing the output stops the video surface.
+ service->releaseControl(rendererControl);
+ QCOMPARE(surfaceA.isActive(), false);
+
+ // Test reseting the output restarts it.
+ mediaControl = service->requestControl(QVideoRendererControl_iid);
+ QVERIFY(mediaControl != 0);
+
+ rendererControl = qobject_cast<QVideoRendererControl *>(mediaControl);
+ rendererControl->setSurface(&surfaceA);
+ QVERIFY(rendererControl != 0);
+ {
+ QVideoSurfaceFormat format = surfaceA.surfaceFormat();
+ QCOMPARE(format.handleType(), QAbstractVideoBuffer::NoHandle);
+ QCOMPARE(format.pixelFormat(), QVideoFrame::Format_RGB32);
+ QCOMPARE(format.frameSize(), QSize(75, 50));
+
+ QVideoFrame frame = surfaceA.frame();
+ QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle);
+ QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_RGB32);
+ QCOMPARE(frame.size(), QSize(75, 50));
+ }
+
+ // Test changing the surface while viewing an image stops the old surface and starts
+ // the new one and presents the image.
+ rendererControl->setSurface(&surfaceB);
+ QCOMPARE(rendererControl->surface(), (QAbstractVideoSurface*)&surfaceB);
+
+ QCOMPARE(surfaceA.isActive(), false);
+ QCOMPARE(surfaceB.isActive(), true);
+
+ QVideoSurfaceFormat format = surfaceB.surfaceFormat();
+ QCOMPARE(format.handleType(), QAbstractVideoBuffer::NoHandle);
+ QCOMPARE(format.pixelFormat(), QVideoFrame::Format_RGB32);
+ QCOMPARE(format.frameSize(), QSize(75, 50));
+
+ QVideoFrame frame = surfaceB.frame();
+ QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle);
+ QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_RGB32);
+ QCOMPARE(frame.size(), QSize(75, 50));
+
+ // Test setting null media stops the surface.
+ viewer.setMedia(QMediaContent());
+ QCOMPARE(surfaceB.isActive(), false);
+
+ // Test the renderer control accepts a null surface.
+ rendererControl->setSurface(0);
+ QCOMPARE(rendererControl->surface(), nullSurface);
+}
+
+void tst_QMediaImageViewer::setVideoOutput()
+{
+ QMediaImageViewer imageViewer;
+ imageViewer.setMedia(QMediaContent(imageUrl("image.png")));
+
+ connect(&imageViewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)),
+ &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTestEventLoop::instance().enterLoop(2);
+
+ if (imageViewer.mediaStatus() != QMediaImageViewer::LoadedMedia)
+ QSKIP("failed to load test image", SkipSingle);
+
+ QVideoWidget widget;
+ QGraphicsVideoItem item;
+ QtTestVideoSurface surface;
+
+ imageViewer.setVideoOutput(&widget);
+ QVERIFY(widget.mediaObject() == &imageViewer);
+
+ imageViewer.setVideoOutput(&item);
+ QVERIFY(widget.mediaObject() == 0);
+ QVERIFY(item.mediaObject() == &imageViewer);
+
+ imageViewer.setVideoOutput(reinterpret_cast<QVideoWidget *>(0));
+ QVERIFY(item.mediaObject() == 0);
+
+ imageViewer.setVideoOutput(&widget);
+ QVERIFY(widget.mediaObject() == &imageViewer);
+
+ imageViewer.setVideoOutput(reinterpret_cast<QGraphicsVideoItem *>(0));
+ QVERIFY(widget.mediaObject() == 0);
+
+ imageViewer.setVideoOutput(&surface);
+ QVERIFY(surface.isActive());
+
+ imageViewer.setVideoOutput(reinterpret_cast<QAbstractVideoSurface *>(0));
+ QVERIFY(!surface.isActive());
+
+ imageViewer.setVideoOutput(&surface);
+ QVERIFY(surface.isActive());
+
+ imageViewer.setVideoOutput(&widget);
+ QVERIFY(!surface.isActive());
+ QVERIFY(widget.mediaObject() == &imageViewer);
+
+ imageViewer.setVideoOutput(&surface);
+ QVERIFY(surface.isActive());
+ QVERIFY(widget.mediaObject() == 0);
+}
+
+void tst_QMediaImageViewer::debugEnums()
+{
+ QTest::ignoreMessage(QtDebugMsg, "QMediaImageViewer::PlayingState ");
+ qDebug() << QMediaImageViewer::PlayingState;
+ QTest::ignoreMessage(QtDebugMsg, "QMediaImageViewer::NoMedia ");
+ qDebug() << QMediaImageViewer::NoMedia;
+}
+
+QTEST_MAIN(tst_QMediaImageViewer)
+
+#include "tst_qmediaimageviewer.moc"
diff --git a/tests/auto/qmediaobject/main.cpp b/tests/auto/qmediaobject/main.cpp
new file mode 100644
index 000000000..4dc763f11
--- /dev/null
+++ b/tests/auto/qmediaobject/main.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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.h>
+#include <QtTest/QtTest>
+
+#include "tst_qmediaobject.h"
+#ifdef Q_OS_SYMBIAN
+#include "tst_qmediaobject_xa.h"
+#include "tst_qmediaobject_mmf.h"
+#endif
+
+int main(int argc, char**argv)
+{
+ QApplication app(argc,argv);
+ int ret;
+ tst_QMediaObject test_api;
+ ret = QTest::qExec(&test_api, argc, argv);
+#ifdef Q_OS_SYMBIAN
+ char *new_argv[3];
+ QString str = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_xa.log";
+ QByteArray bytes = str.toAscii();
+ char arg1[] = "-o";
+ new_argv[0] = argv[0];
+ new_argv[1] = arg1;
+ new_argv[2] = bytes.data();
+ tst_QMetadata_xa test_xa;
+ ret = QTest::qExec(&test_xa, 3, new_argv);
+ char *new_argv1[3];
+ QString str1 = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_s60.log";
+ QByteArray bytes1 = str1.toAscii();
+ char arg2[] = "-o";
+ new_argv1[0] = argv[0];
+ new_argv1[1] = arg2;
+ new_argv1[2] = bytes1.data();
+ tst_QMediaObject_mmf test_mmf;
+ ret = QTest::qExec(&test_mmf, 3, new_argv1);
+#endif
+ return ret;
+}
diff --git a/tests/auto/qmediaobject/qmediaobject.pro b/tests/auto/qmediaobject/qmediaobject.pro
new file mode 100644
index 000000000..756603ad7
--- /dev/null
+++ b/tests/auto/qmediaobject/qmediaobject.pro
@@ -0,0 +1,27 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qmediaobject
+# CONFIG += testcase
+
+symbian {
+ HEADERS += tst_qmediaobject_xa.h
+ SOURCES += tst_qmediaobject_xa.cpp
+ TARGET.CAPABILITY = ALL -TCB
+
+ testFiles.sources = testfiles/*
+ testFiles.path = /Data/testfiles
+ DEPLOYMENT += testFiles
+ HEADERS += tst_qmediaobject_mmf.h
+ SOURCES += tst_qmediaobject_mmf.cpp
+ TARGET.CAPABILITY = ALL -TCB
+
+ testFiles.sources = testfiles/*
+ testFiles.path = /Data/testfiles
+ DEPLOYMENT += testFiles
+}
+
+HEADERS+= tst_qmediaobject.h
+SOURCES += main.cpp tst_qmediaobject.cpp
+
diff --git a/tests/auto/qmediaobject/tst_qmediaobject.cpp b/tests/auto/qmediaobject/tst_qmediaobject.cpp
new file mode 100644
index 000000000..b286c4ed9
--- /dev/null
+++ b/tests/auto/qmediaobject/tst_qmediaobject.cpp
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include "tst_qmediaobject.h"
+
+QT_USE_NAMESPACE
+
+void tst_QMediaObject::propertyWatch()
+{
+ QtTestMediaObject object;
+ object.setNotifyInterval(0);
+
+ QEventLoop loop;
+ connect(&object, SIGNAL(aChanged(int)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ connect(&object, SIGNAL(bChanged(int)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ connect(&object, SIGNAL(cChanged(int)), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QSignalSpy aSpy(&object, SIGNAL(aChanged(int)));
+ QSignalSpy bSpy(&object, SIGNAL(bChanged(int)));
+ QSignalSpy cSpy(&object, SIGNAL(cChanged(int)));
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QCOMPARE(aSpy.count(), 0);
+ QCOMPARE(bSpy.count(), 0);
+ QCOMPARE(cSpy.count(), 0);
+
+ int aCount = 0;
+ int bCount = 0;
+ int cCount = 0;
+
+ object.addPropertyWatch("a");
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QVERIFY(aSpy.count() > aCount);
+ QCOMPARE(bSpy.count(), 0);
+ QCOMPARE(cSpy.count(), 0);
+ QCOMPARE(aSpy.last().value(0).toInt(), 0);
+
+ aCount = aSpy.count();
+
+ object.setA(54);
+ object.setB(342);
+ object.setC(233);
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QVERIFY(aSpy.count() > aCount);
+ QCOMPARE(bSpy.count(), 0);
+ QCOMPARE(cSpy.count(), 0);
+ QCOMPARE(aSpy.last().value(0).toInt(), 54);
+
+ aCount = aSpy.count();
+
+ object.addPropertyWatch("b");
+ object.addPropertyWatch("d");
+ object.removePropertyWatch("e");
+ object.setA(43);
+ object.setB(235);
+ object.setC(90);
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QVERIFY(aSpy.count() > aCount);
+ QVERIFY(bSpy.count() > bCount);
+ QCOMPARE(cSpy.count(), 0);
+ QCOMPARE(aSpy.last().value(0).toInt(), 43);
+ QCOMPARE(bSpy.last().value(0).toInt(), 235);
+
+ aCount = aSpy.count();
+ bCount = bSpy.count();
+
+ object.removePropertyWatch("a");
+ object.addPropertyWatch("c");
+ object.addPropertyWatch("e");
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QCOMPARE(aSpy.count(), aCount);
+ QVERIFY(bSpy.count() > bCount);
+ QVERIFY(cSpy.count() > cCount);
+ QCOMPARE(bSpy.last().value(0).toInt(), 235);
+ QCOMPARE(cSpy.last().value(0).toInt(), 90);
+
+ bCount = bSpy.count();
+ cCount = cSpy.count();
+
+ object.setA(435);
+ object.setC(9845);
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QCOMPARE(aSpy.count(), aCount);
+ QVERIFY(bSpy.count() > bCount);
+ QVERIFY(cSpy.count() > cCount);
+ QCOMPARE(bSpy.last().value(0).toInt(), 235);
+ QCOMPARE(cSpy.last().value(0).toInt(), 9845);
+
+ bCount = bSpy.count();
+ cCount = cSpy.count();
+
+ object.setA(8432);
+ object.setB(324);
+ object.setC(443);
+ object.removePropertyWatch("c");
+ object.removePropertyWatch("d");
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QCOMPARE(aSpy.count(), aCount);
+ QVERIFY(bSpy.count() > bCount);
+ QCOMPARE(cSpy.count(), cCount);
+ QCOMPARE(bSpy.last().value(0).toInt(), 324);
+ QCOMPARE(cSpy.last().value(0).toInt(), 9845);
+
+ bCount = bSpy.count();
+
+ object.removePropertyWatch("b");
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QCOMPARE(aSpy.count(), aCount);
+ QCOMPARE(bSpy.count(), bCount);
+ QCOMPARE(cSpy.count(), cCount);
+}
+
+void tst_QMediaObject::setupNotifyTests()
+{
+ QTest::addColumn<int>("interval");
+ QTest::addColumn<int>("count");
+
+ QTest::newRow("single 750ms")
+ << 750
+ << 1;
+ QTest::newRow("single 600ms")
+ << 600
+ << 1;
+ QTest::newRow("x3 300ms")
+ << 300
+ << 3;
+ QTest::newRow("x5 180ms")
+ << 180
+ << 5;
+}
+
+void tst_QMediaObject::notifySignals_data()
+{
+ setupNotifyTests();
+}
+
+void tst_QMediaObject::notifySignals()
+{
+ QFETCH(int, interval);
+ QFETCH(int, count);
+
+ QtTestMediaObject object;
+ object.setNotifyInterval(interval);
+ object.addPropertyWatch("a");
+
+ QSignalSpy spy(&object, SIGNAL(aChanged(int)));
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QCOMPARE(spy.count(), count);
+}
+
+void tst_QMediaObject::notifyInterval_data()
+{
+ setupNotifyTests();
+}
+
+void tst_QMediaObject::notifyInterval()
+{
+ QFETCH(int, interval);
+
+ QtTestMediaObject object;
+ QSignalSpy spy(&object, SIGNAL(notifyIntervalChanged(int)));
+
+ object.setNotifyInterval(interval);
+ QCOMPARE(object.notifyInterval(), interval);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.last().value(0).toInt(), interval);
+
+ object.setNotifyInterval(interval);
+ QCOMPARE(object.notifyInterval(), interval);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QMediaObject::nullMetaDataControl()
+{
+ const QString titleKey(QLatin1String("Title"));
+ const QString title(QLatin1String("Host of Seraphim"));
+
+ QtTestMetaDataService service;
+ service.hasMetaData = false;
+
+ QtTestMediaObject object(&service);
+
+ QSignalSpy spy(&object, SIGNAL(metaDataChanged()));
+
+ QCOMPARE(object.isMetaDataAvailable(), false);
+
+ QCOMPARE(object.metaData(QtMultimediaKit::Title).toString(), QString());
+ QCOMPARE(object.extendedMetaData(titleKey).toString(), QString());
+ QCOMPARE(object.availableMetaData(), QList<QtMultimediaKit::MetaData>());
+ QCOMPARE(object.availableExtendedMetaData(), QStringList());
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QMediaObject::isMetaDataAvailable()
+{
+ QtTestMetaDataService service;
+ service.metaData.setMetaDataAvailable(false);
+
+ QtTestMediaObject object(&service);
+ QCOMPARE(object.isMetaDataAvailable(), false);
+
+ QSignalSpy spy(&object, SIGNAL(metaDataAvailableChanged(bool)));
+ service.metaData.setMetaDataAvailable(true);
+
+ QCOMPARE(object.isMetaDataAvailable(), true);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), true);
+
+ service.metaData.setMetaDataAvailable(false);
+
+ QCOMPARE(object.isMetaDataAvailable(), false);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.at(1).at(0).toBool(), false);
+}
+
+void tst_QMediaObject::metaDataChanged()
+{
+ QtTestMetaDataService service;
+ QtTestMediaObject object(&service);
+
+ QSignalSpy spy(&object, SIGNAL(metaDataChanged()));
+
+ service.metaData.metaDataChanged();
+ QCOMPARE(spy.count(), 1);
+
+ service.metaData.metaDataChanged();
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_QMediaObject::metaData_data()
+{
+ QTest::addColumn<QString>("artist");
+ QTest::addColumn<QString>("title");
+ QTest::addColumn<QString>("genre");
+
+ QTest::newRow("")
+ << QString::fromLatin1("Dead Can Dance")
+ << QString::fromLatin1("Host of Seraphim")
+ << QString::fromLatin1("Awesome");
+}
+
+void tst_QMediaObject::metaData()
+{
+ QFETCH(QString, artist);
+ QFETCH(QString, title);
+ QFETCH(QString, genre);
+
+ QtTestMetaDataService service;
+ service.metaData.populateMetaData();
+
+ QtTestMediaObject object(&service);
+ QVERIFY(object.availableMetaData().isEmpty());
+
+ service.metaData.m_data.insert(QtMultimediaKit::AlbumArtist, artist);
+ service.metaData.m_data.insert(QtMultimediaKit::Title, title);
+ service.metaData.m_data.insert(QtMultimediaKit::Genre, genre);
+
+ QCOMPARE(object.metaData(QtMultimediaKit::AlbumArtist).toString(), artist);
+ QCOMPARE(object.metaData(QtMultimediaKit::Title).toString(), title);
+
+ QList<QtMultimediaKit::MetaData> metaDataKeys = object.availableMetaData();
+ QCOMPARE(metaDataKeys.size(), 3);
+ QVERIFY(metaDataKeys.contains(QtMultimediaKit::AlbumArtist));
+ QVERIFY(metaDataKeys.contains(QtMultimediaKit::Title));
+ QVERIFY(metaDataKeys.contains(QtMultimediaKit::Genre));
+}
+
+void tst_QMediaObject::extendedMetaData()
+{
+ QFETCH(QString, artist);
+ QFETCH(QString, title);
+ QFETCH(QString, genre);
+
+ QtTestMetaDataService service;
+ QtTestMediaObject object(&service);
+ QVERIFY(object.availableExtendedMetaData().isEmpty());
+
+ service.metaData.m_extendedData.insert(QLatin1String("Artist"), artist);
+ service.metaData.m_extendedData.insert(QLatin1String("Title"), title);
+ service.metaData.m_extendedData.insert(QLatin1String("Genre"), genre);
+
+ QCOMPARE(object.extendedMetaData(QLatin1String("Artist")).toString(), artist);
+ QCOMPARE(object.extendedMetaData(QLatin1String("Title")).toString(), title);
+
+ QStringList extendedKeys = object.availableExtendedMetaData();
+ QCOMPARE(extendedKeys.size(), 3);
+ QVERIFY(extendedKeys.contains(QLatin1String("Artist")));
+ QVERIFY(extendedKeys.contains(QLatin1String("Title")));
+ QVERIFY(extendedKeys.contains(QLatin1String("Genre")));
+}
+
+void tst_QMediaObject::availability()
+{
+ QtTestMediaObject nullObject(0);
+ QCOMPARE(nullObject.isAvailable(), false);
+ QCOMPARE(nullObject.availabilityError(), QtMultimediaKit::ServiceMissingError);
+
+ QtTestMetaDataService service;
+ QtTestMediaObject object(&service);
+ QCOMPARE(object.isAvailable(), true);
+ QCOMPARE(object.availabilityError(), QtMultimediaKit::NoError);
+}
diff --git a/tests/auto/qmediaobject/tst_qmediaobject.h b/tests/auto/qmediaobject/tst_qmediaobject.h
new file mode 100644
index 000000000..3b46f752f
--- /dev/null
+++ b/tests/auto/qmediaobject/tst_qmediaobject.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** 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 TST_QMEDIAOBJECT_H
+#define TST_QMEDIAOBJECT_H
+
+#include <QtTest/QtTest>
+
+#include <QtCore/qtimer.h>
+
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qmetadatareadercontrol.h>
+
+//TESTED_COMPONENT=src/multimedia
+
+QT_USE_NAMESPACE
+class tst_QMediaObject : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void propertyWatch();
+ void notifySignals_data();
+ void notifySignals();
+ void notifyInterval_data();
+ void notifyInterval();
+
+ void nullMetaDataControl();
+ void isMetaDataAvailable();
+ void metaDataChanged();
+ void metaData_data();
+ void metaData();
+ void availability();
+ void extendedMetaData_data() { metaData_data(); }
+ void extendedMetaData();
+
+
+private:
+ void setupNotifyTests();
+};
+
+class QtTestMetaDataProvider : public QMetaDataReaderControl
+{
+ Q_OBJECT
+public:
+ QtTestMetaDataProvider(QObject *parent = 0)
+ : QMetaDataReaderControl(parent)
+ , m_available(false)
+ {
+ }
+
+ bool isMetaDataAvailable() const { return m_available; }
+ void setMetaDataAvailable(bool available) {
+ if (m_available != available)
+ emit metaDataAvailableChanged(m_available = available);
+ }
+ QList<QtMultimediaKit::MetaData> availableMetaData() const { return m_data.keys(); }
+
+
+ QVariant metaData(QtMultimediaKit::MetaData key) const { return m_data.value(key); }
+
+ QVariant extendedMetaData(const QString &key) const { return m_extendedData.value(key); }
+
+ QStringList availableExtendedMetaData() const { return m_extendedData.keys(); }
+
+ using QMetaDataReaderControl::metaDataChanged;
+
+ void populateMetaData()
+ {
+ m_available = true;
+ }
+
+ bool m_available;
+ QMap<QtMultimediaKit::MetaData, QVariant> m_data;
+ QMap<QString, QVariant> m_extendedData;
+};
+
+class QtTestMetaDataService : public QMediaService
+{
+ Q_OBJECT
+public:
+ QtTestMetaDataService(QObject *parent = 0):QMediaService(parent), metaDataRef(0), hasMetaData(true)
+ {
+ }
+
+ QMediaControl *requestControl(const char *iid)
+ {
+ if (hasMetaData && qstrcmp(iid, QMetaDataReaderControl_iid) == 0)
+ return &metaData;
+ else
+ return 0;
+ }
+
+ void releaseControl(QMediaControl *)
+ {
+ }
+
+ QtTestMetaDataProvider metaData;
+ int metaDataRef;
+ bool hasMetaData;
+};
+
+class QtTestMediaObject : public QMediaObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int a READ a WRITE setA NOTIFY aChanged)
+ Q_PROPERTY(int b READ b WRITE setB NOTIFY bChanged)
+ Q_PROPERTY(int c READ c WRITE setC NOTIFY cChanged)
+ Q_PROPERTY(int d READ d WRITE setD)
+public:
+ QtTestMediaObject(QMediaService *service = 0): QMediaObject(0, service), m_a(0), m_b(0), m_c(0), m_d(0) {}
+
+ using QMediaObject::addPropertyWatch;
+ using QMediaObject::removePropertyWatch;
+
+ int a() const { return m_a; }
+ void setA(int a) { m_a = a; }
+
+ int b() const { return m_b; }
+ void setB(int b) { m_b = b; }
+
+ int c() const { return m_c; }
+ void setC(int c) { m_c = c; }
+
+ int d() const { return m_d; }
+ void setD(int d) { m_d = d; }
+
+Q_SIGNALS:
+ void aChanged(int a);
+ void bChanged(int b);
+ void cChanged(int c);
+
+private:
+ int m_a;
+ int m_b;
+ int m_c;
+ int m_d;
+};
+#endif //TST_QMEDIAOBJECT_H \ No newline at end of file
diff --git a/tests/auto/qmediaobject/tst_qmediaobject_mmf.cpp b/tests/auto/qmediaobject/tst_qmediaobject_mmf.cpp
new file mode 100644
index 000000000..7cf5622a5
--- /dev/null
+++ b/tests/auto/qmediaobject/tst_qmediaobject_mmf.cpp
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 <tst_qmediaobject_mmf.h>
+
+QT_USE_NAMESPACE
+
+void tst_QMediaObject_mmf::initTestCase_data()
+{
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<QMediaContent>("mediaContent");
+ QTest::addColumn<bool>("metaDataAvailable");
+
+ QTest::newRow("TestDataNull")
+ << false // valid
+ << QMediaContent() // mediaContent
+ << false; // metaDataAvailable
+
+ QTest::newRow("test_amr.amr")
+ << true // valid
+ << QMediaContent(QUrl("file:///C:/data/testfiles/test_amr.amr")) // mediaContent
+ << false; // metaDataAvailable
+
+ QTest::newRow("test_flash_video.flv")
+ << true // valid
+ << QMediaContent(QUrl("file:///C:/data/testfiles/test_flash_video.flv")) // mediaContent
+ << false; // metaDataAvailable
+
+ QTest::newRow("test_invalid_extension_mp4.xyz")
+ << true // valid
+ << QMediaContent(QUrl("file:///C:/data/testfiles/test_invalid_extension_mp4.xyz")) // mediaContent
+ << false; // metaDataAvailable
+
+ QTest::newRow("test_invalid_extension_wav.xyz")
+ << true // valid
+ << QMediaContent(QUrl("file:///C:/data/testfiles/test_invalid_extension_wav.xyz")) // mediaContent
+ << false; // metaDataAvailable
+
+ QTest::newRow("test_mp3.mp3")
+ << true // valid
+ << QMediaContent(QUrl("file:///C:/data/testfiles/test_mp3.mp3")) // mediaContent
+#if !defined(__WINS__) || !defined(__WINSCW__)
+ << true; // metaDataAvailable
+#else
+ << false; // metaDataAvailable
+#endif // !defined(__WINS__) || defined(__WINSCW__)
+
+ QTest::newRow("test_mp3_no_metadata.mp3")
+ << true // valid
+ << QMediaContent(QUrl("file:///C:/data/testfiles/test_mp3_no_metadata.mp3")) // mediaContent
+ << false; // metaDataAvailable
+
+ QTest::newRow("test_mp4.mp4")
+ << true // valid
+ << QMediaContent(QUrl("file:///C:/data/testfiles/test_mp4.mp4")) // mediaContent
+#if defined(__WINS__) || defined(__WINSCW__)
+ << true; // metaDataAvailable
+#else
+ << false; // metaDataAvailable
+#endif // !defined(__WINS__) || defined(__WINSCW__)
+
+ QTest::newRow("test_wav.wav")
+ << true // valid
+ << QMediaContent(QUrl("file:///C:/data/testfiles/test_wav.wav")) // mediaContent
+ << false; // metaDataAvailable
+
+ QTest::newRow("test_wmv9.wmv")
+ << true // valid
+ << QMediaContent(QUrl("file:///C:/data/testfiles/test_wmv9.wmv")) // mediaContent
+ << false; // metaDataAvailable
+
+ QTest::newRow("test youtube stream")
+ << true // valid
+ << QMediaContent(QUrl("rtsp://v3.cache4.c.youtube.com/CkgLENy73wIaPwlU2rm7yu8PFhMYESARFEIJbXYtZ29vZ2xlSARSB3JlbGF0ZWRaDkNsaWNrVGh1bWJuYWlsYPi6_IXT2rvpSgw=/0/0/0/video.3gp")) // mediaContent
+ << false; // metaDataAvailable
+}
+
+void tst_QMediaObject_mmf::initTestCase()
+{
+}
+
+void tst_QMediaObject_mmf::cleanupTestCase()
+{
+}
+
+void tst_QMediaObject_mmf::init()
+{
+ qRegisterMetaType<QMediaContent>("QMediaContent");
+}
+
+void tst_QMediaObject_mmf::cleanup()
+{
+}
+
+void tst_QMediaObject_mmf::isMetaDataAvailable()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(bool, metaDataAvailable);
+ QMediaPlayer player;
+
+ player.setMedia(mediaContent);
+ QTest::qWait(700);
+ QVERIFY(player.isMetaDataAvailable() == metaDataAvailable);
+}
+
+void tst_QMediaObject_mmf::metaData()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(bool, metaDataAvailable);
+ QMediaPlayer player;
+
+ player.setMedia(mediaContent);
+ QTest::qWait(700);
+ const QString artist(QLatin1String("Artist"));
+ const QString title(QLatin1String("Title"));
+
+ if (player.isMetaDataAvailable()) {
+ QCOMPARE(player.metaData(QtMultimediaKit::AlbumArtist).toString(), artist);
+ QCOMPARE(player.metaData(QtMultimediaKit::Title).toString(), title);
+ }
+}
+
+void tst_QMediaObject_mmf::availableMetaData()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(bool, metaDataAvailable);
+ QMediaPlayer player;
+
+ player.setMedia(mediaContent);
+ QTest::qWait(700);
+
+ if (player.isMetaDataAvailable()) {
+ QList<QtMultimediaKit::MetaData> metaDataKeys = player.availableMetaData();
+ QVERIFY(metaDataKeys.count() > 0);
+ QVERIFY(metaDataKeys.contains(QtMultimediaKit::AlbumArtist));
+ QVERIFY(metaDataKeys.contains(QtMultimediaKit::Title));
+ }
+}
+
+void tst_QMediaObject_mmf::extendedMetaData()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QMediaPlayer player;
+
+ player.setMedia(mediaContent);
+ QTest::qWait(700);
+ const QString artist(QLatin1String("Artist"));
+ const QString title(QLatin1String("Title"));
+
+ if (player.isMetaDataAvailable()) {
+ QCOMPARE(player.extendedMetaData(metaDataKeyAsString(QtMultimediaKit::AlbumArtist)).toString(), artist);
+ QCOMPARE(player.extendedMetaData(metaDataKeyAsString(QtMultimediaKit::Title)).toString(), title);
+ }
+}
+
+void tst_QMediaObject_mmf::availableExtendedMetaData()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QMediaPlayer player;
+
+ player.setMedia(mediaContent);
+ QTest::qWait(700);
+ const QString artist(QLatin1String("Artist"));
+ const QString title(QLatin1String("Title"));
+
+ if (player.isMetaDataAvailable()) {
+ QStringList metaDataKeys = player.availableExtendedMetaData();
+ QVERIFY(metaDataKeys.count() > 0);
+/* qWarning() << "metaDataKeys.count: " << metaDataKeys.count();
+ int count = metaDataKeys.count();
+ count = count-1;
+ int i = 0;
+ while(count >= i)
+ {
+ qWarning() << "metaDataKeys "<<i<<"." << metaDataKeys.at(i);
+ i++;
+ }*/
+ QVERIFY(metaDataKeys.contains(metaDataKeyAsString(QtMultimediaKit::AlbumArtist)));
+ QVERIFY(metaDataKeys.contains(metaDataKeyAsString(QtMultimediaKit::Title)));
+ }
+}
+
+QString tst_QMediaObject_mmf::metaDataKeyAsString(QtMultimediaKit::MetaData key) const
+{
+ switch(key) {
+ case QtMultimediaKit::Title: return "title";
+ case QtMultimediaKit::AlbumArtist: return "artist";
+ case QtMultimediaKit::Comment: return "comment";
+ case QtMultimediaKit::Genre: return "genre";
+ case QtMultimediaKit::Year: return "year";
+ case QtMultimediaKit::Copyright: return "copyright";
+ case QtMultimediaKit::AlbumTitle: return "album";
+ case QtMultimediaKit::Composer: return "composer";
+ case QtMultimediaKit::TrackNumber: return "albumtrack";
+ case QtMultimediaKit::AudioBitRate: return "audiobitrate";
+ case QtMultimediaKit::VideoBitRate: return "videobitrate";
+ case QtMultimediaKit::Duration: return "duration";
+ case QtMultimediaKit::MediaType: return "contenttype";
+ case QtMultimediaKit::SubTitle:
+ case QtMultimediaKit::Description:
+ case QtMultimediaKit::Category:
+ case QtMultimediaKit::Date:
+ case QtMultimediaKit::UserRating:
+ case QtMultimediaKit::Keywords:
+ case QtMultimediaKit::Language:
+ case QtMultimediaKit::Publisher:
+ case QtMultimediaKit::ParentalRating:
+ case QtMultimediaKit::RatingOrganisation:
+ case QtMultimediaKit::Size:
+ case QtMultimediaKit::AudioCodec:
+ case QtMultimediaKit::AverageLevel:
+ case QtMultimediaKit::ChannelCount:
+ case QtMultimediaKit::PeakValue:
+ case QtMultimediaKit::SampleRate:
+ case QtMultimediaKit::Author:
+ case QtMultimediaKit::ContributingArtist:
+ case QtMultimediaKit::Conductor:
+ case QtMultimediaKit::Lyrics:
+ case QtMultimediaKit::Mood:
+ case QtMultimediaKit::TrackCount:
+ case QtMultimediaKit::CoverArtUrlSmall:
+ case QtMultimediaKit::CoverArtUrlLarge:
+ case QtMultimediaKit::Resolution:
+ case QtMultimediaKit::PixelAspectRatio:
+ case QtMultimediaKit::VideoFrameRate:
+ case QtMultimediaKit::VideoCodec:
+ case QtMultimediaKit::PosterUrl:
+ case QtMultimediaKit::ChapterNumber:
+ case QtMultimediaKit::Director:
+ case QtMultimediaKit::LeadPerformer:
+ case QtMultimediaKit::Writer:
+ case QtMultimediaKit::CameraManufacturer:
+ case QtMultimediaKit::CameraModel:
+ case QtMultimediaKit::Event:
+ case QtMultimediaKit::Subject:
+ default:
+ break;
+ }
+
+ return QString();
+}
diff --git a/tests/auto/qmediaobject/tst_qmediaobject_mmf.h b/tests/auto/qmediaobject/tst_qmediaobject_mmf.h
new file mode 100644
index 000000000..1a381dec8
--- /dev/null
+++ b/tests/auto/qmediaobject/tst_qmediaobject_mmf.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 TST_QMEDIAOBJECT_MMF_H
+#define TST_QMEDIAOBJECT_MMF_H
+
+#include <QtTest/QtTest>
+#include <QtCore>
+#include <QtGui>
+
+#include <qtmedianamespace.h>
+#include <QMediaPlayer>
+#include <QMediaPlayerControl>
+#include <QMediaPlaylist>
+#include <QMediaService>
+#include <QMediaStreamsControl>
+#include <QVideoWidget>
+
+QT_USE_NAMESPACE
+
+class tst_QMediaObject_mmf : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase_data();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void isMetaDataAvailable();
+ void metaData();
+ void availableMetaData();
+ void extendedMetaData();
+ void availableExtendedMetaData();
+
+private:
+ QString metaDataKeyAsString(QtMultimediaKit::MetaData key) const;
+};
+
+#endif // TST_QMEDIAOBJECT_MMF_H
diff --git a/tests/auto/qmediaobject/tst_qmediaobject_xa.cpp b/tests/auto/qmediaobject/tst_qmediaobject_xa.cpp
new file mode 100644
index 000000000..810a414b8
--- /dev/null
+++ b/tests/auto/qmediaobject/tst_qmediaobject_xa.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 "tst_qmediaobject_xa.h"
+
+QT_USE_NAMESPACE
+
+#define WAIT_FOR_CONDITION(a,e) \
+ for (int _i = 0; _i < 500; _i += 1) { \
+ if ((a) == (e)) break; \
+ QTest::qWait(10);}
+
+
+#define WAIT_LONG_FOR_CONDITION(a,e) \
+ for (int _i = 0; _i < 1800; _i += 1) { \
+ if ((a) == (e)) break; \
+ QTest::qWait(100);}
+
+Q_DECLARE_METATYPE(QtMultimediaKit::MetaData)
+
+void tst_QMetadata_xa::initTestCase_data()
+{
+ QTest::addColumn<QMediaContent>("mediaContent");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<QtMultimediaKit::MetaData>("key");
+ QTest::addColumn<qint64>("intValue");
+ QTest::addColumn<QString>("strValue");
+
+ QTest::newRow("testmp3.mp3 - No Metadata")
+ << QMediaContent(QUrl("file:///C:/data/testfiles/test.mp3")) // mediaContent
+ << 0 //count
+ << QtMultimediaKit::Title //key - irrelavant when count 0
+ << qint64(-1) //intValue
+ << QString(); //strValue
+
+ QTest::newRow("JapJap.mp3 - Title")
+ << QMediaContent(QUrl("file:///C:/data/testfiles/JapJap.mp3")) // mediaContent
+ << -1 //count - ignore
+ << QtMultimediaKit::Title //key
+ << qint64(-1) //intValue
+ << QString("JapJap");//strValue
+
+ QTest::newRow("JapJap.mp3 - Artist")
+ << QMediaContent(QUrl("file:///C:/data/testfiles/JapJap.mp3")) // mediaContent
+ << -1 //count - ignore
+ << QtMultimediaKit::AlbumArtist //key
+ << qint64(-1) //intValue
+ << QString("Screaming trees");//strValue
+
+ QTest::newRow("JapJap.mp3 - Album")
+ << QMediaContent(QUrl("file:///C:/data/testfiles/JapJap.mp3")) // mediaContent
+ << -1 //count - ignore
+ << QtMultimediaKit::AlbumTitle //key
+ << qint64(-1) //intValue
+ << QString("Sweet oblivion"); //strValue
+
+ QTest::newRow("JapJap.mp3 - CoverArt")
+ << QMediaContent(QUrl("file:///C:/data/testfiles/JapJap.mp3")) // mediaContent
+ << -1 //count - ignore
+ << QtMultimediaKit::CoverArtImage //key
+ << qint64(28521) //intValue
+ << QString("C:/data/testfiles/JapJapCoverArt.jpeg"); //strValue
+}
+
+void tst_QMetadata_xa::initTestCase()
+{
+ m_player = new QMediaPlayer();
+
+ // Symbian back end needs coecontrol for creation.
+ m_widget = new QVideoWidget();
+ //m_widget->setMediaObject(m_player);
+ m_widget->show();
+ runonce = false;
+}
+
+void tst_QMetadata_xa::cleanupTestCase()
+{
+ delete m_player;
+ delete m_widget;
+}
+
+void tst_QMetadata_xa::init()
+{
+ qRegisterMetaType<QMediaContent>("QMediaContent");
+ qRegisterMetaType<QtMultimediaKit::MetaData>("QtMultimediaKit::MetaData");
+}
+
+void tst_QMetadata_xa::cleanup()
+{
+}
+
+void tst_QMetadata_xa::testMetadata()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(int, count);
+ QFETCH_GLOBAL(QtMultimediaKit::MetaData, key);
+ QFETCH_GLOBAL(QString, strValue);
+ QFETCH_GLOBAL(qint64, intValue);
+
+ QSignalSpy spy(m_player, SIGNAL(metaDataAvailableChanged(bool)));
+ m_player->setMedia(mediaContent);
+
+ WAIT_FOR_CONDITION(spy.count(), 1);
+ //get metadata count
+ QList<QtMultimediaKit::MetaData> mdList = m_player->availableMetaData ();
+ QStringList amdList = m_player->availableExtendedMetaData();
+
+ int numMetadataItems = mdList.size() + amdList.size();
+ if (count>=0) //-1 indicate ignore count
+ QVERIFY(count==numMetadataItems);
+
+ if (numMetadataItems>0 && !strValue.isEmpty()) {
+ QVariant val = m_player->metaData(key);
+
+ if(key == QtMultimediaKit::CoverArtImage)
+ val.value<QImage>().save(strValue);
+ else
+ QVERIFY(strValue == val.toString());
+ }
+}
diff --git a/tests/auto/qmediaobject/tst_qmediaobject_xa.h b/tests/auto/qmediaobject/tst_qmediaobject_xa.h
new file mode 100644
index 000000000..81dc85095
--- /dev/null
+++ b/tests/auto/qmediaobject/tst_qmediaobject_xa.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 TST_QMEDIAOBJECT_XA_H
+#define TST_QMEDIAOBJECT_XA_H
+
+#include <QtTest/QtTest>
+#include <QtCore>
+#include <QtGui>
+
+#include <QMediaPlayer>
+#include <QMediaPlayerControl>
+#include <QMediaPlaylist>
+#include <QMediaService>
+#include <QMediaStreamsControl>
+#include <QVideoWidget>
+
+#include <QList>
+#include <QStringList>
+
+QT_USE_NAMESPACE
+
+class tst_QMetadata_xa: public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase_data();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void testMetadata();
+
+
+private:
+ void displayImage(QImage);
+ QMediaPlayer *m_player;
+ QVideoWidget *m_widget;
+ bool runonce;
+};
+
+#endif //TST_QMEDIAOBJECT_XA_H
diff --git a/tests/auto/qmediaplayer/main.cpp b/tests/auto/qmediaplayer/main.cpp
new file mode 100755
index 000000000..b4dd5c470
--- /dev/null
+++ b/tests/auto/qmediaplayer/main.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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.h>
+#include <QtTest/QtTest>
+
+#include "tst_qmediaplayer.h"
+
+#ifdef Q_OS_SYMBIAN
+#include "tst_qmediaplayer_xa.h"
+#include "tst_qmediaplayer_s60.h"
+#endif
+
+int main(int argc, char**argv)
+{
+ QApplication app(argc,argv);
+ int ret;
+ tst_QMediaPlayer test_api;
+ ret = QTest::qExec(&test_api, argc, argv);
+#ifdef Q_OS_SYMBIAN
+ char *new_argv[3];
+ QString str = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_s60.log";
+ QByteArray bytes = str.toAscii();
+ char arg1[] = "-o";
+ new_argv[0] = argv[0];
+ new_argv[1] = arg1;
+ new_argv[2] = bytes.data();
+ tst_QMediaPlayer_xa test_xa;
+ ret = QTest::qExec(&test_xa, 3, new_argv);
+ char *new_argv1[3];
+ QString str1 = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_s60.log";
+ QByteArray bytes1 = str1.toAscii();
+ char arg2[] = "-o";
+ new_argv1[0] = argv[0];
+ new_argv1[1] = arg2;
+ new_argv1[2] = bytes1.data();
+ tst_QMediaPlayer_s60 test_s60;
+ ret = QTest::qExec(&test_s60, 3, new_argv1);
+#endif
+ return ret;
+}
diff --git a/tests/auto/qmediaplayer/qmediaplayer.pro b/tests/auto/qmediaplayer/qmediaplayer.pro
new file mode 100644
index 000000000..b624afd91
--- /dev/null
+++ b/tests/auto/qmediaplayer/qmediaplayer.pro
@@ -0,0 +1,25 @@
+load(qttest_p4)
+
+QT += network multimediakit-private
+
+# TARGET = tst_qmediaplayer
+# CONFIG += testcase
+
+symbian {
+ TARGET.CAPABILITY = NetworkServices
+ testFiles.sources = testfiles/*
+ testFiles.path = /Data/testfiles
+ DEPLOYMENT += testFiles
+ contains(openmaxal_symbian_enabled, no) {
+ DEFINES += HAS_OPENMAXAL_MEDIAPLAY_BACKEND
+ HEADERS += tst_qmediaplayer_xa.h
+ SOURCES += tst_qmediaplayer_xa.cpp
+ } else {
+ HEADERS += tst_qmediaplayer_s60.h
+ SOURCES += tst_qmediaplayer_s60.cpp
+ }
+}
+
+HEADERS += tst_qmediaplayer.h
+SOURCES += main.cpp tst_qmediaplayer.cpp
+
diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer.cpp b/tests/auto/qmediaplayer/tst_qmediaplayer.cpp
new file mode 100644
index 000000000..4cef0e354
--- /dev/null
+++ b/tests/auto/qmediaplayer/tst_qmediaplayer.cpp
@@ -0,0 +1,1019 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include "tst_qmediaplayer.h"
+
+#include <qgraphicsvideoitem.h>
+#include <QtNetwork/qnetworkconfigmanager.h>
+
+// Encouraging successful diversity through copy and paste.
+#ifndef QTRY_COMPARE
+#define QTRY_COMPARE(__expr, __expected) \
+ do { \
+ const int __step = 50; \
+ const int __timeout = 5000; \
+ if ((__expr) != (__expected)) { \
+ QTest::qWait(0); \
+ } \
+ for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \
+ QTest::qWait(__step); \
+ } \
+ QCOMPARE(__expr, __expected); \
+ } while(0)
+#endif
+
+#ifndef QTRY_VERIFY
+#define QTRY_VERIFY(__expr) \
+ do { \
+ const int __step = 50; \
+ const int __timeout = 5000; \
+ if (!(__expr)) { \
+ QTest::qWait(0); \
+ } \
+ for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \
+ QTest::qWait(__step); \
+ } \
+ QVERIFY(__expr); \
+ } while(0)
+#endif
+
+QT_USE_NAMESPACE
+
+void tst_QMediaPlayer::initTestCase_data()
+{
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<QMediaPlayer::State>("state");
+ QTest::addColumn<QMediaPlayer::MediaStatus>("status");
+ QTest::addColumn<QMediaContent>("mediaContent");
+ QTest::addColumn<qint64>("duration");
+ QTest::addColumn<qint64>("position");
+ QTest::addColumn<bool>("seekable");
+ QTest::addColumn<int>("volume");
+ QTest::addColumn<bool>("muted");
+ QTest::addColumn<bool>("videoAvailable");
+ QTest::addColumn<int>("bufferStatus");
+ QTest::addColumn<qreal>("playbackRate");
+ QTest::addColumn<QMediaPlayer::Error>("error");
+ QTest::addColumn<QString>("errorString");
+
+ QTest::newRow("invalid") << false << QMediaPlayer::StoppedState << QMediaPlayer::UnknownMediaStatus <<
+ QMediaContent() << qint64(0) << qint64(0) << false << 0 << false << false << 0 <<
+ qreal(0) << QMediaPlayer::NoError << QString();
+ QTest::newRow("valid+null") << true << QMediaPlayer::StoppedState << QMediaPlayer::UnknownMediaStatus <<
+ QMediaContent() << qint64(0) << qint64(0) << false << 0 << false << false << 50 <<
+ qreal(0) << QMediaPlayer::NoError << QString();
+ QTest::newRow("valid+content+stopped") << true << QMediaPlayer::StoppedState << QMediaPlayer::UnknownMediaStatus <<
+ QMediaContent(QUrl("file:///some.mp3")) << qint64(0) << qint64(0) << false << 50 << false << false << 0 <<
+ qreal(1) << QMediaPlayer::NoError << QString();
+ QTest::newRow("valid+content+playing") << true << QMediaPlayer::PlayingState << QMediaPlayer::LoadedMedia <<
+ QMediaContent(QUrl("file:///some.mp3")) << qint64(10000) << qint64(10) << true << 50 << true << false << 0 <<
+ qreal(1) << QMediaPlayer::NoError << QString();
+ QTest::newRow("valid+content+paused") << true << QMediaPlayer::PausedState << QMediaPlayer::LoadedMedia <<
+ QMediaContent(QUrl("file:///some.mp3")) << qint64(10000) << qint64(10) << true << 50 << true << false << 0 <<
+ qreal(1) << QMediaPlayer::NoError << QString();
+ QTest::newRow("valud+streaming") << true << QMediaPlayer::PlayingState << QMediaPlayer::LoadedMedia <<
+ QMediaContent(QUrl("http://example.com/stream")) << qint64(10000) << qint64(10000) << false << 50 << false << true << 0 <<
+ qreal(1) << QMediaPlayer::NoError << QString();
+ QTest::newRow("valid+error") << true << QMediaPlayer::StoppedState << QMediaPlayer::UnknownMediaStatus <<
+ QMediaContent(QUrl("http://example.com/stream")) << qint64(0) << qint64(0) << false << 50 << false << false << 0 <<
+ qreal(0) << QMediaPlayer::ResourceError << QString("Resource unavailable");
+}
+
+void tst_QMediaPlayer::initTestCase()
+{
+ qRegisterMetaType<QMediaPlayer::State>("QMediaPlayer::State");
+ qRegisterMetaType<QMediaPlayer::Error>("QMediaPlayer::Error");
+ qRegisterMetaType<QMediaPlayer::MediaStatus>("QMediaPlayer::MediaStatus");
+ qRegisterMetaType<QMediaContent>("QMediaContent");
+
+ mockService = new MockPlayerService;
+ mockProvider = new MockProvider(mockService);
+ player = new QMediaPlayer(0, 0, mockProvider);
+}
+
+void tst_QMediaPlayer::cleanupTestCase()
+{
+ delete player;
+}
+
+void tst_QMediaPlayer::init()
+{
+ mockService->reset();
+}
+
+void tst_QMediaPlayer::cleanup()
+{
+}
+
+void tst_QMediaPlayer::testNullService()
+{
+ MockProvider provider(0);
+ QMediaPlayer player(0, 0, &provider);
+
+ const QIODevice *nullDevice = 0;
+
+ QCOMPARE(player.media(), QMediaContent());
+ QCOMPARE(player.mediaStream(), nullDevice);
+ QCOMPARE(player.state(), QMediaPlayer::StoppedState);
+ QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus);
+ QCOMPARE(player.duration(), qint64(-1));
+ QCOMPARE(player.position(), qint64(0));
+ QCOMPARE(player.volume(), 0);
+ QCOMPARE(player.isMuted(), false);
+ QCOMPARE(player.isVideoAvailable(), false);
+ QCOMPARE(player.bufferStatus(), 0);
+ QCOMPARE(player.isSeekable(), false);
+ QCOMPARE(player.playbackRate(), qreal(0));
+ QCOMPARE(player.error(), QMediaPlayer::ServiceMissingError);
+ QCOMPARE(player.isAvailable(), false);
+ QCOMPARE(player.availabilityError(), QtMultimediaKit::ServiceMissingError);
+
+ {
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+
+ QSignalSpy spy(&player, SIGNAL(mediaChanged(QMediaContent)));
+ QFile file;
+
+ player.setMedia(mediaContent, &file);
+ QCOMPARE(player.media(), QMediaContent());
+ QCOMPARE(player.mediaStream(), nullDevice);
+ QCOMPARE(spy.count(), 0);
+ } {
+ QSignalSpy stateSpy(&player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+
+ player.play();
+ QCOMPARE(player.state(), QMediaPlayer::StoppedState);
+ QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus);
+ QCOMPARE(stateSpy.count(), 0);
+ QCOMPARE(statusSpy.count(), 0);
+
+ player.pause();
+ QCOMPARE(player.state(), QMediaPlayer::StoppedState);
+ QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus);
+ QCOMPARE(stateSpy.count(), 0);
+ QCOMPARE(statusSpy.count(), 0);
+
+ player.stop();
+ QCOMPARE(player.state(), QMediaPlayer::StoppedState);
+ QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus);
+ QCOMPARE(stateSpy.count(), 0);
+ QCOMPARE(statusSpy.count(), 0);
+ } {
+ QFETCH_GLOBAL(int, volume);
+ QFETCH_GLOBAL(bool, muted);
+
+ QSignalSpy volumeSpy(&player, SIGNAL(volumeChanged(int)));
+ QSignalSpy mutingSpy(&player, SIGNAL(mutedChanged(bool)));
+
+ player.setVolume(volume);
+ QCOMPARE(player.volume(), 0);
+ QCOMPARE(volumeSpy.count(), 0);
+
+ player.setMuted(muted);
+ QCOMPARE(player.isMuted(), false);
+ QCOMPARE(mutingSpy.count(), 0);
+ } {
+ QFETCH_GLOBAL(qint64, position);
+
+ QSignalSpy spy(&player, SIGNAL(positionChanged(qint64)));
+
+ player.setPosition(position);
+ QCOMPARE(player.position(), qint64(0));
+ QCOMPARE(spy.count(), 0);
+ } {
+ QFETCH_GLOBAL(qreal, playbackRate);
+
+ QSignalSpy spy(&player, SIGNAL(playbackRateChanged(qreal)));
+
+ player.setPlaybackRate(playbackRate);
+ QCOMPARE(player.playbackRate(), qreal(0));
+ QCOMPARE(spy.count(), 0);
+ } {
+ QMediaPlaylist playlist;
+ player.setPlaylist(&playlist);
+
+ QSignalSpy mediaSpy(&player, SIGNAL(mediaChanged(QMediaContent)));
+ QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+
+ playlist.addMedia(QUrl("http://example.com/stream"));
+ playlist.addMedia(QUrl("file:///some.mp3"));
+
+ playlist.setCurrentIndex(0);
+ QCOMPARE(playlist.currentIndex(), 0);
+ QCOMPARE(player.media(), QMediaContent());
+ QCOMPARE(mediaSpy.count(), 0);
+ QCOMPARE(statusSpy.count(), 0);
+
+ playlist.next();
+ QCOMPARE(playlist.currentIndex(), 1);
+ QCOMPARE(player.media(), QMediaContent());
+ QCOMPARE(mediaSpy.count(), 0);
+ QCOMPARE(statusSpy.count(), 0);
+ }
+}
+
+void tst_QMediaPlayer::testValid()
+{
+ /*
+ QFETCH_GLOBAL(bool, valid);
+
+ mockService->setIsValid(valid);
+ QCOMPARE(player->isValid(), valid);
+ */
+}
+
+void tst_QMediaPlayer::testMedia()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+
+ mockService->setMedia(mediaContent);
+ QCOMPARE(player->media(), mediaContent);
+
+ QBuffer stream;
+ player->setMedia(mediaContent, &stream);
+ QCOMPARE(player->media(), mediaContent);
+ QCOMPARE((QBuffer*)player->mediaStream(), &stream);
+}
+
+void tst_QMediaPlayer::testDuration()
+{
+ QFETCH_GLOBAL(qint64, duration);
+
+ mockService->setDuration(duration);
+ QVERIFY(player->duration() == duration);
+}
+
+void tst_QMediaPlayer::testPosition()
+{
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(bool, seekable);
+ QFETCH_GLOBAL(qint64, position);
+ QFETCH_GLOBAL(qint64, duration);
+
+ mockService->setIsValid(valid);
+ mockService->setSeekable(seekable);
+ mockService->setPosition(position);
+ mockService->setDuration(duration);
+ QVERIFY(player->isSeekable() == seekable);
+ QVERIFY(player->position() == position);
+ QVERIFY(player->duration() == duration);
+
+ if (seekable) {
+ { QSignalSpy spy(player, SIGNAL(positionChanged(qint64)));
+ player->setPosition(position);
+ QCOMPARE(player->position(), position);
+ QCOMPARE(spy.count(), 0); }
+
+ mockService->setPosition(position);
+ { QSignalSpy spy(player, SIGNAL(positionChanged(qint64)));
+ player->setPosition(0);
+ QCOMPARE(player->position(), qint64(0));
+ QCOMPARE(spy.count(), position == 0 ? 0 : 1); }
+
+ mockService->setPosition(position);
+ { QSignalSpy spy(player, SIGNAL(positionChanged(qint64)));
+ player->setPosition(duration);
+ QCOMPARE(player->position(), duration);
+ QCOMPARE(spy.count(), position == duration ? 0 : 1); }
+
+ mockService->setPosition(position);
+ { QSignalSpy spy(player, SIGNAL(positionChanged(qint64)));
+ player->setPosition(-1);
+ QCOMPARE(player->position(), qint64(0));
+ QCOMPARE(spy.count(), position == 0 ? 0 : 1); }
+
+ mockService->setPosition(position);
+ { QSignalSpy spy(player, SIGNAL(positionChanged(qint64)));
+ player->setPosition(duration + 1);
+ QCOMPARE(player->position(), duration);
+ QCOMPARE(spy.count(), position == duration ? 0 : 1); }
+ }
+ else {
+ QSignalSpy spy(player, SIGNAL(positionChanged(qint64)));
+ player->setPosition(position);
+
+ QCOMPARE(player->position(), position);
+ QCOMPARE(spy.count(), 0);
+ }
+}
+
+void tst_QMediaPlayer::testVolume()
+{
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(int, volume);
+
+ mockService->setVolume(volume);
+ QVERIFY(player->volume() == volume);
+
+ if (valid) {
+ { QSignalSpy spy(player, SIGNAL(volumeChanged(int)));
+ player->setVolume(10);
+ QCOMPARE(player->volume(), 10);
+ QCOMPARE(spy.count(), 1); }
+
+ { QSignalSpy spy(player, SIGNAL(volumeChanged(int)));
+ player->setVolume(-1000);
+ QCOMPARE(player->volume(), 0);
+ QCOMPARE(spy.count(), 1); }
+
+ { QSignalSpy spy(player, SIGNAL(volumeChanged(int)));
+ player->setVolume(100);
+ QCOMPARE(player->volume(), 100);
+ QCOMPARE(spy.count(), 1); }
+
+ { QSignalSpy spy(player, SIGNAL(volumeChanged(int)));
+ player->setVolume(1000);
+ QCOMPARE(player->volume(), 100);
+ QCOMPARE(spy.count(), 0); }
+ }
+}
+
+void tst_QMediaPlayer::testMuted()
+{
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(bool, muted);
+ QFETCH_GLOBAL(int, volume);
+
+ if (valid) {
+ mockService->setMuted(muted);
+ mockService->setVolume(volume);
+ QVERIFY(player->isMuted() == muted);
+
+ QSignalSpy spy(player, SIGNAL(mutedChanged(bool)));
+ player->setMuted(!muted);
+ QCOMPARE(player->isMuted(), !muted);
+ QCOMPARE(player->volume(), volume);
+ QCOMPARE(spy.count(), 1);
+ }
+}
+
+void tst_QMediaPlayer::testVideoAvailable()
+{
+ QFETCH_GLOBAL(bool, videoAvailable);
+
+ mockService->setVideoAvailable(videoAvailable);
+ QVERIFY(player->isVideoAvailable() == videoAvailable);
+}
+
+void tst_QMediaPlayer::testBufferStatus()
+{
+ QFETCH_GLOBAL(int, bufferStatus);
+
+ mockService->setBufferStatus(bufferStatus);
+ QVERIFY(player->bufferStatus() == bufferStatus);
+}
+
+void tst_QMediaPlayer::testSeekable()
+{
+ QFETCH_GLOBAL(bool, seekable);
+
+ mockService->setSeekable(seekable);
+ QVERIFY(player->isSeekable() == seekable);
+}
+
+void tst_QMediaPlayer::testPlaybackRate()
+{
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(qreal, playbackRate);
+
+ if (valid) {
+ mockService->setPlaybackRate(playbackRate);
+ QVERIFY(player->playbackRate() == playbackRate);
+
+ QSignalSpy spy(player, SIGNAL(playbackRateChanged(qreal)));
+ player->setPlaybackRate(playbackRate + 0.5f);
+ QCOMPARE(player->playbackRate(), playbackRate + 0.5f);
+ QCOMPARE(spy.count(), 1);
+ }
+}
+
+void tst_QMediaPlayer::testError()
+{
+ QFETCH_GLOBAL(QMediaPlayer::Error, error);
+
+ mockService->setError(error);
+ QVERIFY(player->error() == error);
+}
+
+void tst_QMediaPlayer::testErrorString()
+{
+ QFETCH_GLOBAL(QString, errorString);
+
+ mockService->setErrorString(errorString);
+ QVERIFY(player->errorString() == errorString);
+}
+
+void tst_QMediaPlayer::testIsAvailable()
+{
+ QCOMPARE(player->isAvailable(), true);
+ QCOMPARE(player->availabilityError(), QtMultimediaKit::NoError);
+}
+
+void tst_QMediaPlayer::testService()
+{
+ /*
+ QFETCH_GLOBAL(bool, valid);
+
+ mockService->setIsValid(valid);
+
+ if (valid)
+ QVERIFY(player->service() != 0);
+ else
+ QVERIFY(player->service() == 0);
+ */
+}
+
+void tst_QMediaPlayer::testPlay()
+{
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(QMediaPlayer::State, state);
+
+ mockService->setIsValid(valid);
+ mockService->setState(state);
+ mockService->setMedia(mediaContent);
+ QVERIFY(player->state() == state);
+ QVERIFY(player->media() == mediaContent);
+
+ QSignalSpy spy(player, SIGNAL(stateChanged(QMediaPlayer::State)));
+
+ player->play();
+
+ if (!valid || mediaContent.isNull()) {
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(spy.count(), 0);
+ }
+ else {
+ QCOMPARE(player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(spy.count(), state == QMediaPlayer::PlayingState ? 0 : 1);
+ }
+}
+
+void tst_QMediaPlayer::testPause()
+{
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(QMediaPlayer::State, state);
+
+ mockService->setIsValid(valid);
+ mockService->setState(state);
+ mockService->setMedia(mediaContent);
+ QVERIFY(player->state() == state);
+ QVERIFY(player->media() == mediaContent);
+
+ QSignalSpy spy(player, SIGNAL(stateChanged(QMediaPlayer::State)));
+
+ player->pause();
+
+ if (!valid || mediaContent.isNull()) {
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(spy.count(), 0);
+ }
+ else {
+ QCOMPARE(player->state(), QMediaPlayer::PausedState);
+ QCOMPARE(spy.count(), state == QMediaPlayer::PausedState ? 0 : 1);
+ }
+}
+
+void tst_QMediaPlayer::testStop()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(QMediaPlayer::State, state);
+
+ mockService->setState(state);
+ mockService->setMedia(mediaContent);
+ QVERIFY(player->state() == state);
+ QVERIFY(player->media() == mediaContent);
+
+ QSignalSpy spy(player, SIGNAL(stateChanged(QMediaPlayer::State)));
+
+ player->stop();
+
+ if (mediaContent.isNull() || state == QMediaPlayer::StoppedState) {
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(spy.count(), 0);
+ }
+ else {
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(spy.count(), 1);
+ }
+}
+
+void tst_QMediaPlayer::testMediaStatus()
+{
+ QFETCH_GLOBAL(int, bufferStatus);
+ int bufferSignals = 0;
+
+ player->setNotifyInterval(10);
+
+ mockService->setMediaStatus(QMediaPlayer::NoMedia);
+ mockService->setBufferStatus(bufferStatus);
+
+ AutoConnection connection(
+ player, SIGNAL(bufferStatusChanged(int)),
+ &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QSignalSpy statusSpy(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ QSignalSpy bufferSpy(player, SIGNAL(bufferStatusChanged(int)));
+
+ QCOMPARE(player->mediaStatus(), QMediaPlayer::NoMedia);
+
+ mockService->setMediaStatus(QMediaPlayer::LoadingMedia);
+ QCOMPARE(player->mediaStatus(), QMediaPlayer::LoadingMedia);
+ QCOMPARE(statusSpy.count(), 1);
+
+ QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(statusSpy.last().value(0)),
+ QMediaPlayer::LoadingMedia);
+
+ mockService->setMediaStatus(QMediaPlayer::LoadedMedia);
+ QCOMPARE(player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(statusSpy.count(), 2);
+
+ QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(statusSpy.last().value(0)),
+ QMediaPlayer::LoadedMedia);
+
+ // Verify the bufferStatusChanged() signal isn't being emitted.
+ QTestEventLoop::instance().enterLoop(1);
+ QCOMPARE(bufferSpy.count(), 0);
+
+ mockService->setMediaStatus(QMediaPlayer::StalledMedia);
+ QCOMPARE(player->mediaStatus(), QMediaPlayer::StalledMedia);
+ QCOMPARE(statusSpy.count(), 3);
+
+ QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(statusSpy.last().value(0)),
+ QMediaPlayer::StalledMedia);
+
+ // Verify the bufferStatusChanged() signal is being emitted.
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(bufferSpy.count() > bufferSignals);
+ QCOMPARE(bufferSpy.last().value(0).toInt(), bufferStatus);
+ bufferSignals = bufferSpy.count();
+
+ mockService->setMediaStatus(QMediaPlayer::BufferingMedia);
+ QCOMPARE(player->mediaStatus(), QMediaPlayer::BufferingMedia);
+ QCOMPARE(statusSpy.count(), 4);
+
+ QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(statusSpy.last().value(0)),
+ QMediaPlayer::BufferingMedia);
+
+ // Verify the bufferStatusChanged() signal is being emitted.
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(bufferSpy.count() > bufferSignals);
+ QCOMPARE(bufferSpy.last().value(0).toInt(), bufferStatus);
+ bufferSignals = bufferSpy.count();
+
+ mockService->setMediaStatus(QMediaPlayer::BufferedMedia);
+ QCOMPARE(player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(statusSpy.count(), 5);
+
+ QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(statusSpy.last().value(0)),
+ QMediaPlayer::BufferedMedia);
+
+ // Verify the bufferStatusChanged() signal isn't being emitted.
+ QTestEventLoop::instance().enterLoop(1);
+ QCOMPARE(bufferSpy.count(), bufferSignals);
+
+ mockService->setMediaStatus(QMediaPlayer::EndOfMedia);
+ QCOMPARE(player->mediaStatus(), QMediaPlayer::EndOfMedia);
+ QCOMPARE(statusSpy.count(), 6);
+
+ QCOMPARE(qvariant_cast<QMediaPlayer::MediaStatus>(statusSpy.last().value(0)),
+ QMediaPlayer::EndOfMedia);
+}
+
+void tst_QMediaPlayer::testPlaylist()
+{
+ QMediaContent content0(QUrl(QLatin1String("test://audio/song1.mp3")));
+ QMediaContent content1(QUrl(QLatin1String("test://audio/song2.mp3")));
+ QMediaContent content2(QUrl(QLatin1String("test://video/movie1.mp4")));
+ QMediaContent content3(QUrl(QLatin1String("test://video/movie2.mp4")));
+ QMediaContent content4(QUrl(QLatin1String("test://image/photo.jpg")));
+
+ mockService->setIsValid(true);
+ mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::NoMedia);
+
+ QMediaPlaylist *playlist = new QMediaPlaylist;
+ player->setPlaylist(playlist);
+
+ QSignalSpy stateSpy(player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ QSignalSpy mediaSpy(player, SIGNAL(mediaChanged(QMediaContent)));
+
+ // Test the player does nothing with an empty playlist attached.
+ player->play();
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(player->media(), QMediaContent());
+ QCOMPARE(stateSpy.count(), 0);
+ QCOMPARE(mediaSpy.count(), 0);
+
+ playlist->addMedia(content0);
+ playlist->addMedia(content1);
+ playlist->addMedia(content2);
+ playlist->addMedia(content3);
+
+ // Test changing the playlist position, changes the current media, but not the playing state.
+ playlist->setCurrentIndex(1);
+ QCOMPARE(player->media(), content1);
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.count(), 0);
+ QCOMPARE(mediaSpy.count(), 1);
+
+ // Test playing starts with the current media.
+ player->play();
+ QCOMPARE(player->media(), content1);
+ QCOMPARE(player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 1);
+ QCOMPARE(mediaSpy.count(), 1);
+
+ // Test pausing doesn't change the current media.
+ player->pause();
+ QCOMPARE(player->media(), content1);
+ QCOMPARE(player->state(), QMediaPlayer::PausedState);
+ QCOMPARE(stateSpy.count(), 2);
+ QCOMPARE(mediaSpy.count(), 1);
+
+ // Test stopping doesn't change the current media.
+ player->stop();
+ QCOMPARE(player->media(), content1);
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.count(), 3);
+ QCOMPARE(mediaSpy.count(), 1);
+
+ // Test when the player service reaches the end of the current media, the player moves onto
+ // the next item without stopping.
+ player->play();
+ QCOMPARE(player->media(), content1);
+ QCOMPARE(player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 4);
+ QCOMPARE(mediaSpy.count(), 1);
+
+ mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::EndOfMedia);
+ QCOMPARE(player->media(), content2);
+ QCOMPARE(player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 4);
+ QCOMPARE(mediaSpy.count(), 2);
+
+ // Test skipping the current media doesn't change the state.
+ playlist->next();
+ QCOMPARE(player->media(), content3);
+ QCOMPARE(player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 4);
+ QCOMPARE(mediaSpy.count(), 3);
+
+ // Test changing the current media while paused doesn't change the state.
+ player->pause();
+ mockService->setMediaStatus(QMediaPlayer::BufferedMedia);
+ QCOMPARE(player->media(), content3);
+ QCOMPARE(player->state(), QMediaPlayer::PausedState);
+ QCOMPARE(stateSpy.count(), 5);
+ QCOMPARE(mediaSpy.count(), 3);
+
+ playlist->previous();
+ QCOMPARE(player->media(), content2);
+ QCOMPARE(player->state(), QMediaPlayer::PausedState);
+ QCOMPARE(stateSpy.count(), 5);
+ QCOMPARE(mediaSpy.count(), 4);
+
+ // Test changing the current media while stopped doesn't change the state.
+ player->stop();
+ mockService->setMediaStatus(QMediaPlayer::LoadedMedia);
+ QCOMPARE(player->media(), content2);
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.count(), 6);
+ QCOMPARE(mediaSpy.count(), 4);
+
+ playlist->next();
+ QCOMPARE(player->media(), content3);
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.count(), 6);
+ QCOMPARE(mediaSpy.count(), 5);
+
+ // Test the player is stopped and the current media cleared when it reaches the end of the last
+ // item in the playlist.
+ player->play();
+ QCOMPARE(player->media(), content3);
+ QCOMPARE(player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 7);
+ QCOMPARE(mediaSpy.count(), 5);
+
+ // Double up the signals to ensure some noise doesn't destabalize things.
+ mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::EndOfMedia);
+ mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::EndOfMedia);
+ QCOMPARE(player->media(), QMediaContent());
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.count(), 8);
+ QCOMPARE(mediaSpy.count(), 6);
+
+ // Test starts playing from the start of the playlist if there is no current media selected.
+ player->play();
+ QCOMPARE(player->media(), content0);
+ QCOMPARE(player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 9);
+ QCOMPARE(mediaSpy.count(), 7);
+
+ // Test deleting the playlist stops the player and clears the media it set.
+ delete playlist;
+ QCOMPARE(player->media(), QMediaContent());
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.count(), 10);
+ QCOMPARE(mediaSpy.count(), 8);
+
+ // Test the player works as normal with the playlist removed.
+ player->play();
+ QCOMPARE(player->media(), QMediaContent());
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.count(), 10);
+ QCOMPARE(mediaSpy.count(), 8);
+
+ player->setMedia(content1);
+ player->play();
+
+ QCOMPARE(player->media(), content1);
+ QCOMPARE(player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 11);
+ QCOMPARE(mediaSpy.count(), 9);
+
+ // Test the player can bind to playlist again
+ playlist = new QMediaPlaylist;
+ player->setPlaylist(playlist);
+
+ QCOMPARE(player->media(), QMediaContent());
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+
+ playlist->addMedia(content0);
+ playlist->addMedia(content1);
+ playlist->addMedia(content2);
+ playlist->addMedia(content3);
+
+ playlist->setCurrentIndex(1);
+ QCOMPARE(player->media(), content1);
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+
+ // Test attaching the new playlist,
+ // player should detach the current one
+ QMediaPlaylist *playlist2 = new QMediaPlaylist;
+ playlist2->addMedia(content1);
+ playlist2->addMedia(content2);
+ playlist2->addMedia(content3);
+ playlist2->setCurrentIndex(2);
+
+ player->play();
+ player->setPlaylist(playlist2);
+ QCOMPARE(player->media(), playlist2->currentMedia());
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+
+ playlist2->setCurrentIndex(1);
+ QCOMPARE(player->media(), playlist2->currentMedia());
+
+ {
+ QMediaPlaylist playlist;
+ playlist.addMedia(content1);
+ playlist.addMedia(content2);
+ playlist.addMedia(content3);
+ playlist.setCurrentIndex(1);
+
+ player->setPlaylist(&playlist);
+ QCOMPARE(player->playlist(), &playlist);
+ QCOMPARE(player->media(), content2);
+ } //playlist should be detached now
+
+ QVERIFY(player->playlist() == 0);
+ QCOMPARE(player->media(), QMediaContent());
+
+ // Test when the player service encounters an invalid media, the player moves onto
+ // the next item without stopping
+ {
+ QSignalSpy ss(player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ QSignalSpy ms(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+
+ player->setPlaylist(playlist);
+ player->play();
+ QCOMPARE(ss.count(), 1);
+
+ mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::InvalidMedia);
+ QCOMPARE(player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(player->mediaStatus(), QMediaPlayer::InvalidMedia);
+ QCOMPARE(ss.count(), 1);
+ QCOMPARE(ms.count(), 1);
+
+ // NOTE: status should begin transitioning through to BufferedMedia.
+ QCOMPARE(player->media(), content2);
+ }
+
+}
+
+void tst_QMediaPlayer::testNetworkAccess()
+{
+ QNetworkConfigurationManager manager;
+ QList<QNetworkConfiguration> configs = manager.allConfigurations();
+
+ if (configs.count() >= 1) {
+ QSignalSpy spy(player, SIGNAL(networkConfigurationChanged(QNetworkConfiguration)));
+ int index = qFloor((configs.count())/2);
+ player->setNetworkConfigurations(configs);
+ mockService->selectCurrentConfiguration(configs.at(index));
+
+ QVERIFY(spy.count() == 1);
+ QList<QVariant> args = spy.takeFirst();
+ QNetworkConfiguration config = args.at(0).value<QNetworkConfiguration>();
+ QCOMPARE(config.identifier() , configs.at(index).identifier());
+ QCOMPARE(player->currentNetworkConfiguration().identifier() , config.identifier());
+ }
+
+ // invalidate current network configuration
+ QSignalSpy spy(player, SIGNAL(networkConfigurationChanged(QNetworkConfiguration)));
+ mockService->selectCurrentConfiguration(QNetworkConfiguration());
+ QVERIFY(spy.count() == 1);
+ QList<QVariant> args = spy.takeFirst();
+ QNetworkConfiguration config = args.at(0).value<QNetworkConfiguration>();
+ QVERIFY(config.isValid() == false);
+ QVERIFY(player->currentNetworkConfiguration().isValid() == false);
+}
+
+void tst_QMediaPlayer::testSetVideoOutput()
+{
+ QVideoWidget widget;
+ QGraphicsVideoItem item;
+ MockVideoSurface surface;
+
+ MockPlayerService service;
+ MockProvider provider(&service);
+ provider.deleteServiceOnRelease = false;
+ QMediaPlayer player(0, 0, &provider);
+
+ player.setVideoOutput(&widget);
+ QVERIFY(widget.mediaObject() == &player);
+
+ player.setVideoOutput(&item);
+ QVERIFY(widget.mediaObject() == 0);
+ QVERIFY(item.mediaObject() == &player);
+
+ player.setVideoOutput(reinterpret_cast<QVideoWidget *>(0));
+ QVERIFY(item.mediaObject() == 0);
+
+ player.setVideoOutput(&widget);
+ QVERIFY(widget.mediaObject() == &player);
+
+ player.setVideoOutput(reinterpret_cast<QGraphicsVideoItem *>(0));
+ QVERIFY(widget.mediaObject() == 0);
+
+ player.setVideoOutput(&surface);
+ QVERIFY(service.rendererControl->surface() == &surface);
+
+ player.setVideoOutput(reinterpret_cast<QAbstractVideoSurface *>(0));
+ QVERIFY(service.rendererControl->surface() == 0);
+
+ player.setVideoOutput(&surface);
+ QVERIFY(service.rendererControl->surface() == &surface);
+
+ player.setVideoOutput(&widget);
+ QVERIFY(service.rendererControl->surface() == 0);
+ QVERIFY(widget.mediaObject() == &player);
+
+ player.setVideoOutput(&surface);
+ QVERIFY(service.rendererControl->surface() == &surface);
+ QVERIFY(widget.mediaObject() == 0);
+}
+
+
+void tst_QMediaPlayer::testSetVideoOutputNoService()
+{
+ QVideoWidget widget;
+ QGraphicsVideoItem item;
+ MockVideoSurface surface;
+
+ MockProvider provider(0);
+ QMediaPlayer player(0, 0, &provider);
+
+ player.setVideoOutput(&widget);
+ QVERIFY(widget.mediaObject() == 0);
+
+ player.setVideoOutput(&item);
+ QVERIFY(item.mediaObject() == 0);
+
+ player.setVideoOutput(&surface);
+ // Nothing we can verify here other than it doesn't assert.
+}
+
+void tst_QMediaPlayer::testSetVideoOutputNoControl()
+{
+ QVideoWidget widget;
+ QGraphicsVideoItem item;
+ MockVideoSurface surface;
+
+ MockPlayerService service;
+ service.rendererRef = 1;
+ service.windowRef = 1;
+
+ MockProvider provider(&service);
+ provider.deleteServiceOnRelease = false;
+ QMediaPlayer player(0, 0, &provider);
+
+ player.setVideoOutput(&widget);
+ QVERIFY(widget.mediaObject() == 0);
+
+ player.setVideoOutput(&item);
+ QVERIFY(item.mediaObject() == 0);
+
+ player.setVideoOutput(&surface);
+ QVERIFY(service.rendererControl->surface() == 0);
+}
+
+void tst_QMediaPlayer::testSetVideoOutputDestruction()
+{
+ MockVideoSurface surface;
+
+ MockPlayerService service;
+ MockProvider provider(&service);
+ provider.deleteServiceOnRelease = false;
+
+ {
+ QMediaPlayer player(0, 0, &provider);
+ player.setVideoOutput(&surface);
+ QVERIFY(service.rendererControl->surface() == &surface);
+ QCOMPARE(service.rendererRef, 1);
+ }
+ QVERIFY(service.rendererControl->surface() == 0);
+ QCOMPARE(service.rendererRef, 0);
+}
+
+void tst_QMediaPlayer::testPositionPropertyWatch()
+{
+ QMediaContent content0(QUrl(QLatin1String("test://audio/song1.mp3")));
+ QMediaContent content1(QUrl(QLatin1String("test://audio/song2.mp3")));
+
+ mockService->setIsValid(true);
+ mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::NoMedia);
+
+ QMediaPlaylist *playlist = new QMediaPlaylist;
+
+ playlist->addMedia(content0);
+ playlist->addMedia(content1);
+
+ player->setPlaylist(playlist);
+ player->setNotifyInterval(5);
+
+ player->play();
+ QSignalSpy positionSpy(player, SIGNAL(positionChanged(qint64)));
+ playlist->next();
+ QCOMPARE(player->state(), QMediaPlayer::PlayingState);
+ QTRY_VERIFY(positionSpy.count() > 0);
+
+ playlist->next();
+ QCOMPARE(player->state(), QMediaPlayer::StoppedState);
+
+ positionSpy.clear();
+ QTRY_COMPARE(positionSpy.count(), 0);
+}
+
+void tst_QMediaPlayer::debugEnums()
+{
+ QTest::ignoreMessage(QtDebugMsg, "QMediaPlayer::PlayingState ");
+ qDebug() << QMediaPlayer::PlayingState;
+ QTest::ignoreMessage(QtDebugMsg, "QMediaPlayer::NoMedia ");
+ qDebug() << QMediaPlayer::NoMedia;
+ QTest::ignoreMessage(QtDebugMsg, "QMediaPlayer::NetworkError ");
+ qDebug() << QMediaPlayer::NetworkError;
+}
+
+
diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer.h b/tests/auto/qmediaplayer/tst_qmediaplayer.h
new file mode 100755
index 000000000..6371ac3ff
--- /dev/null
+++ b/tests/auto/qmediaplayer/tst_qmediaplayer.h
@@ -0,0 +1,435 @@
+/****************************************************************************
+**
+** 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 TST_QMEDIAPLAYER_H
+#define TST_QMEDIAPLAYER_H
+
+#include <QtTest/QtTest>
+#include <QtCore/qdebug.h>
+#include <QtCore/qbuffer.h>
+#include <QtNetwork/qnetworkconfiguration.h>
+
+#include <qabstractvideosurface.h>
+#include <qmediaplayer.h>
+#include <qmediaplayercontrol.h>
+#include <qmediaplaylist.h>
+#include <qmediaservice.h>
+#include <qmediastreamscontrol.h>
+#include <qmedianetworkaccesscontrol.h>
+#include <qvideorenderercontrol.h>
+#include <qvideowindowcontrol.h>
+
+QT_USE_NAMESPACE
+
+class AutoConnection
+{
+public:
+ AutoConnection(QObject *sender, const char *signal, QObject *receiver, const char *method)
+ : sender(sender), signal(signal), receiver(receiver), method(method)
+ {
+ QObject::connect(sender, signal, receiver, method);
+ }
+
+ ~AutoConnection()
+ {
+ QObject::disconnect(sender, signal, receiver, method);
+ }
+
+private:
+ QObject *sender;
+ const char *signal;
+ QObject *receiver;
+ const char *method;
+};
+
+
+class MockPlayerControl : public QMediaPlayerControl
+{
+ friend class MockPlayerService;
+
+public:
+ MockPlayerControl():QMediaPlayerControl(0) {}
+
+ QMediaPlayer::State state() const { return _state; }
+ QMediaPlayer::MediaStatus mediaStatus() const { return _mediaStatus; }
+
+ qint64 duration() const { return _duration; }
+
+ qint64 position() const { return _position; }
+
+ void setPosition(qint64 position) { if (position != _position) emit positionChanged(_position = position); }
+
+ int volume() const { return _volume; }
+ void setVolume(int volume) { emit volumeChanged(_volume = volume); }
+
+ bool isMuted() const { return _muted; }
+ void setMuted(bool muted) { if (muted != _muted) emit mutedChanged(_muted = muted); }
+
+ int bufferStatus() const { return _bufferStatus; }
+
+ bool isAudioAvailable() const { return _audioAvailable; }
+ bool isVideoAvailable() const { return _videoAvailable; }
+
+ bool isSeekable() const { return _isSeekable; }
+ QMediaTimeRange availablePlaybackRanges() const { return QMediaTimeRange(_seekRange.first, _seekRange.second); }
+ void setSeekRange(qint64 minimum, qint64 maximum) { _seekRange = qMakePair(minimum, maximum); }
+
+ qreal playbackRate() const { return _playbackRate; }
+ void setPlaybackRate(qreal rate) { if (rate != _playbackRate) emit playbackRateChanged(_playbackRate = rate); }
+
+ QMediaContent media() const { return _media; }
+ void setMedia(const QMediaContent &content, QIODevice *stream)
+ {
+ _stream = stream;
+ _media = content;
+ if (_state != QMediaPlayer::StoppedState) {
+ _mediaStatus = _media.isNull() ? QMediaPlayer::NoMedia : QMediaPlayer::LoadingMedia;
+ emit stateChanged(_state = QMediaPlayer::StoppedState);
+ emit mediaStatusChanged(_mediaStatus);
+ }
+ emit mediaChanged(_media = content);
+ }
+ QIODevice *mediaStream() const { return _stream; }
+
+ void play() { if (_isValid && !_media.isNull() && _state != QMediaPlayer::PlayingState) emit stateChanged(_state = QMediaPlayer::PlayingState); }
+ void pause() { if (_isValid && !_media.isNull() && _state != QMediaPlayer::PausedState) emit stateChanged(_state = QMediaPlayer::PausedState); }
+ void stop() { if (_state != QMediaPlayer::StoppedState) emit stateChanged(_state = QMediaPlayer::StoppedState); }
+
+ QMediaPlayer::State _state;
+ QMediaPlayer::MediaStatus _mediaStatus;
+ QMediaPlayer::Error _error;
+ qint64 _duration;
+ qint64 _position;
+ int _volume;
+ bool _muted;
+ int _bufferStatus;
+ bool _audioAvailable;
+ bool _videoAvailable;
+ bool _isSeekable;
+ QPair<qint64, qint64> _seekRange;
+ qreal _playbackRate;
+ QMediaContent _media;
+ QIODevice *_stream;
+ bool _isValid;
+ QString _errorString;
+};
+
+class MockVideoSurface : public QAbstractVideoSurface
+{
+public:
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ const QAbstractVideoBuffer::HandleType) const
+ {
+ return QList<QVideoFrame::PixelFormat>();
+ }
+
+ bool present(const QVideoFrame &) { return false; }
+};
+
+class MockVideoRendererControl : public QVideoRendererControl
+{
+public:
+ MockVideoRendererControl() : m_surface(0) {}
+
+ QAbstractVideoSurface *surface() const { return m_surface; }
+ void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; }
+
+ QAbstractVideoSurface *m_surface;
+};
+
+class MockVideoWindowControl : public QVideoWindowControl
+{
+public:
+ WId winId() const { return 0; }
+ void setWinId(WId) {}
+ QRect displayRect() const { return QRect(); }
+ void setDisplayRect(const QRect &) {}
+ bool isFullScreen() const { return false; }
+ void setFullScreen(bool) {}
+ void repaint() {}
+ QSize nativeSize() const { return QSize(); }
+ Qt::AspectRatioMode aspectRatioMode() const { return Qt::KeepAspectRatio; }
+ void setAspectRatioMode(Qt::AspectRatioMode) {}
+ int brightness() const { return 0; }
+ void setBrightness(int) {}
+ int contrast() const { return 0; }
+ void setContrast(int) {}
+ int hue() const { return 0; }
+ void setHue(int) {}
+ int saturation() const { return 0; }
+ void setSaturation(int) {}
+};
+
+class MockStreamsControl : public QMediaStreamsControl
+{
+public:
+ MockStreamsControl(QObject *parent = 0) : QMediaStreamsControl(parent) {}
+
+ int streamCount() { return _streams.count(); }
+ void setStreamCount(int count) { _streams.resize(count); }
+
+ StreamType streamType(int index) { return _streams.at(index).type; }
+ void setStreamType(int index, StreamType type) { _streams[index].type = type; }
+
+ QVariant metaData(int index, QtMultimediaKit::MetaData key) {
+ return _streams.at(index).metaData.value(key); }
+ void setMetaData(int index, QtMultimediaKit::MetaData key, const QVariant &value) {
+ _streams[index].metaData.insert(key, value); }
+
+ bool isActive(int index) { return _streams.at(index).active; }
+ void setActive(int index, bool state) { _streams[index].active = state; }
+
+private:
+ struct Stream
+ {
+ Stream() : type(UnknownStream), active(false) {}
+ StreamType type;
+ QMap<QtMultimediaKit::MetaData, QVariant> metaData;
+ bool active;
+ };
+
+ QVector<Stream> _streams;
+};
+
+class MockNetworkAccessControl : public QMediaNetworkAccessControl
+{
+ friend class MockPlayerService;
+
+public:
+ MockNetworkAccessControl() {}
+ ~MockNetworkAccessControl() {}
+
+ void setConfigurations(const QList<QNetworkConfiguration> &configurations)
+ {
+ _configurations = configurations;
+ _current = QNetworkConfiguration();
+ }
+
+ QNetworkConfiguration currentConfiguration() const
+ {
+ return _current;
+ }
+
+private:
+ void setCurrentConfiguration(QNetworkConfiguration configuration)
+ {
+ if (_configurations.contains(configuration))
+ emit configurationChanged(_current = configuration);
+ else
+ emit configurationChanged(_current = QNetworkConfiguration());
+ }
+
+ QList<QNetworkConfiguration> _configurations;
+ QNetworkConfiguration _current;
+};
+
+Q_DECLARE_METATYPE(QNetworkConfiguration)
+
+class MockPlayerService : public QMediaService
+{
+ Q_OBJECT
+
+public:
+ MockPlayerService():QMediaService(0)
+ {
+ mockControl = new MockPlayerControl;
+ mockStreamsControl = new MockStreamsControl;
+ mockNetworkControl = new MockNetworkAccessControl;
+ rendererControl = new MockVideoRendererControl;
+ windowControl = new MockVideoWindowControl;
+ rendererRef = 0;
+ windowRef = 0;
+ }
+
+ ~MockPlayerService()
+ {
+ delete mockControl;
+ delete mockStreamsControl;
+ delete mockNetworkControl;
+ delete rendererControl;
+ delete windowControl;
+ }
+
+ QMediaControl* requestControl(const char *iid)
+ {
+ if (qstrcmp(iid, QMediaPlayerControl_iid) == 0) {
+ return mockControl;
+ } else if (qstrcmp(iid, QVideoRendererControl_iid) == 0) {
+ if (rendererRef == 0) {
+ rendererRef += 1;
+ return rendererControl;
+ }
+ } else if (qstrcmp(iid, QVideoWindowControl_iid) == 0) {
+ if (windowRef == 0) {
+ windowRef += 1;
+ return windowControl;
+ }
+ }
+
+
+ if (qstrcmp(iid, QMediaNetworkAccessControl_iid) == 0)
+ return mockNetworkControl;
+ return 0;
+ }
+
+ void releaseControl(QMediaControl *control)
+ {
+ if (control == rendererControl)
+ rendererRef -= 1;
+ else if (control == windowControl)
+ windowRef -= 1;
+ }
+
+ void setState(QMediaPlayer::State state) { emit mockControl->stateChanged(mockControl->_state = state); }
+ void setState(QMediaPlayer::State state, QMediaPlayer::MediaStatus status) {
+ mockControl->_state = state;
+ mockControl->_mediaStatus = status;
+ emit mockControl->mediaStatusChanged(status);
+ emit mockControl->stateChanged(state);
+ }
+ void setMediaStatus(QMediaPlayer::MediaStatus status) { emit mockControl->mediaStatusChanged(mockControl->_mediaStatus = status); }
+ void setIsValid(bool isValid) { mockControl->_isValid = isValid; }
+ void setMedia(QMediaContent media) { mockControl->_media = media; }
+ void setDuration(qint64 duration) { mockControl->_duration = duration; }
+ void setPosition(qint64 position) { mockControl->_position = position; }
+ void setSeekable(bool seekable) { mockControl->_isSeekable = seekable; }
+ void setVolume(int volume) { mockControl->_volume = volume; }
+ void setMuted(bool muted) { mockControl->_muted = muted; }
+ void setVideoAvailable(bool videoAvailable) { mockControl->_videoAvailable = videoAvailable; }
+ void setBufferStatus(int bufferStatus) { mockControl->_bufferStatus = bufferStatus; }
+ void setPlaybackRate(qreal playbackRate) { mockControl->_playbackRate = playbackRate; }
+ void setError(QMediaPlayer::Error error) { mockControl->_error = error; emit mockControl->error(mockControl->_error, mockControl->_errorString); }
+ void setErrorString(QString errorString) { mockControl->_errorString = errorString; emit mockControl->error(mockControl->_error, mockControl->_errorString); }
+
+ void selectCurrentConfiguration(QNetworkConfiguration config) { mockNetworkControl->setCurrentConfiguration(config); }
+
+ void reset()
+ {
+ mockControl->_state = QMediaPlayer::StoppedState;
+ mockControl->_mediaStatus = QMediaPlayer::UnknownMediaStatus;
+ mockControl->_error = QMediaPlayer::NoError;
+ mockControl->_duration = 0;
+ mockControl->_position = 0;
+ mockControl->_volume = 0;
+ mockControl->_muted = false;
+ mockControl->_bufferStatus = 0;
+ mockControl->_videoAvailable = false;
+ mockControl->_isSeekable = false;
+ mockControl->_playbackRate = 0.0;
+ mockControl->_media = QMediaContent();
+ mockControl->_stream = 0;
+ mockControl->_isValid = false;
+ mockControl->_errorString = QString();
+
+ mockNetworkControl->_current = QNetworkConfiguration();
+ mockNetworkControl->_configurations = QList<QNetworkConfiguration>();
+ }
+
+ MockPlayerControl *mockControl;
+ MockStreamsControl *mockStreamsControl;
+ MockNetworkAccessControl *mockNetworkControl;
+ MockVideoRendererControl *rendererControl;
+ MockVideoWindowControl *windowControl;
+ int rendererRef;
+ int windowRef;
+};
+
+class MockProvider : public QMediaServiceProvider
+{
+public:
+ MockProvider(MockPlayerService *service):mockService(service), deleteServiceOnRelease(true) {}
+ QMediaService *requestService(const QByteArray &, const QMediaServiceProviderHint &)
+ {
+ return mockService;
+ }
+
+ void releaseService(QMediaService *service) { if (deleteServiceOnRelease) delete service; }
+
+ MockPlayerService *mockService;
+ bool deleteServiceOnRelease;
+};
+
+class tst_QMediaPlayer: public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase_data();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void testNullService();
+ void testValid();
+ void testMedia();
+ void testDuration();
+ void testPosition();
+ void testVolume();
+ void testMuted();
+ void testIsAvailable();
+ void testVideoAvailable();
+ void testBufferStatus();
+ void testSeekable();
+ void testPlaybackRate();
+ void testError();
+ void testErrorString();
+ void testService();
+ void testPlay();
+ void testPause();
+ void testStop();
+ void testMediaStatus();
+ void testPlaylist();
+ void testNetworkAccess();
+ void testSetVideoOutput();
+ void testSetVideoOutputNoService();
+ void testSetVideoOutputNoControl();
+ void testSetVideoOutputDestruction();
+ void testPositionPropertyWatch();
+ void debugEnums();
+
+private:
+ MockProvider *mockProvider;
+ MockPlayerService *mockService;
+ QMediaPlayer *player;
+};
+
+#endif //TST_QMEDIAPLAYER_H
diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer_s60.cpp b/tests/auto/qmediaplayer/tst_qmediaplayer_s60.cpp
new file mode 100755
index 000000000..f30934a96
--- /dev/null
+++ b/tests/auto/qmediaplayer/tst_qmediaplayer_s60.cpp
@@ -0,0 +1,1708 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include "tst_qmediaplayer_s60.h"
+#include <qmediastreamscontrol.h>
+
+static const QString TestFilePath = QLatin1String("c:/data/testfiles/");
+
+// Comment out the following line if the test device does not have network
+// access.
+#define TEST_DEVICE_HAS_NETWORK_ACCESS
+
+QT_USE_NAMESPACE
+
+void tst_QMediaPlayer_s60::initTestCase_data()
+{
+#ifdef __WINSCW__
+ initTestCase_data_default_winscw();
+#else
+ initTestCase_data_default_armv5();
+#endif
+}
+
+void tst_QMediaPlayer_s60::initTestCase_data_default_armv5()
+{
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<bool>("streamable");
+ QTest::addColumn<QMediaPlayer::State>("state");
+ QTest::addColumn<QMediaPlayer::MediaStatus>("status");
+ QTest::addColumn<QMediaContent>("mediaContent");
+ QTest::addColumn<qint64>("duration");
+ QTest::addColumn<qint64>("position");
+ QTest::addColumn<bool>("seekable");
+ QTest::addColumn<bool>("seekableWhilePlaying");
+ QTest::addColumn<int>("volume");
+ QTest::addColumn<bool>("videoAvailable");
+ QTest::addColumn<bool>("audioAvailable");
+ QTest::addColumn<qreal>("playbackRate");
+ QTest::addColumn<QMediaPlayer::Error>("error");
+ QTest::addColumn<QString>("errorString");
+
+ QTest::newRow("TestDataNull")
+ << false //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::NoMedia // status
+ << QMediaContent() // mediaContent
+ << qint64(-1) // duration
+ << qint64(0) // position
+ << false // seekable
+ << false // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << false //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_3gp.3gp")
+ << true //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status LoadedMedia
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_3gp.3gp")) // mediaContent
+ << qint64(46860) // duration
+ << qint64(23430) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << true //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_mp4.mp4")
+ << true //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_mp4.mp4")) // mediaContent
+ << qint64(2701) // duration
+ << qint64(1351) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << true //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_wmv9.wmv")
+ << true //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_wmv9.wmv")) // mediaContent
+ << qint64(169389) // duration
+ << qint64(84695) // position (duration/2)
+ << true // seekable
+ << false // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << true //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_AAC.dat")
+ << false //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::InvalidMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_AAC.dat")) // mediaContent
+ << qint64(-1) // duration
+ << qint64(0) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << false //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::ResourceError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_amr.amr")
+ << true // valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_amr.amr")) // mediaContent
+ << qint64(14400) // duration
+ << qint64(7200) // position
+ << true // seekable
+ << false // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << true // audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_mp3.mp3")
+ << true // valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_mp3.mp3")) // mediaContent
+ << qint64(102044) //qint64(102044) duration
+ << qint64(51022) // position
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << true // audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+#ifdef TEST_DEVICE_HAS_NETWORK_ACCESS
+ QTest::newRow("test_stream 3gp")
+ << false // valid
+ << true //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl("rtsp://v3.cache4.c.youtube.com/CkgLENy73wIaPwlU2rm7yu8PFhMYESARFEIJbXYtZ29vZ2xlSARSB3JlbGF0ZWRaDkNsaWNrVGh1bWJuYWlsYPi6_IXT2rvpSgw=/0/0/0/video.3gp")) // mediaContent
+ << qint64(103000) // duration
+ << qint64(0) // position
+ << false // seekable
+ << false // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << true // audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("RTSP link to H.263/AMR")
+ << false // valid
+ << true //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl("rtsp://v7.cache8.c.youtube.com/CiILENy73wIaGQnNUH6lxLd0MRMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp")) // mediaContent
+ << qint64(249000) // duration
+ << qint64(0) // position
+ << false // seekable
+ << false // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << true // audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("RTSP link to MPEG-4/AAC")
+ << false // valid
+ << true //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl("rtsp://v8.cache1.c.youtube.com/CiILENy73wIaGQnNUH6lxLd0MRMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp")) // mediaContent
+ << qint64(249000) // duration
+ << qint64(0) // position
+ << false // seekable
+ << false // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << true // audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+#endif // TEST_DEVICE_HAS_NETWORK_ACCESS
+}
+
+void tst_QMediaPlayer_s60::initTestCase_data_default_winscw()
+{
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<bool>("streamable");
+ QTest::addColumn<QMediaPlayer::State>("state");
+ QTest::addColumn<QMediaPlayer::MediaStatus>("status");
+ QTest::addColumn<QMediaContent>("mediaContent");
+ QTest::addColumn<qint64>("duration");
+ QTest::addColumn<qint64>("position");
+ QTest::addColumn<bool>("seekable");
+ QTest::addColumn<bool>("seekableWhilePlaying");
+ QTest::addColumn<int>("volume");
+ QTest::addColumn<bool>("videoAvailable");
+ QTest::addColumn<bool>("audioAvailable");
+ QTest::addColumn<qreal>("playbackRate");
+ QTest::addColumn<QMediaPlayer::Error>("error");
+ QTest::addColumn<QString>("errorString");
+
+ QTest::newRow("TestDataNull")
+ << false //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::NoMedia // status
+ << QMediaContent() // mediaContent
+ << qint64(-1) // duration
+ << qint64(0) // position
+ << false // seekable
+ << false // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << false //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_3GPP.dat")
+ << true //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_3GPP.dat")) // mediaContent
+ << qint64(7200) // duration
+ << qint64(3600) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << true //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_3gp.3gp")
+ << true //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_3gp.3gp")) // mediaContent
+ << qint64(46860) // duration
+ << qint64(23430) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << true //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_mp4.mp4")
+ << true //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_mp4.mp4")) // mediaContent
+ << qint64(2701) // duration
+ << qint64(1351) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << false //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::FormatError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_MP4.dat")
+ << false //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::InvalidMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_MP4.dat")) // mediaContent
+ << qint64(-1) // duration
+ << qint64(0) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << false //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::AccessDeniedError// error
+ << QString(); // errorString
+
+ QTest::newRow("test_wmv9.wmv")
+ << true //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_wmv9.wmv")) // mediaContent
+ << qint64(169389) // duration
+ << qint64(84695) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << false //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::FormatError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_h264_qcif.264")
+ << false //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::InvalidMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_h264_qcif.264")) // mediaContent
+ << qint64(-1) // duration
+ << qint64(0) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << false //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::ResourceError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_RM.dat")
+ << true //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_RM.dat")) // mediaContent
+ << qint64(20245) // duration
+ << qint64(10123) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << true //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_SWF.dat")
+ << false //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::InvalidMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_SWF.dat")) // mediaContent
+ << qint64(-1) // duration
+ << qint64(0) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << false //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::ResourceError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_WMV.dat")
+ << true //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_WMV.dat")) // mediaContent
+ << qint64(3098) // duration
+ << qint64(1549) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying, on emulator codec leaks memory and causes alloc panic on dtor
+ << 50 // volume
+ << true // videoAvailable
+ << false //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::FormatError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_WMA.dat")
+ << false //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::InvalidMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_WMA.dat")) // mediaContent
+ << qint64(-1) // duration
+ << qint64(0) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << false //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::AccessDeniedError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_flash_video.flv")
+ << false // valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::InvalidMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_flash_video.flv")) // mediaContent
+ << qint64(-1) // duration
+ << qint64(0) // position
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << false //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::ResourceError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_MXMF.dat")
+ << true //valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_MXMF.dat")) // mediaContent
+ << qint64(31980) // duration
+ << qint64(15990) // position (duration/2)
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << true //audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_amr.amr")
+ << true // valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_amr.amr")) // mediaContent
+ << qint64(14402) // duration
+ << qint64(7200) // position
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << true // audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_AMR.dat")
+ << true // valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_AMR.dat")) // mediaContent
+ << qint64(38509) // duration
+ << qint64(19255) // position
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << true // audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_mp3.mp3")
+ << false // valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_mp3.mp3")) // mediaContent
+ << qint64(-1) //qint64(102044) duration
+ << qint64(0) // position
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << false // audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::ResourceError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_MP3.dat")
+ << false // valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::InvalidMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_MP3.dat")) // mediaContent
+ << qint64(-1) //qint64(102044) duration
+ << qint64(0) // position
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << false // audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::ResourceError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_MIDI.dat")
+ << true // valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_MIDI.dat")) // mediaContent
+ << qint64(32782) // duration
+ << qint64(16391) // position
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << true // audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_ACC.dat")
+ << false // valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::InvalidMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_ACC.dat")) // mediaContent
+ << qint64(-1) // duration
+ << qint64(0) // position
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << false // audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::ResourceError // error
+ << QString(); // errorString
+
+ QTest::newRow("test_WAV.dat")
+ << true // valid
+ << false //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_WAV.dat")) // mediaContent
+ << qint64(2864) // duration
+ << qint64(1432) // position
+ << true // seekable
+ << true // seekableWhilePlaying
+ << 50 // volume
+ << false // videoAvailable
+ << true // audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::NoError // error
+ << QString(); // errorString
+
+#ifdef TEST_DEVICE_HAS_NETWORK_ACCESS
+ QTest::newRow("test_stream")
+ << false // valid
+ << true //streamable
+ << QMediaPlayer::StoppedState // state
+ << QMediaPlayer::LoadedMedia // status
+ << QMediaContent(QUrl("rtsp://v3.cache4.c.youtube.com/CkgLENy73wIaPwlU2rm7yu8PFhMYESARFEIJbXYtZ29vZ2xlSARSB3JlbGF0ZWRaDkNsaWNrVGh1bWJuYWlsYPi6_IXT2rvpSgw=/0/0/0/video.3gp")) // mediaContent
+ << qint64(-1) // duration
+ << qint64(0) // position
+ << false // seekable
+ << false // seekableWhilePlaying
+ << 50 // volume
+ << true // videoAvailable
+ << false // audioAvailable
+ << qreal(0) // playbackRate
+ << QMediaPlayer::AccessDeniedError // error
+ << QString(); // errorString
+#endif
+}
+
+void tst_QMediaPlayer_s60::initTestCase()
+{
+ m_player = new QMediaPlayer();
+
+ // Symbian back end needs coecontrol for creation.
+ m_widget = new QVideoWidget();
+ m_player->setVideoOutput(m_widget);
+ m_widget->show();
+ runonce = false;
+}
+
+void tst_QMediaPlayer_s60::cleanupTestCase()
+{
+ delete m_player;
+ delete m_widget;
+}
+
+void tst_QMediaPlayer_s60::init()
+{
+ qRegisterMetaType<QMediaPlayer::State>("QMediaPlayer::State");
+ qRegisterMetaType<QMediaPlayer::Error>("QMediaPlayer::Error");
+ qRegisterMetaType<QMediaPlayer::MediaStatus>("QMediaPlayer::MediaStatus");
+ qRegisterMetaType<QMediaContent>("QMediaContent");
+}
+
+void tst_QMediaPlayer_s60::cleanup()
+{
+}
+
+void tst_QMediaPlayer_s60::testNullService()
+{
+ if(runonce)
+ return;
+ MockProvider_s60 provider(0);
+ QMediaPlayer player(0, 0, &provider);
+
+ const QIODevice *nullDevice = 0;
+
+ QCOMPARE(player.media(), QMediaContent());
+ QCOMPARE(player.mediaStream(), nullDevice);
+ QCOMPARE(player.state(), QMediaPlayer::StoppedState);
+ QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus);
+ QCOMPARE(player.duration(), qint64(-1));
+ QCOMPARE(player.position(), qint64(0));
+ QCOMPARE(player.volume(), 0);
+ QCOMPARE(player.isMuted(), false);
+ QCOMPARE(player.isVideoAvailable(), false);
+ QCOMPARE(player.bufferStatus(), 0);
+ QCOMPARE(player.isSeekable(), false);
+ QCOMPARE(player.playbackRate(), qreal(0));
+ QCOMPARE(player.error(), QMediaPlayer::ServiceMissingError);
+
+ {
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+
+ QSignalSpy spy(&player, SIGNAL(mediaChanged(QMediaContent)));
+ QFile file;
+
+ player.setMedia(mediaContent, &file);
+ QCOMPARE(player.media(), QMediaContent());
+ QCOMPARE(player.mediaStream(), nullDevice);
+ QCOMPARE(spy.count(), 0);
+ } {
+ QSignalSpy stateSpy(&player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+
+ player.play();
+ QCOMPARE(player.state(), QMediaPlayer::StoppedState);
+ QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus);
+ QCOMPARE(stateSpy.count(), 0);
+ QCOMPARE(statusSpy.count(), 0);
+
+ player.pause();
+ QCOMPARE(player.state(), QMediaPlayer::StoppedState);
+ QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus);
+ QCOMPARE(stateSpy.count(), 0);
+ QCOMPARE(statusSpy.count(), 0);
+
+ player.stop();
+ QCOMPARE(player.state(), QMediaPlayer::StoppedState);
+ QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus);
+ QCOMPARE(stateSpy.count(), 0);
+ QCOMPARE(statusSpy.count(), 0);
+ } {
+ QFETCH_GLOBAL(int, volume);
+
+ QSignalSpy volumeSpy(&player, SIGNAL(volumeChanged(int)));
+ QSignalSpy mutingSpy(&player, SIGNAL(mutedChanged(bool)));
+
+ player.setVolume(volume);
+ QCOMPARE(player.volume(), 0);
+ QCOMPARE(volumeSpy.count(), 0);
+
+ player.setMuted(false);
+ QCOMPARE(player.isMuted(), false);
+ QCOMPARE(mutingSpy.count(), 0);
+ } {
+ QFETCH_GLOBAL(qint64, position);
+
+ QSignalSpy spy(&player, SIGNAL(positionChanged(qint64)));
+
+ player.setPosition(position);
+ QCOMPARE(player.position(), qint64(0));
+ QCOMPARE(spy.count(), 0);
+ } {
+ QFETCH_GLOBAL(qreal, playbackRate);
+
+ QSignalSpy spy(&player, SIGNAL(playbackRateChanged(qreal)));
+
+ player.setPlaybackRate(playbackRate);
+ QCOMPARE(player.playbackRate(), qreal(0));
+ QCOMPARE(spy.count(), 0);
+ } {
+ QMediaPlaylist playlist;
+ player.setPlaylist(&playlist);
+
+ QSignalSpy mediaSpy(&player, SIGNAL(mediaChanged(QMediaContent)));
+ QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+
+ playlist.addMedia(QUrl("http://example.com/stream"));
+ playlist.addMedia(QUrl("file:///some.mp3"));
+
+ playlist.setCurrentIndex(0);
+ QCOMPARE(playlist.currentIndex(), 0);
+ QCOMPARE(player.media(), QMediaContent());
+ QCOMPARE(mediaSpy.count(), 0);
+ QCOMPARE(statusSpy.count(), 0);
+
+ playlist.next();
+ QCOMPARE(playlist.currentIndex(), 1);
+ QCOMPARE(player.media(), QMediaContent());
+ QCOMPARE(mediaSpy.count(), 0);
+ QCOMPARE(statusSpy.count(), 0);
+ }
+ runonce = true;
+}
+
+void tst_QMediaPlayer_s60::testMedia()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ m_player->setMedia(mediaContent);
+ QTest::qWait(500);
+ QCOMPARE(m_player->media(), mediaContent);
+}
+
+
+void tst_QMediaPlayer_s60::testDuration()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(qint64, duration);
+ QFETCH_GLOBAL(bool, valid);
+
+ QSignalSpy spy(m_player, SIGNAL(durationChanged(qint64)));
+ m_player->setMedia(mediaContent);
+
+ if(valid) {
+ WAIT_FOR_CONDITION(spy.count(), 1);
+ } else {
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia));
+ }
+
+ QVERIFY(m_player->duration() == duration);
+}
+
+void tst_QMediaPlayer_s60::testPosition()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(qint64, duration);
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(bool, seekable);
+ QFETCH_GLOBAL(qint64, position);
+ QFETCH_GLOBAL(QMediaPlayer::MediaStatus, status);
+
+ m_player->setMedia(mediaContent);
+
+ if (valid) {
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ QCOMPARE(m_player->isSeekable(), seekable);
+ //QCOMPARE(m_player->mediaStatus(), status);
+ QVERIFY(m_player->mediaStatus() == status);
+
+ // preset position
+ { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->setPosition(position);
+ QCOMPARE(m_player->position(), position);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toLongLong(), position);}
+
+ // same pos second time
+ { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->setPosition(position);
+ QCOMPARE(m_player->position(), position);
+ QCOMPARE(spy.count(), 0);}
+
+ //zero pos
+ { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->setPosition(0);
+ QCOMPARE(m_player->position(), qint64(0));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toLongLong(), qint64(0));}
+
+ //end pos
+ { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->setPosition(duration);
+ QCOMPARE(m_player->position(), duration);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toLongLong(), duration);}
+
+ //negative pos
+ { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->setPosition(qint64(-1));
+ QCOMPARE(m_player->position(), qint64(0));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toLongLong(), qint64(0));}
+
+ //over duration
+ { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->setPosition(duration+1);
+ QCOMPARE(m_player->position(), duration);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toLongLong(), duration);}
+
+ } else {
+ if (valid)
+ WAIT_LONG_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia)
+ else
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia))
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(m_player->isSeekable(), seekable);
+ QCOMPARE(m_player->mediaStatus(), status);
+ }
+}
+
+void tst_QMediaPlayer_s60::testPositionWhilePlaying()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(qint64, duration);
+ QFETCH_GLOBAL(bool, seekableWhilePlaying);
+ QFETCH_GLOBAL(bool, seekable);
+ QFETCH_GLOBAL(qint64, position);
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(bool, streamable);
+ QFETCH_GLOBAL(QMediaPlayer::MediaStatus, status);
+
+ m_player->setMedia(mediaContent);
+
+ if (streamable) {
+ WAIT_LONG_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia));
+ } else {
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia));
+ }
+
+ //qDebug()<<"";
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(m_player->isSeekable(), seekable);
+ QCOMPARE(m_player->mediaStatus(), status);
+
+ if (seekableWhilePlaying && valid) {
+ QCOMPARE(m_player->isSeekable(), seekableWhilePlaying);
+
+ // preset position
+ //qDebug()<<"preset";
+ { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ m_player->setPosition(position);
+ WAIT_FOR_CONDITION(spy.count(), 2);
+ QVERIFY(m_player->mediaStatus() == QMediaPlayer::BufferingMedia ||
+ m_player->mediaStatus() == QMediaPlayer::BufferedMedia ||
+ m_player->mediaStatus() == QMediaPlayer::EndOfMedia ||
+ m_player->mediaStatus() == QMediaPlayer::LoadedMedia);
+
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QVERIFY(m_player->position()>=position);
+ QVERIFY(spy.count()!=0);}
+
+ //reset position
+ m_player->stop();
+ m_player->setPosition(position);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ //zero pos
+ //qDebug()<<"zero";
+ { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ m_player->setPosition(0);
+ WAIT_FOR_CONDITION(spy.count(), 2);
+ QVERIFY(m_player->mediaStatus() == QMediaPlayer::BufferingMedia ||
+ m_player->mediaStatus() == QMediaPlayer::BufferedMedia ||
+ m_player->mediaStatus() == QMediaPlayer::EndOfMedia ||
+ m_player->mediaStatus() == QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QVERIFY(m_player->position() >= qint64(0));
+ QVERIFY(spy.count()!=0);}
+
+ //reset position
+ m_player->stop();
+ m_player->setPosition(position);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ //end pos
+ //qDebug()<<"dur";
+ { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ m_player->setPosition(duration);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(m_player->position(), qint64(0));
+ QVERIFY(spy.count()!=0);}
+
+ //reset position
+ m_player->stop();
+ m_player->setPosition(position);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ //negative pos
+ //qDebug()<<"negavite";
+ { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ m_player->setPosition(qint64(-1));
+ WAIT_FOR_CONDITION(spy.count(), 2);
+ QVERIFY(m_player->mediaStatus() == QMediaPlayer::BufferingMedia ||
+ m_player->mediaStatus() == QMediaPlayer::BufferedMedia ||
+ m_player->mediaStatus() == QMediaPlayer::EndOfMedia ||
+ m_player->mediaStatus() == QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QVERIFY(m_player->position() >= qint64(0));
+ QVERIFY(spy.count()!=0);}
+
+ //reset position
+ m_player->stop();
+ m_player->setPosition(position);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ //over duration
+ //qDebug()<<"over";
+ { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ m_player->setPosition(duration+1);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);
+ // s60 MP3 controller has a weard feature to reduce position by ~200 when position
+ // is set over the duration, therefore we skip it here
+ if (!mediaContent.canonicalUrl().path().endsWith("mp3")) {
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(m_player->position(), qint64(0));
+ QVERIFY(spy.count()!=0);}
+ }
+ } else
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ //qDebug()<<"end";
+}
+
+
+void tst_QMediaPlayer_s60::testVolume()
+{
+ QFETCH_GLOBAL(int, volume);
+
+ // preset volume
+ { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(volume);
+ QCOMPARE(m_player->volume(), volume);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);}
+
+ // same volume
+ { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ int currentVolume = m_player->volume();
+ m_player->setVolume(currentVolume);
+ QCOMPARE(m_player->volume(), currentVolume);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 0);}
+
+ // zero volume
+ { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(0);
+ QCOMPARE(m_player->volume(), 0);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);}
+
+ // max volume
+ { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(100);
+ QCOMPARE(m_player->volume(), 100);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);}
+
+ // negative volume
+ { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(int(-1));
+ QCOMPARE(m_player->volume(), 0);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);}
+
+ // over max volume
+ { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(1000);
+ QCOMPARE(m_player->volume(), 100);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);}
+}
+
+void tst_QMediaPlayer_s60::testVolumeWhilePlaying()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(int, volume);
+ QFETCH_GLOBAL(bool, valid);
+
+ if (valid) {
+ m_player->setMedia(mediaContent);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+
+ m_player->play();
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ // preset volume
+ { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(volume);
+ QCOMPARE(m_player->volume(), volume);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);}
+
+ // same volume
+ { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ int currentVolume = m_player->volume();
+ m_player->setVolume(currentVolume);
+ QCOMPARE(m_player->volume(), currentVolume);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 0);}
+
+ // zero volume
+ { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(0);
+ QCOMPARE(m_player->volume(), 0);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);}
+
+ // max volume
+ { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(100);
+ QCOMPARE(m_player->volume(), 100);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);}
+
+ // negative volume
+ { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(int(-1));
+ QCOMPARE(m_player->volume(), 0);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);}
+
+ // over max volume
+ { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(1000);
+ QCOMPARE(m_player->volume(), 100);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);}
+
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ }
+}
+
+
+void tst_QMediaPlayer_s60::testMuted()
+{
+ QFETCH_GLOBAL(int, volume);
+
+ //reset mute & volume
+ m_player->setMuted(false);
+ m_player->setVolume(0);
+ QVERIFY(m_player->isMuted() == false);
+ QCOMPARE(m_player->volume(), 0);
+
+ // set muted
+ {QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool)));
+ m_player->setMuted(true);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_player->isMuted() == true);}
+
+ // set muted again
+ {QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool)));
+ m_player->setMuted(true);
+ QCOMPARE(spy.count(), 0);
+ QVERIFY(m_player->isMuted() == true);}
+
+ // unmute
+ {QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool)));
+ m_player->setMuted(false);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_player->isMuted() == false);}
+
+ // set volume while muted
+ {QSignalSpy muteSpy(m_player, SIGNAL(mutedChanged(bool)));
+ QSignalSpy volumeSpy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setMuted(true);
+ m_player->setVolume(volume);
+ QCOMPARE(m_player->volume(), volume);
+ QCOMPARE(muteSpy.count(), 1);
+ QCOMPARE(volumeSpy.count(), 1);
+ QVERIFY(m_player->isMuted() == true);}
+}
+
+void tst_QMediaPlayer_s60::testMutedWhilePlaying()
+{
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(int, volume);
+ QFETCH_GLOBAL(bool, valid);
+
+ if (valid) {
+ m_player->setMedia(mediaContent);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+
+ //reset mute & volume
+ m_player->setMuted(false);
+ m_player->setVolume(65);
+ QVERIFY(m_player->isMuted() == false);
+ QCOMPARE(m_player->volume(), 65);
+
+ m_player->play();
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ // set muted
+ {QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool)));
+ m_player->setMuted(true);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_player->isMuted() == true);}
+
+ // set muted again
+ {QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool)));
+ m_player->setMuted(true);
+ QCOMPARE(spy.count(), 0);
+ QVERIFY(m_player->isMuted() == true);}
+
+ // unmute
+ {QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool)));
+ m_player->setMuted(false);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_player->isMuted() == false);}
+
+ // set volume while muted
+ {QSignalSpy muteSpy(m_player, SIGNAL(mutedChanged(bool)));
+ QSignalSpy volumeSpy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setMuted(true);
+ m_player->setVolume(volume);
+ QCOMPARE(m_player->volume(), volume);
+ QCOMPARE(muteSpy.count(), 1);
+ QCOMPARE(volumeSpy.count(), 1);
+ QVERIFY(m_player->isMuted() == true);}
+
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ }
+}
+
+
+void tst_QMediaPlayer_s60::testVideoAndAudioAvailability()
+{
+ QFETCH_GLOBAL(bool, videoAvailable);
+ QFETCH_GLOBAL(bool, audioAvailable);
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+
+ if(valid) {
+ QSignalSpy audioAvailableSpy(m_player, SIGNAL(audioAvailableChanged(bool)));
+ QSignalSpy videoAvailableSpy(m_player, SIGNAL(videoAvailableChanged(bool)));
+
+ m_player->setMedia(mediaContent);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+
+ QVERIFY(m_player->isVideoAvailable() == videoAvailable);
+ QVERIFY(m_player->isAudioAvailable() == audioAvailable);
+
+ QCOMPARE(audioAvailableSpy.count(), 1);
+ QCOMPARE(videoAvailableSpy.count(), 1);
+ }
+}
+
+void tst_QMediaPlayer_s60::testError()
+{
+ QFETCH_GLOBAL(QMediaPlayer::Error, error);
+ QFETCH_GLOBAL(bool, videoAvailable);
+ QFETCH_GLOBAL(bool, audioAvailable);
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(QMediaPlayer::State, state);
+ QFETCH_GLOBAL(QMediaPlayer::MediaStatus, status);
+
+ QSignalSpy errorSpy(m_player, SIGNAL(error(QMediaPlayer::Error)));
+ m_player->setMedia(mediaContent);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia));
+ QVERIFY(m_player->mediaStatus() == status);
+ QVERIFY(m_player->state() == state);
+ QVERIFY(m_player->error() == error);
+ if (error != QMediaPlayer::NoError) {
+ QVERIFY(errorSpy.count()!=0);
+ }
+}
+
+void tst_QMediaPlayer_s60::testPlay()
+{
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(bool, streamable);
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(QMediaPlayer::State, state);
+
+ m_player->setMedia(mediaContent);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia));
+ QVERIFY(m_player->state() == state);
+ QVERIFY(m_player->media() == mediaContent);
+ QSignalSpy spy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->play();
+
+ if(valid) {
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(spy.count(), state == QMediaPlayer::PlayingState ? 0 : 1);
+
+ //Play->Play
+ {QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->play();
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 0);}
+
+ //Play->Pause
+ {QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->pause();
+ QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QCOMPARE(stateSpy.count(), 1);}
+
+ //Play->Stop
+ {m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ if (m_player->mediaStatus() != QMediaPlayer::EndOfMedia) {
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.count(), 1);
+ } else {
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(spy.count(), 4);
+ }}
+ } else if (streamable) {
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(spy.count(), 2);
+ } else {
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(spy.count(), 0);
+ }
+
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+}
+
+void tst_QMediaPlayer_s60::testPause()
+{
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(bool, streamable);
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(QMediaPlayer::State, state);
+
+ m_player->setMedia(mediaContent);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia));
+ QVERIFY(m_player->state() == state);
+ QVERIFY(m_player->media() == mediaContent);
+ QSignalSpy spy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->pause();
+
+ if(valid) {
+ QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QCOMPARE(spy.count(), 1);
+
+ //Pause->Play
+ {QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->play();
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 1);}
+
+ //Pause->Pause
+ {m_player->pause();
+ QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->pause();
+ QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QCOMPARE(stateSpy.count(), 0);}
+
+ //Pause->Stop
+ {QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.count(), 1);}
+ } else if (streamable) {
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(spy.count(), 2);
+ } else {
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(spy.count(), 0);
+ }
+}
+
+void tst_QMediaPlayer_s60::testStop()
+{
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(QMediaPlayer::State, state);
+
+ m_player->setMedia(mediaContent);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia));
+ QVERIFY(m_player->state() == state);
+ QVERIFY(m_player->media() == mediaContent);
+
+ QSignalSpy spy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->stop();
+
+ if(valid) {
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(spy.count(), 0);
+
+ //Stop->Play
+ {QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->play();
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 1);}
+
+ //Stop->Pause
+ {m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->pause();
+ QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QCOMPARE(stateSpy.count(), 1);}
+
+ //Stop->Stop
+ {m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.count(), 0);}
+ } else {
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(spy.count(), 0);
+ }
+}
+
+void tst_QMediaPlayer_s60::testMediaStatus()
+{
+ QFETCH_GLOBAL(bool, videoAvailable);
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(bool, streamable);
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+
+ QSignalSpy statusSpy(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ mediaStatusList list(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ m_player->setMedia(mediaContent);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia));
+
+ if(valid) {
+ if (videoAvailable) {
+ QCOMPARE(statusSpy.count(), 3);
+ QCOMPARE(list.count(), 3);
+ QCOMPARE(list.at(0), QMediaPlayer::UnknownMediaStatus);
+ QCOMPARE(list.at(1), QMediaPlayer::LoadingMedia);
+ QCOMPARE(list.at(2), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+
+ m_player->play();
+ {WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);}
+ QCOMPARE(statusSpy.count(), 5);
+ QCOMPARE(list.count(), 5);
+ QCOMPARE(list.at(3), QMediaPlayer::BufferingMedia);
+ QCOMPARE(list.at(4), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ {WAIT_LONG_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);}
+ QVERIFY(statusSpy.count() == 6);
+ QVERIFY(list.count() == 6);
+ QCOMPARE(list.last(), QMediaPlayer::EndOfMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);
+ }else {
+ QCOMPARE(statusSpy.count(), 3);
+ QCOMPARE(list.count(), 3);
+ QCOMPARE(list.at(0), QMediaPlayer::UnknownMediaStatus);
+ QCOMPARE(list.at(1), QMediaPlayer::LoadingMedia);
+ QCOMPARE(list.at(2), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+
+ m_player->play();
+ {WAIT_LONG_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);}
+ QVERIFY(statusSpy.count() == 4);
+ QVERIFY(list.count() == 4);
+ QCOMPARE(list.last(), QMediaPlayer::EndOfMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);
+ }
+ } else if (mediaContent.isNull()) {
+ QCOMPARE(statusSpy.count(), 2);
+ QCOMPARE(list.count(), 2);
+ QCOMPARE(list.at(0), QMediaPlayer::UnknownMediaStatus);
+ QCOMPARE(list.at(1), QMediaPlayer::NoMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::NoMedia);
+ m_player->play();
+ QCOMPARE(statusSpy.count(), 2);
+ QCOMPARE(list.count(), 2);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::NoMedia);
+ } else if (streamable) {
+ QCOMPARE(statusSpy.count(), 3);
+ QCOMPARE(list.count(), 3);
+ QCOMPARE(list.at(0), QMediaPlayer::UnknownMediaStatus);
+ QCOMPARE(list.at(1), QMediaPlayer::LoadingMedia);
+ QCOMPARE(list.at(2), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ m_player->play();
+ QCOMPARE(statusSpy.count(), 3);
+ QCOMPARE(list.count(), 3);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ } else {
+ QCOMPARE(statusSpy.count(), 3);
+ QCOMPARE(list.count(), 3);
+ QCOMPARE(list.at(0), QMediaPlayer::UnknownMediaStatus);
+ QCOMPARE(list.at(1), QMediaPlayer::LoadingMedia);
+ QCOMPARE(list.at(2), QMediaPlayer::InvalidMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::InvalidMedia);
+ m_player->play();
+ QCOMPARE(statusSpy.count(), 3);
+ QCOMPARE(list.count(), 3);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::InvalidMedia);
+ }
+
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+}
+
+void tst_QMediaPlayer_s60::testPlaylist()
+{
+ if(!runonce) {
+ QMediaContent content0(QUrl::fromLocalFile(TestFilePath + "test_mp4.mp4"));
+ QMediaContent content1(QUrl::fromLocalFile(TestFilePath + "test_WAV.dat"));
+ QMediaContent content2(QUrl::fromLocalFile(TestFilePath + "test_mp4.mp4"));
+ QMediaContent content3(QUrl::fromLocalFile(TestFilePath + "test_WAV.dat"));
+ QMediaContent content4(QUrl::fromLocalFile(TestFilePath + "test_MIDI.dat"));
+
+ QMediaPlaylist *playlist = new QMediaPlaylist(m_player);
+ m_player->setPlaylist(playlist);
+
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ QSignalSpy mediaSpy(m_player, SIGNAL(mediaChanged(QMediaContent)));
+
+ // Test the player does nothing with an empty playlist attached.
+ m_player->play();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(m_player->media(), QMediaContent());
+ QCOMPARE(stateSpy.count(), 0);
+ QCOMPARE(mediaSpy.count(), 0);
+
+ playlist->addMedia(content0);
+ playlist->addMedia(content1);
+ playlist->addMedia(content2);
+ playlist->addMedia(content3);
+
+ // Test changing the playlist position, changes the current media, but not the playing state.
+ playlist->setCurrentIndex(1);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->media(), content1);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(stateSpy.count(), 0);
+ QCOMPARE(mediaSpy.count(), 1);
+
+ // Test playing starts with the current media.
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->media(), content1);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia));
+ QCOMPARE(stateSpy.count(), 1);
+ QCOMPARE(mediaSpy.count(), 1);
+
+ // Test pausing doesn't change the current media.
+ m_player->pause();
+ QCOMPARE(m_player->media(), content1);
+ QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia));
+ QCOMPARE(stateSpy.count(), 2);
+ QCOMPARE(mediaSpy.count(), 1);
+
+ // Test stopping doesn't change the current media.
+ m_player->stop();
+ QCOMPARE(m_player->media(), content1);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(stateSpy.count(), 3);
+ QCOMPARE(mediaSpy.count(), 1);
+
+ // Test when the player service reaches the end of the current media, the player moves onto
+ // the next item without stopping.
+ m_player->play();
+ QCOMPARE(m_player->media(), content1);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 4);
+ QCOMPARE(mediaSpy.count(), 1);
+
+ WAIT_FOR_CONDITION(mediaSpy.count(), 2);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->media(), content2);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia));
+ QCOMPARE(stateSpy.count(), 6);
+ QCOMPARE(mediaSpy.count(), 2);
+
+ // Test skipping the current media doesn't change the state.
+ playlist->next();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->media(), content3);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia));
+ QCOMPARE(stateSpy.count(), 6);
+ QCOMPARE(mediaSpy.count(), 3);
+
+ // Test changing the current media while paused doesn't change the state.
+ m_player->pause();
+ QCOMPARE(m_player->media(), content3);
+ QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia));
+ QCOMPARE(stateSpy.count(), 7);
+ QCOMPARE(mediaSpy.count(), 3);
+
+ playlist->previous();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->media(), content2);
+ QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia));
+ QCOMPARE(stateSpy.count(), 7);
+ QCOMPARE(mediaSpy.count(), 4);
+
+ // Test changing the current media while stopped doesn't change the state.
+ m_player->stop();
+ QCOMPARE(m_player->media(), content2);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(stateSpy.count(), 8);
+ QCOMPARE(mediaSpy.count(), 4);
+
+ playlist->next();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->media(), content3);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(stateSpy.count(), 8);
+ QCOMPARE(mediaSpy.count(), 5);
+
+ // Test the player is stopped and the current media cleared when it reaches the end of the last
+ // item in the playlist.
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->media(), content3);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia));
+ QCOMPARE(stateSpy.count(), 9);
+ QCOMPARE(mediaSpy.count(), 5);
+
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);
+ QCOMPARE(m_player->media(), QMediaContent());
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::NoMedia);
+ QCOMPARE(stateSpy.count(), 10);
+ QCOMPARE(mediaSpy.count(), 6);
+
+ // Test starts playing from the start of the playlist if there is no current media selected.
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->media(), content0);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia));
+ QCOMPARE(stateSpy.count(), 11);
+ QCOMPARE(mediaSpy.count(), 7);
+
+ // Test deleting the playlist stops the player and clears the media it set.
+ delete playlist;
+ QCOMPARE(m_player->media(), QMediaContent());
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::NoMedia);
+ QCOMPARE(stateSpy.count(), 12);
+ QCOMPARE(mediaSpy.count(), 8);
+
+ // Test the player works as normal with the playlist removed.
+ m_player->play();
+ QCOMPARE(m_player->media(), QMediaContent());
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::NoMedia);
+ QCOMPARE(stateSpy.count(), 12);
+ QCOMPARE(mediaSpy.count(), 8);
+
+ m_player->setMedia(content1);
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia)
+ QCOMPARE(m_player->media(), content1);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia));
+ QCOMPARE(stateSpy.count(), 13);
+ QCOMPARE(mediaSpy.count(), 9);
+ m_player->stop();
+ runonce = true;
+ }
+}
+
+void tst_QMediaPlayer_s60::testStreamControl()
+{
+ QFETCH_GLOBAL(bool, valid);
+ QFETCH_GLOBAL(bool, streamable);
+ QFETCH_GLOBAL(QMediaContent, mediaContent);
+ QFETCH_GLOBAL(QMediaPlayer::State, state);
+ QFETCH_GLOBAL(bool, videoAvailable);
+ QFETCH_GLOBAL(bool, audioAvailable);
+
+ QMediaStreamsControl* m_streamControl = (QMediaStreamsControl*)(m_player->service()->requestControl(QMediaStreamsControl_iid));
+ if(m_streamControl) {
+ if (valid || streamable) {
+ if (audioAvailable && !videoAvailable) {
+ QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged()));
+ m_player->setMedia(mediaContent);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia));
+ QVERIFY(m_streamControl->streamCount() == 1);
+ QVERIFY(m_streamControl->streamType(1) == QMediaStreamsControl::AudioStream);
+ QVERIFY(m_streamControl->isActive(1) == true);
+ QCOMPARE(streamInfoSpy.count(), 1);
+ }else if (audioAvailable && videoAvailable){
+ QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged()));
+ m_player->setMedia(mediaContent);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia));
+ QVERIFY(m_streamControl->streamCount() == 2);
+ QVERIFY(m_streamControl->streamType(1) == QMediaStreamsControl::VideoStream);
+ QVERIFY(m_streamControl->isActive(2) == true);
+ QCOMPARE(streamInfoSpy.count(), 1);
+ }else if (!audioAvailable && videoAvailable) {
+ QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged()));
+ m_player->setMedia(mediaContent);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia));
+ QVERIFY(m_streamControl->streamCount() == 1);
+ QVERIFY(m_streamControl->streamType(1) == QMediaStreamsControl::VideoStream);
+ QVERIFY(m_streamControl->isActive(2) == true);
+ QCOMPARE(streamInfoSpy.count(), 1);
+ }
+
+ // Test that streamsChanged signal do not get emitted when adding same media
+ QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged()));
+ m_player->setMedia(mediaContent);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia));
+ QCOMPARE(streamInfoSpy.count(), 0);
+ }
+ }
+}
diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer_s60.h b/tests/auto/qmediaplayer/tst_qmediaplayer_s60.h
new file mode 100755
index 000000000..1ebe42588
--- /dev/null
+++ b/tests/auto/qmediaplayer/tst_qmediaplayer_s60.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 TST_QMEDIAPLAYER_S60_H
+#define TST_QMEDIAPLAYER_S60_H
+
+#include <QtTest/QtTest>
+#include <QtCore>
+#include <QtGui>
+#include <QFile>
+
+#include <QMediaPlayer>
+#include <QMediaPlayerControl>
+#include <QMediaPlaylist>
+#include <QMediaService>
+#include <QMediaStreamsControl>
+#include <QVideoWidget>
+
+QT_USE_NAMESPACE
+
+#define WAIT_FOR_CONDITION(a,e) \
+ for (int _i = 0; _i < 500; _i += 1) { \
+ if ((a) == (e)) break; \
+ QTest::qWait(10);}
+
+
+#define WAIT_LONG_FOR_CONDITION(a,e) \
+ for (int _i = 0; _i < 1800; _i += 1) { \
+ if ((a) == (e)) break; \
+ QTest::qWait(100);}
+
+class mediaStatusList : public QObject, public QList<QMediaPlayer::MediaStatus>
+{
+ Q_OBJECT
+public slots:
+ void mediaStatus(QMediaPlayer::MediaStatus status) {
+ append(status);
+ }
+
+public:
+ mediaStatusList(QObject *obj, const char *aSignal)
+ : QObject()
+ {
+ connect(obj, aSignal, this, SLOT(mediaStatus(QMediaPlayer::MediaStatus)));
+ }
+};
+
+class MockProvider_s60 : public QMediaServiceProvider
+{
+public:
+ MockProvider_s60(QMediaService *service):mockService(service) {}
+ QMediaService *requestService(const QByteArray &, const QMediaServiceProviderHint &)
+ {
+ return mockService;
+ }
+
+ void releaseService(QMediaService *service) { delete service; }
+
+ QMediaService *mockService;
+};
+
+class tst_QMediaPlayer_s60: public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase_data();
+ void initTestCase_data_default_winscw();
+ void initTestCase_data_default_armv5();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void testNullService();
+ void testMedia();
+ void testDuration();
+ void testPosition();
+ void testPositionWhilePlaying();
+ void testVolume();
+ void testVolumeWhilePlaying();
+ void testMuted();
+ void testMutedWhilePlaying();
+ void testVideoAndAudioAvailability();
+ void testError();
+ void testPlay();
+ void testPause();
+ void testStop();
+ void testMediaStatus();
+ void testPlaylist();
+ void testStreamControl();
+
+private:
+ QMediaPlayer *m_player;
+ QVideoWidget *m_widget;
+ bool runonce;
+};
+
+#endif // TST_QMEDIAPLAYER_S60_H
diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer_xa.cpp b/tests/auto/qmediaplayer/tst_qmediaplayer_xa.cpp
new file mode 100644
index 000000000..403fe5457
--- /dev/null
+++ b/tests/auto/qmediaplayer/tst_qmediaplayer_xa.cpp
@@ -0,0 +1,1413 @@
+/****************************************************************************
+**
+** 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 "tst_QMediaPlayer_xa.h"
+
+QT_USE_NAMESPACE
+
+#define QTEST_MAIN_XA(TestObject) \
+ int main(int argc, char *argv[]) { \
+ char *new_argv[3]; \
+ QApplication app(argc, argv); \
+ \
+ QString str = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + ".log"; \
+ QByteArray bytes = str.toAscii(); \
+ \
+ char arg1[] = "-o"; \
+ \
+ new_argv[0] = argv[0]; \
+ new_argv[1] = arg1; \
+ new_argv[2] = bytes.data(); \
+ \
+ TestObject tc; \
+ return QTest::qExec(&tc, 3, new_argv); \
+ }
+
+#define WAIT_FOR_CONDITION(a,e) \
+ for (int _i = 0; _i < 500; _i += 1) { \
+ if ((a) == (e)) break; \
+ QTest::qWait(10);}
+
+#define WAIT_FOR_EITHER_CONDITION(a,e,f) \
+ for (int _i = 0; _i < 500; _i += 1) { \
+ if (((a) == (e)) || ((a) == (f))) break; \
+ QTest::qWait(10);}
+
+#define WAIT_FOR_CONDITION1(a) \
+ for (int _i = 0; _i < 500; _i += 1) { \
+ if (a) break; \
+ QTest::qWait(10);}
+
+
+#define WAIT_LONG_FOR_CONDITION(a,e) \
+ for (int _i = 0; _i < 1800; _i += 1) { \
+ if ((a) == (e)) break; \
+ QTest::qWait(10);}
+
+#define WAIT_LONG_FOR_CONDITION1(a) \
+ for (int _i = 0; _i < 1800; _i += 1) { \
+ if (a) break; \
+ QTest::qWait(100);}
+
+tst_QMediaPlayer_xa::tst_QMediaPlayer_xa(): m_player(NULL), m_widget(NULL), m_windowWidget(NULL)
+{
+ audioOnlyContent = new QMediaContent(QUrl("file:///C:/data/testfiles/test.mp3"));
+ videoOnlyContent = new QMediaContent(QUrl("file:///C:/data/testfiles/test_video.3gp"));
+ audioVideoContent = new QMediaContent(QUrl("file:///C:/data/testfiles/test.3gp"));
+ audioVideoAltContent = new QMediaContent(QUrl("file:///C:/data/testfiles/test_alt.3gp"));
+ //streamingContent = new QMediaContent(QUrl("rtsp://10.48.2.51/Copyright_Free_Test_Content/Clips/Video/3GP/176x144/h263/h263_176x144_15fps_384kbps_AAC-LC_128kbps_mono_44.1kHz.3gp"));
+ streamingContent3gp = new QMediaContent(QUrl("http://www.mobileplayground.co.uk/video/Crazy Frog.3gp"));
+ audioStreamingContent = new QMediaContent(QUrl("http://myopusradio.com:8000/easy"));
+ mediaContent = audioVideoContent;
+}
+
+tst_QMediaPlayer_xa::~tst_QMediaPlayer_xa()
+{
+ delete audioOnlyContent;
+ delete videoOnlyContent;
+ delete audioVideoContent;
+ delete audioVideoAltContent;
+}
+
+void tst_QMediaPlayer_xa::initTestCase_data()
+{
+}
+
+void tst_QMediaPlayer_xa::initTestCase()
+{
+ m_player = new QMediaPlayer();
+
+ // Symbian back end needs coecontrol for creation.
+ m_widget = new QVideoWidget();
+ m_widget->setGeometry ( 0, 100, 350, 250 );
+ m_player->setVideoOutput(m_widget);
+ m_widget->showNormal();
+}
+
+void tst_QMediaPlayer_xa::cleanupTestCase()
+{
+ delete m_player;
+ delete m_widget;
+ delete m_windowWidget;
+}
+
+void tst_QMediaPlayer_xa::resetPlayer()
+{
+ delete m_player;
+ m_player = new QMediaPlayer();
+ m_player->setVideoOutput(m_widget);
+}
+
+void tst_QMediaPlayer_xa::resetPlayer_WindowControl()
+{
+ delete m_player;
+ m_player = new QMediaPlayer();
+
+ if(!m_windowWidget) {
+ m_windowWidget = new QWidget();
+ m_windowWidget->showMaximized();
+ }
+
+ QVideoWindowControl* windowControl = (QVideoWindowControl*)(m_player->service()->requestControl(QVideoWindowControl_iid));
+ if (windowControl)
+ windowControl->setWinId(m_windowWidget->winId());
+}
+
+void tst_QMediaPlayer_xa::init()
+{
+ qRegisterMetaType<QMediaPlayer::State>("QMediaPlayer::State");
+ qRegisterMetaType<QMediaPlayer::Error>("QMediaPlayer::Error");
+ qRegisterMetaType<QMediaPlayer::MediaStatus>("QMediaPlayer::MediaStatus");
+ qRegisterMetaType<QMediaContent>("QMediaContent");
+ updateLog("QT MediaPlayer Auto Test Cases", true);
+}
+
+void tst_QMediaPlayer_xa::cleanup()
+{
+}
+
+
+void tst_QMediaPlayer_xa::testMedia()
+{
+ updateLog("*****testMedia");
+
+ setAudioVideoContent();
+
+ QTest::qWait(500);
+ QCOMPARE(m_player->media(), *mediaContent);
+
+ updateLog("*****testMedia: PASSED");
+}
+
+
+void tst_QMediaPlayer_xa::testDuration()
+{
+ updateLog("*****testDuration");
+
+ resetPlayer();
+
+ QSignalSpy spy(m_player, SIGNAL(durationChanged(qint64)));
+ setAudioVideoContent();
+
+ WAIT_FOR_CONDITION1(spy.count()>0);
+
+ QVERIFY(m_player->duration() == duration);
+
+ updateLog("*****testDuration: PASSED");
+}
+
+void tst_QMediaPlayer_xa::testPosition()
+{
+ updateLog("*****testPosition");
+ resetPlayer();
+
+ qint64 position = 60000;
+ setAudioVideoContent();
+
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ QCOMPARE(m_player->isSeekable(), true);
+
+ // preset position
+ {
+ QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->setPosition(position);
+ WAIT_FOR_CONDITION(spy.count(), 1);
+ QCOMPARE(m_player->position(), position);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toLongLong(), position);
+ }
+
+ // same pos second time
+ {
+ QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->setPosition(position);
+ QCOMPARE(m_player->position(), position);
+ QCOMPARE(spy.count(), 0);
+ }
+
+ //zero pos
+ {
+ QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->setPosition(0);
+ QCOMPARE(m_player->position(), qint64(0));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toLongLong(), qint64(0));
+ }
+
+ //end pos
+ {
+ QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->setPosition(duration);
+ QCOMPARE(m_player->position(), duration);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toLongLong(), duration);
+ }
+
+ //negative pos
+ {
+ QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->setPosition(qint64(-1));
+ QCOMPARE(m_player->position(), qint64(0));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toLongLong(), qint64(0));
+ }
+
+ //over duration
+ {
+ QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->setPosition(duration+1);
+ QCOMPARE(m_player->position(), duration);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toLongLong(), duration);
+ }
+
+}
+
+
+void tst_QMediaPlayer_xa::testPositionWhilePlaying()
+{
+ updateLog("*****testPositionWhilePlaying");
+ resetPlayer();
+
+ qint64 position = 60000;
+
+ setAudioVideoContent();
+
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ // preset position
+ {
+ QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ m_player->setPosition(position);
+ WAIT_FOR_CONDITION1(spy.count()>0);
+ QVERIFY(m_player->mediaStatus() == QMediaPlayer::BufferingMedia || m_player->mediaStatus() == QMediaPlayer::BufferedMedia);
+
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QVERIFY(m_player->position()>=position);
+ QVERIFY(spy.count()!=0);
+ }
+
+ //reset position
+ m_player->stop();
+ m_player->setPosition(position);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ //zero pos
+ { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64)));
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ m_player->setPosition(0);
+ WAIT_FOR_CONDITION1(spy.count()>0);
+ QVERIFY(m_player->mediaStatus() == QMediaPlayer::BufferingMedia ||
+ m_player->mediaStatus() == QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QVERIFY(m_player->position() >= qint64(0));
+ QVERIFY(spy.count()!=0);
+ }
+
+ //reset position
+ m_player->stop();
+ m_player->setPosition(position);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ updateLog("*****testPositionWhilePlaying: PASSED");
+}
+
+
+void tst_QMediaPlayer_xa::testVolume()
+{
+ updateLog("*****testVolume");
+
+ int volume = 20;
+
+ // preset volume
+ {
+ QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(volume);
+ QCOMPARE(m_player->volume(), volume);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);
+ }
+
+ // same volume
+ {
+ QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ int currentVolume = m_player->volume();
+ m_player->setVolume(currentVolume);
+ QCOMPARE(m_player->volume(), currentVolume);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 0);
+ }
+
+ // zero volume
+ {
+ QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(0);
+ QCOMPARE(m_player->volume(), 0);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);
+ }
+
+ // max volume
+ {
+ QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(100);
+ QCOMPARE(m_player->volume(), 100);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);
+ }
+
+ // negative volume
+ {
+ QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(int(-1));
+ QCOMPARE(m_player->volume(), 0);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);
+ }
+
+ // over max volume
+ {
+ QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(1000);
+ QCOMPARE(m_player->volume(), 100);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);
+ }
+
+ updateLog("*****testVolume: PASSED");
+}
+
+void tst_QMediaPlayer_xa::testVolumeWhilePlaying()
+{
+ updateLog("*****testVideoAndAudioAvailability");
+ resetPlayer();
+
+ int volume = 20;
+
+ setAudioVideoContent();
+
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+
+ m_player->play();
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ // preset volume
+ {
+ QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(volume);
+ QCOMPARE(m_player->volume(), volume);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);
+ }
+
+ // same volume
+ {
+ QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ int currentVolume = m_player->volume();
+ m_player->setVolume(currentVolume);
+ QCOMPARE(m_player->volume(), currentVolume);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 0);
+ }
+
+ // zero volume
+ {
+ QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(0);
+ QCOMPARE(m_player->volume(), 0);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);
+ }
+
+ // max volume
+ {
+ QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(100);
+ QCOMPARE(m_player->volume(), 100);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);
+ }
+
+ // negative volume
+ {
+ QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(int(-1));
+ QCOMPARE(m_player->volume(), 0);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);
+ }
+
+ // over max volume
+ {
+ QSignalSpy spy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setVolume(1000);
+ QCOMPARE(m_player->volume(), 100);
+ QCOMPARE(m_player->isMuted(), false);
+ QCOMPARE(spy.count(), 1);
+ }
+
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ updateLog("*****testVideoAndAudioAvailability: PASSED");
+}
+
+
+void tst_QMediaPlayer_xa::testMuted()
+{
+ updateLog("*****testMuted");
+
+ int volume = 20;
+
+ //reset mute & volume
+ m_player->setMuted(false);
+ m_player->setVolume(0);
+ QVERIFY(m_player->isMuted() == false);
+ QCOMPARE(m_player->volume(), 0);
+
+ // set muted
+ {
+ QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool)));
+ m_player->setMuted(true);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_player->isMuted() == true);
+ }
+
+ // set muted again
+ {
+ QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool)));
+ m_player->setMuted(true);
+ QCOMPARE(spy.count(), 0);
+ QVERIFY(m_player->isMuted() == true);
+ }
+
+ // unmute
+ {
+ QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool)));
+ m_player->setMuted(false);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_player->isMuted() == false);
+ }
+
+ // set volume while muted
+ {
+ QSignalSpy muteSpy(m_player, SIGNAL(mutedChanged(bool)));
+ QSignalSpy volumeSpy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setMuted(true);
+ m_player->setVolume(volume);
+ QCOMPARE(m_player->volume(), volume);
+ QCOMPARE(muteSpy.count(), 1);
+ QCOMPARE(volumeSpy.count(), 1);
+ QVERIFY(m_player->isMuted() == true);
+ }
+
+ updateLog("*****testMuted: PASSED");
+}
+
+void tst_QMediaPlayer_xa::testMutedWhilePlaying()
+{
+ updateLog("*****testMutedWhilePlaying");
+ resetPlayer();
+
+ int volume = 20;
+
+ setAudioVideoContent();
+
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+
+ //reset mute & volume
+ m_player->setMuted(false);
+ m_player->setVolume(65);
+ QVERIFY(m_player->isMuted() == false);
+ QCOMPARE(m_player->volume(), 65);
+
+ m_player->play();
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ // set muted
+ {
+ QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool)));
+ m_player->setMuted(true);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_player->isMuted() == true);
+ }
+
+ // set muted again
+ {
+ QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool)));
+ m_player->setMuted(true);
+ QCOMPARE(spy.count(), 0);
+ QVERIFY(m_player->isMuted() == true);
+ }
+
+ // unmute
+ {
+ QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool)));
+ m_player->setMuted(false);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_player->isMuted() == false);
+ }
+
+ // set volume while muted
+ {
+ QSignalSpy muteSpy(m_player, SIGNAL(mutedChanged(bool)));
+ QSignalSpy volumeSpy(m_player, SIGNAL(volumeChanged(int)));
+ m_player->setMuted(true);
+ m_player->setVolume(volume);
+ QCOMPARE(m_player->volume(), volume);
+ QCOMPARE(muteSpy.count(), 1);
+ QCOMPARE(volumeSpy.count(), 1);
+ QVERIFY(m_player->isMuted() == true);
+ }
+
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+
+ updateLog("*****testMutedWhilePlaying: PASSED");
+}
+
+void tst_QMediaPlayer_xa::testVideoAndAudioAvailability()
+{
+ updateLog("*****testVideoAndAudioAvailability");
+ resetPlayer();
+
+ QList<QVariant> arguments;
+
+
+ setVideoOnlyContent();
+
+
+ QSignalSpy audioAvailableSpy(m_player, SIGNAL(audioAvailableChanged(bool)));
+ QSignalSpy videoAvailableSpy(m_player, SIGNAL(videoAvailableChanged(bool)));
+
+ setAudioOnlyContent();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ updateLog("SetMedia: audioOnlyContent");
+ WAIT_FOR_CONDITION(m_player->isAudioAvailable(), true);
+ updateLog("\t isAudioAvailable() == true");
+ QVERIFY(m_player->isVideoAvailable() == false);
+ updateLog("\t isVideoAvailable() == false");
+ QCOMPARE(audioAvailableSpy.count(), 1);
+ arguments = audioAvailableSpy.takeFirst();
+ QVERIFY(arguments.at(0).toBool() == true);
+ updateLog("\t audioAvailableChanged(true)");
+ QCOMPARE(videoAvailableSpy.count(), 1);
+ arguments = videoAvailableSpy.takeFirst();
+ QVERIFY(arguments.at(0).toBool() == false);
+ updateLog("\t videoAvailableChanged(false)");
+
+ setVideoOnlyContent();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ updateLog("SetMedia: videoOnlyContent");
+ WAIT_FOR_CONDITION(m_player->isVideoAvailable(), true);
+ updateLog("\t isVideoAvailable() == true");
+ QVERIFY(m_player->isAudioAvailable() == false);
+ updateLog("\t isAudioAvailable() == false");
+ QCOMPARE(audioAvailableSpy.count(), 1);
+ arguments = audioAvailableSpy.takeFirst();
+ QVERIFY(arguments.at(0).toBool() == false);
+ updateLog("\t audioAvailableChanged(false)");
+ QCOMPARE(videoAvailableSpy.count(), 1);
+ arguments = videoAvailableSpy.takeFirst();
+ QVERIFY(arguments.at(0).toBool() == true);
+ updateLog("\t videoAvailableChanged(true)");
+
+ setAudioVideoContent();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ updateLog("SetMedia: audioVideoContent");
+ WAIT_FOR_CONDITION(m_player->isAudioAvailable(), true);
+ updateLog("\t isAudioAvailable() == true");
+ QCOMPARE(audioAvailableSpy.count(), 1);
+ arguments = audioAvailableSpy.takeFirst();
+ QVERIFY(arguments.at(0).toBool() == true);
+ updateLog("\t audioAvailableChanged(true)");
+ QCOMPARE(videoAvailableSpy.count(), 0);
+
+ updateLog("*****testVideoAndAudioAvailability: PASSED");
+
+}
+
+void tst_QMediaPlayer_xa::testStreamInformation()
+{
+ updateLog("*****testStreamInformation");
+ resetPlayer();
+ QMediaStreamsControl* m_streamControl = (QMediaStreamsControl*)(m_player->service()->requestControl(QMediaStreamsControl_iid));
+ setVideoOnlyContent();
+
+ if(m_streamControl)
+ {
+ {
+ QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged()));
+ setAudioOnlyContent();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVERIFY(m_streamControl->streamCount() == 1);
+ QCOMPARE(streamInfoSpy.count(), 1);
+ }
+
+ {
+ QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged()));
+ setAudioVideoContent();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVERIFY(m_streamControl->streamCount() == 2);
+ QCOMPARE(streamInfoSpy.count(), 1);
+ }
+
+ {
+ QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged()));
+ setAudioVideoContent(); //set alternate content
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVERIFY(m_streamControl->streamCount() == 2);
+ QCOMPARE(streamInfoSpy.count(), 1);
+ }
+
+ {
+ QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged()));
+ setVideoOnlyContent();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVERIFY(m_streamControl->streamCount() == 1);
+ QCOMPARE(streamInfoSpy.count(), 1);
+ }
+
+ updateLog("*****testStreamInformation: PASSED");
+ }
+}
+
+void tst_QMediaPlayer_xa::testPlay()
+{
+ updateLog("*****testPlay");
+ resetPlayer();
+
+ setAudioVideoContent();
+
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVERIFY(m_player->media() == *mediaContent);
+ QSignalSpy spy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->play();
+
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+
+ //Play->Play
+ {
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->play();
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 0);
+ }
+
+ //Play->Pause
+ {
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->pause();
+ QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QCOMPARE(stateSpy.count(), 1);
+ }
+
+ //Play->Stop
+ {
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.count(), 1);
+ }
+
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ updateLog("*****testPlay: PASSED");
+}
+
+void tst_QMediaPlayer_xa::testPause()
+{
+ updateLog("*****testPause");
+ resetPlayer();
+
+ setAudioVideoContent();
+
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVERIFY(m_player->media() == *mediaContent);
+ QSignalSpy spy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->pause();
+ // at present there is no support for stop->pause state transition. TODO: uncomment when support added
+ //QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ //QCOMPARE(spy.count(), 1);
+
+ //Pause->Play
+ {
+ //QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->play();
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 1);
+ }
+
+ //Pause->Pause
+ {
+ m_player->pause();
+ QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->pause();
+ QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QCOMPARE(stateSpy.count(), 0);
+ }
+
+ //Pause->Stop
+ {
+ QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.count(), 1);
+ }
+
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ updateLog("*****testPause: PASSED");
+
+}
+
+void tst_QMediaPlayer_xa::testStop()
+{
+ updateLog("*****testStop");
+ resetPlayer();
+ setAudioVideoContent();
+
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVERIFY(m_player->media() == *mediaContent);
+
+ QSignalSpy spy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->stop();
+
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(spy.count(), 0);
+
+ //Stop->Play
+ {
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->play();
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ QCOMPARE(stateSpy.count(), 1);
+ }
+ // at present there is no support for stop->pause state transition. TODO: uncomment when support added
+ //Stop->Pause
+/* {
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->pause();
+ QCOMPARE(m_player->state(), QMediaPlayer::PausedState);
+ QCOMPARE(stateSpy.count(), 1);
+ }
+*/
+ //Stop->Stop
+ {
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(stateSpy.count(), 0);
+ }
+
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ updateLog("*****testStop: PASSED");
+}
+
+void tst_QMediaPlayer_xa::testMediaStatus()
+{
+ updateLog("*****testMediaStatus");
+ resetPlayer();
+
+ QSignalSpy statusSpy(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+
+ setAudioVideoContent();
+
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVERIFY(statusSpy.count()>0);
+
+ {
+ QSignalSpy statusSpy(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QVERIFY(statusSpy.count()>0);
+ }
+
+ {
+ QSignalSpy statusSpy(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ m_player->setPosition(duration - 10);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);
+ QVERIFY(statusSpy.count()>0);
+ }
+
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ updateLog("*****testMediaStatus: PASSED");
+}
+
+void tst_QMediaPlayer_xa::testBufferStatus()
+{
+ updateLog("*****testBufferStatus");
+ resetPlayer();
+ m_player->setNotifyInterval(50); //Since default interval is 1 sec,could not receive any bufferStatusChanged SIGNAL,hence checking for 50milliseconds
+ QSignalSpy spy(m_player, SIGNAL(bufferStatusChanged(int)));
+ // setStreamingContent();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ WAIT_FOR_CONDITION(m_player->bufferStatus(), 100);
+ QVERIFY(spy.count()>0);
+ updateLog("*****testBufferStatus: PASSED");
+}
+
+void tst_QMediaPlayer_xa::testPlaybackRate()
+{
+ updateLog("*****testPlaybackRate");
+
+ resetPlayer();
+
+ qreal playbackRate = 1.5;
+
+ setAudioVideoContent();
+
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+
+ m_player->setPlaybackRate(playbackRate);
+ QVERIFY(m_player->playbackRate() == playbackRate);
+
+ QSignalSpy spy(m_player, SIGNAL(playbackRateChanged(qreal)));
+ m_player->setPlaybackRate(playbackRate + 0.5f);
+ QCOMPARE(m_player->playbackRate(), playbackRate + 0.5f);
+ QCOMPARE(spy.count(), 1);
+
+ updateLog("*****testPlaybackRate: PASSED");
+}
+
+void tst_QMediaPlayer_xa::testPlaybackRateWhilePlaying()
+{
+ updateLog("*****testPlaybackRateWhilePlaying");
+ resetPlayer();
+
+ qreal playbackRate = 1.5;
+
+ setAudioVideoContent();
+
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ m_player->setPlaybackRate(playbackRate);
+ QVERIFY(m_player->playbackRate() == playbackRate);
+
+ QSignalSpy spy(m_player, SIGNAL(playbackRateChanged(qreal)));
+ m_player->setPlaybackRate(playbackRate + 0.5f);
+ QCOMPARE(m_player->playbackRate(), playbackRate + 0.5f);
+ QCOMPARE(spy.count(), 1);
+
+ updateLog("*****testPlaybackRateWhilePlaying: PASSED");
+}
+
+void tst_QMediaPlayer_xa::testSeekable()
+{
+ updateLog("*****testBufferStatus");
+ resetPlayer();
+ QSignalSpy spy(m_player, SIGNAL(seekableChanged(bool)));
+ setAudioVideoContent();
+ qint64 position = 1000;
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVERIFY(m_player->isSeekable()==true);
+ m_player->setPosition(position);
+ QCOMPARE(spy.count(), 0);
+ QVERIFY(m_player->isSeekable()==true);
+
+ updateLog("*****testBufferStatus: PASSED");
+
+}
+
+void tst_QMediaPlayer_xa::testAspectRatioMode()
+{
+ updateLog("*****testBufferStatus");
+ resetPlayer();
+ setAudioVideoContent();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVideoWidgetControl* m_videoWidgetControl = (QVideoWidgetControl*)(m_player->service()->requestControl(QVideoWidgetControl_iid));
+
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ QCOMPARE(m_videoWidgetControl->aspectRatioMode(), Qt::KeepAspectRatio); //default
+
+ QTest::qWait(5000); //wait for 5 seconds
+
+ {
+ m_videoWidgetControl->setAspectRatioMode(Qt::IgnoreAspectRatio);
+ QCOMPARE(m_videoWidgetControl->aspectRatioMode(), Qt::IgnoreAspectRatio);
+ QTest::qWait(5000); //wait for 5 seconds
+ }
+
+ {
+ m_videoWidgetControl->setAspectRatioMode(Qt::KeepAspectRatioByExpanding);
+ QCOMPARE(m_videoWidgetControl->aspectRatioMode(), Qt::KeepAspectRatioByExpanding);
+ QTest::qWait(5000); //wait for 5 seconds
+ }
+ {
+ m_videoWidgetControl->setAspectRatioMode(Qt::KeepAspectRatio);
+ QCOMPARE(m_videoWidgetControl->aspectRatioMode(), Qt::KeepAspectRatio);
+ QTest::qWait(5000); //wait for 5 seconds
+ }
+
+ updateLog("*****testBufferStatus: PASSED");
+
+}
+
+void tst_QMediaPlayer_xa::testFullScreen()
+{
+ updateLog("*****testFullScreen");
+ resetPlayer();
+ setAudioVideoContent();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVideoWidgetControl* m_videoWidgetControl = (QVideoWidgetControl*)(m_player->service()->requestControl(QVideoWidgetControl_iid));
+
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ //m_widget->resize(50, 50);
+ m_widget->showNormal();
+ QTest::qWait(10000); //wait for 5 seconds
+
+
+ if(m_videoWidgetControl)
+ {
+ QSignalSpy spy(m_videoWidgetControl, SIGNAL(fullScreenChanged(bool)));
+ m_videoWidgetControl->setFullScreen(true);
+ QTest::qWait(10000); //wait for 5 seconds
+ QCOMPARE(m_videoWidgetControl->isFullScreen(), true);
+ QCOMPARE(spy.count(), 1);
+ }
+
+
+ if(m_videoWidgetControl)
+ {
+ QSignalSpy spy(m_videoWidgetControl, SIGNAL(fullScreenChanged(bool)));
+ m_videoWidgetControl->setFullScreen(false);
+ QCOMPARE(m_videoWidgetControl->isFullScreen(), false);
+ QTest::qWait(10000); //wait for 5 seconds
+ QCOMPARE(spy.count(), 1);
+ }
+
+ updateLog("*****testFullScreen: PASSED");
+}
+
+void tst_QMediaPlayer_xa::testWindowControl_NativeSize()
+{
+ updateLog("*****testWindowControl_NativeSize");
+ resetPlayer_WindowControl();
+ setAudioVideoContent();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVERIFY(m_player->media() == *mediaContent);
+ m_player->play();
+ WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState);
+ QVideoWindowControl* windowControl = (QVideoWindowControl*)(m_player->service()->requestControl(QVideoWindowControl_iid));
+ if (windowControl)
+ {
+ QSize size = windowControl->nativeSize();
+ }
+
+ WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ updateLog("*****testWindowControl_NativeSize: PASSED");
+}
+
+void tst_QMediaPlayer_xa::testWindowControl_AspectRatioMode()
+{
+ updateLog("*****testWindowControl_AspectRatioMode");
+ resetPlayer_WindowControl();
+ setAudioVideoContent();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVideoWindowControl* windowControl = (QVideoWindowControl*)(m_player->service()->requestControl(QVideoWindowControl_iid));
+
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ QCOMPARE(windowControl->aspectRatioMode(), Qt::KeepAspectRatio); //default
+
+ QTest::qWait(5000); //wait for 5 seconds
+
+ {
+ windowControl->setAspectRatioMode(Qt::IgnoreAspectRatio);
+ QCOMPARE(windowControl->aspectRatioMode(), Qt::IgnoreAspectRatio);
+ QTest::qWait(5000); //wait for 5 seconds
+ }
+
+ {
+ windowControl->setAspectRatioMode(Qt::KeepAspectRatioByExpanding);
+ QCOMPARE(windowControl->aspectRatioMode(), Qt::KeepAspectRatioByExpanding);
+ QTest::qWait(5000); //wait for 5 seconds
+ }
+ {
+ windowControl->setAspectRatioMode(Qt::KeepAspectRatio);
+ QCOMPARE(windowControl->aspectRatioMode(), Qt::KeepAspectRatio);
+ QTest::qWait(5000); //wait for 5 seconds
+ }
+
+ updateLog("*****testWindowControl_AspectRatioMode: PASSED");
+
+}
+
+void tst_QMediaPlayer_xa::testWindowControl_FullScreen()
+{
+ updateLog("*****testWindowControl_FullScreen");
+ resetPlayer_WindowControl();
+ setAudioVideoContent();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QVideoWindowControl* windowControl = (QVideoWindowControl*)(m_player->service()->requestControl(QVideoWindowControl_iid));
+
+ m_player->play();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ //m_windowWidget->resize(250, 350);
+ m_windowWidget->showNormal();
+ QTest::qWait(10000); //wait for 5 seconds
+
+ if(windowControl)
+ {
+ QSignalSpy spy(windowControl, SIGNAL(fullScreenChanged(bool)));
+ windowControl->setFullScreen(true);
+ QTest::qWait(10000); //wait for 5 seconds
+ QCOMPARE(windowControl->isFullScreen(), true);
+ QCOMPARE(spy.count(), 1);
+ }
+
+
+ if(windowControl)
+ {
+ QSignalSpy spy(windowControl, SIGNAL(fullScreenChanged(bool)));
+ windowControl->setFullScreen(false);
+ QCOMPARE(windowControl->isFullScreen(), false);
+ QTest::qWait(10000); //wait for 5 seconds
+ QCOMPARE(spy.count(), 1);
+ }
+
+ updateLog("*****testWindowControl_FullScreen: PASSED");
+}
+
+
+//adding access-point testcase
+
+
+void tst_QMediaPlayer_xa::testSetconfigurationsAP()
+{
+ updateLog("*****testSetconfigurationsAP");
+ resetPlayer();
+
+ //Passing only valid Accesspoint in QList
+ QList<QNetworkConfiguration> configs;
+ accesspointlist = manager.allConfigurations();
+ for (int i=0; i<=accesspointlist.size()-1;i++)
+ qDebug()<<"accesspointlist"<< accesspointlist.at(i).name();
+ configs<<accesspointlist.at(8);
+ QSignalSpy spy(m_player, SIGNAL(networkConfigurationChanged(const QNetworkConfiguration&)));
+ m_player->setNetworkConfigurations(configs);
+ setStreamingContent3gp();
+ m_player->play();
+ QTest::qWait(100000);
+ WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(8).name());
+ updateLog("*****testSetconfigurationsAP: PASSED");
+
+}
+
+
+void tst_QMediaPlayer_xa::testSetAccesspoint()
+{
+ updateLog("*****testSetAccesspoint");
+ resetPlayer();
+ QList<QNetworkConfiguration> configs;
+ accesspointlist = manager.allConfigurations();
+ configs<<accesspointlist.at(0);
+ configs<<accesspointlist.at(3);
+ configs<<accesspointlist.at(10);
+ configs<<accesspointlist.at(8);
+ //Passing only valid Accesspoint in QList
+ QSignalSpy spy(m_player, SIGNAL(networkConfigurationChanged(const QNetworkConfiguration&)));
+ m_player->setNetworkConfigurations(configs);
+
+ setStreamingContent3gp();
+ QTest::qWait(200000);
+ m_player->play();
+ QTest::qWait(10000);
+ WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(8).name());
+
+ updateLog("*****testSetAccesspoint: PASSED");
+}
+
+
+void tst_QMediaPlayer_xa::testGetAccesspoint()
+{
+ updateLog("*****testGetAccesspoint");
+ resetPlayer();
+ //getting information about the current configured accesspoint without setting any configurations
+ QNetworkConfiguration getaccespoint;
+ getaccespoint = m_player->currentNetworkConfiguration();
+ QCOMPARE(getaccespoint.name(),QString(""));
+ updateLog("*****testGetAccesspoint: ");
+}
+
+
+void tst_QMediaPlayer_xa::testDiffmediacontentAP()
+{
+ updateLog("*****streaming Different mediacontent files via AP");
+ resetPlayer();
+ QList<QNetworkConfiguration> configs;
+ accesspointlist = manager.allConfigurations();
+ configs<<accesspointlist.at(8);
+ QSignalSpy spy(m_player, SIGNAL(networkConfigurationChanged(const QNetworkConfiguration&)));
+ m_player->setNetworkConfigurations(configs);
+ //first mediacontent file
+ setAudioStreamingContent();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ m_player->play();
+ QTest::qWait(30000);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ //second mediacontent file
+ setStreamingContent3gp();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ m_player->play();
+ QTest::qWait(20000);
+ QCOMPARE(m_player->state(), QMediaPlayer::PlayingState);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+
+ QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(8).name());
+ QNetworkConfiguration getaccespoint;
+ getaccespoint = m_player->currentNetworkConfiguration();
+ QCOMPARE(getaccespoint.name(), QString("MMMW"));
+
+ updateLog("*****testDiffmediacontentAP: PASSED");
+}
+
+
+void tst_QMediaPlayer_xa::testInvalidaddressAP()
+{
+ updateLog("*****testInvalidaddressAP");
+ resetPlayer();
+ //setting all invalid accesspoint
+ QList<QNetworkConfiguration> configs;
+ accesspointlist = manager.allConfigurations();
+ configs<<accesspointlist.at(0);
+ configs<<accesspointlist.at(2);
+ configs<<accesspointlist.at(3);
+ QSignalSpy spy(m_player, SIGNAL(networkConfigurationChanged(const QNetworkConfiguration&)));
+ m_player->setNetworkConfigurations(configs);
+ QNetworkConfiguration getaccespoint;
+ getaccespoint = m_player->currentNetworkConfiguration();
+ QCOMPARE(getaccespoint.name(), QString(""));
+
+ updateLog("*****testInvalidaddressAP: PASSED");
+}
+
+
+
+void tst_QMediaPlayer_xa::testMultipleAccesspoints()
+{
+ updateLog("*****testMultipleAccesspoints");
+ resetPlayer();
+ QList<QNetworkConfiguration> configs;
+ accesspointlist = manager.allConfigurations();
+ configs<<accesspointlist.at(8);
+ QSignalSpy spy(m_player, SIGNAL(networkConfigurationChanged(const QNetworkConfiguration&)));
+ m_player->setNetworkConfigurations(configs);
+ setStreamingContent3gp();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ m_player->play();
+ WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QTest::qWait(20000);
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(8).name());
+ //Second configuration list
+ QList<QNetworkConfiguration> secconfigs;
+ secaccesspoint = manager.allConfigurations();
+ secconfigs<<secaccesspoint.at(5);
+ QSignalSpy spy1(m_player, SIGNAL(networkConfigurationChanged(const QNetworkConfiguration&)));
+ m_player->setNetworkConfigurations(secconfigs);
+ setStreamingContent3gp();
+ // setAudioStreamingContent();
+ QTest::qWait(30000);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ m_player->play();
+ WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QTest::qWait(10000);
+ updateLog("*****testSetAccesspoint: PASSED");
+ QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(5).name());
+ QNetworkConfiguration getaccespoint;
+ getaccespoint = m_player->currentNetworkConfiguration();
+ QCOMPARE(getaccespoint.name(), QString("Mobile Office"));
+
+ updateLog("*****testMultipleAccesspoints: PASSED");
+}
+
+
+void tst_QMediaPlayer_xa::testReconnectAPWhilestreaming()
+{
+ updateLog("*****testReconnectAPWhilestreaming");
+ resetPlayer();
+ QList<QNetworkConfiguration> configs;
+ accesspointlist = manager.allConfigurations();
+ configs<<accesspointlist.at(15);
+ configs<<accesspointlist.at(12);
+ configs<<accesspointlist.at(0);
+ configs<<accesspointlist.at(8);
+ QSignalSpy spy(m_player, SIGNAL(networkConfigurationChanged(const QNetworkConfiguration&)));
+ m_player->setNetworkConfigurations(configs);
+ setAudioStreamingContent();
+ m_player->play();
+ QTest::qWait(200000);
+ configs<<accesspointlist.at(5);
+ m_player->setNetworkConfigurations(configs);
+ m_player->play();
+ QTest::qWait(20000);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);
+ QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(8).name());
+ QNetworkConfiguration getaccespoint;
+ getaccespoint = m_player->currentNetworkConfiguration();
+ QCOMPARE(getaccespoint.name(), QString("MMMW"));
+ updateLog("*****testReconnectAPWhilestreaming: PASSED");
+}
+
+
+void tst_QMediaPlayer_xa::teststreampausestream()
+{
+ updateLog("*****teststreampausestream");
+ resetPlayer();
+ QList<QNetworkConfiguration> configs;
+ accesspointlist = manager.allConfigurations();
+ configs<<accesspointlist.at(8);
+ QSignalSpy spy(m_player, SIGNAL(networkConfigurationChanged(const QNetworkConfiguration&)));
+ m_player->setNetworkConfigurations(configs);
+ setStreamingContent3gp();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ m_player->play();
+ WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QTest::qWait(10000);
+ m_player->pause();
+ WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PausedState);
+
+ //Setting up the accesspoint when the player is in paused state
+ QList<QNetworkConfiguration> secconfigs;
+ secaccesspoint = manager.allConfigurations();
+ secconfigs<<secaccesspoint.at(5);
+ m_player->setNetworkConfigurations(secconfigs);
+ m_player->play();
+ QTest::qWait(20000);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ QCOMPARE((m_player->currentNetworkConfiguration()).name(), accesspointlist.at(8).name());
+ m_player->stop();
+ WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::StoppedState);
+ setStreamingContent3gp();
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia);
+ m_player->play();
+ QTest::qWait(20000);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ m_player->stop();
+ WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(5).name());
+
+ updateLog("*****teststreampausestream: PASSED");
+}
+
+
+
+void tst_QMediaPlayer_xa::testStressAccessPoint()
+{
+ updateLog("*****testStressAccessPoint");
+ resetPlayer();
+ for (int i=0; i<=50; i++) {
+ QList<QNetworkConfiguration> configs;
+ accesspointlist = manager.allConfigurations();
+ configs<<accesspointlist.at(8);
+ QSignalSpy spy(m_player, SIGNAL(networkConfigurationChanged(const QNetworkConfiguration&)));
+ m_player->setNetworkConfigurations(configs);
+ setStreamingContent3gp();
+ m_player->play();
+ QTest::qWait(20000);
+ WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState);
+ WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);
+ m_player->stop();
+ QCOMPARE(m_player->state(), QMediaPlayer::StoppedState);
+ QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(8).name());
+ resetPlayer();
+ }
+
+ updateLog("*****testStressAccessPoint: PASSED");
+}
+
+
+
+void tst_QMediaPlayer_xa::updateLog(QString log, bool delFile)
+{
+ QString logFileName = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_detailed.log";
+ if(delFile)
+ {
+ QFile::remove(logFileName);
+ }
+
+ QFile f(logFileName);
+
+ if( !f.open( QIODevice::WriteOnly | QIODevice::Append ) )
+ {
+ return;
+ }
+
+ QTextStream ts( &f );
+
+ ts<<log<<"\n";
+
+ f.close();
+}
diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer_xa.h b/tests/auto/qmediaplayer/tst_qmediaplayer_xa.h
new file mode 100644
index 000000000..732cbd4bf
--- /dev/null
+++ b/tests/auto/qmediaplayer/tst_qmediaplayer_xa.h
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 TST_QMEDIAPLAYER_XA_H
+#define TST_QMEDIAPLAYER_XA_H
+
+#include <QtTest/QtTest>
+#include <QtCore>
+#include <QtGui>
+#include <QFile>
+
+#include <QMediaPlayer>
+#include <QMediaPlayerControl>
+#include <QMediaService>
+#include <QMediaStreamsControl>
+#include <QVideoWidget>
+#include <QVideoWidgetControl>
+#include <QVideoWindowControl>
+#include <QMetadataReaderControl>
+#include <QtNetwork/qnetworkconfiguration.h>
+#include <QtNetwork/qnetworkconfigmanager.h>
+#include <qmedianetworkaccesscontrol.h>
+
+QT_USE_NAMESPACE
+class mediaStatusList;
+/*
+class mediaStatusList : public QObject, public QList<QMediaPlayer::MediaStatus>
+{
+ Q_OBJECT
+public slots:
+ void mediaStatus(QMediaPlayer::MediaStatus status) {
+ append(status);
+ }
+
+public:
+ mediaStatusList(QObject *obj, const char *aSignal)
+ : QObject()
+ {
+ connect(obj, aSignal, this, SLOT(mediaStatus(QMediaPlayer::MediaStatus)));
+ }
+};
+*/
+class tst_QMediaPlayer_xa: public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QMediaPlayer_xa();
+ ~tst_QMediaPlayer_xa();
+
+private slots:
+ void initTestCase_data();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+ void testMediaStatus();
+ void testBufferStatus();
+ void testPositionWhilePlaying();
+ void testFullScreen();
+ void testWindowControl_FullScreen();
+ void testSeekable();
+ void testStreamInformation();
+ void testAspectRatioMode();
+ void testMedia();
+ void testDuration();
+ void testPosition();
+ void testVolume();
+ void testVolumeWhilePlaying();
+ void testMuted();
+ void testMutedWhilePlaying();
+ void testVideoAndAudioAvailability();
+ void testPlay();
+ void testPause();
+ void testStop();
+ void testPlaybackRate();
+ void testPlaybackRateWhilePlaying();
+ void testWindowControl_NativeSize();
+ void testWindowControl_AspectRatioMode();
+ void testSetconfigurationsAP();
+ void testSetAccesspoint();
+ void testGetAccesspoint();
+ void testDiffmediacontentAP();
+ void testInvalidaddressAP();
+ void testMultipleAccesspoints();
+ void testReconnectAPWhilestreaming();
+ void teststreampausestream();
+ void testStressAccessPoint();
+
+private:
+
+ void resetPlayer();
+ void resetPlayer_WindowControl();
+
+ void updateLog(QString str, bool delFile=false);
+ void setAudioOnlyContent()
+ {
+ mediaContent = audioOnlyContent;
+
+ m_player->setMedia(*mediaContent);
+ }
+
+ void setVideoOnlyContent()
+ {
+ mediaContent = videoOnlyContent;
+ duration = 60000;
+
+ m_player->setMedia(*mediaContent);
+ }
+
+ void setAudioVideoContent()
+ {
+ if (mediaContent == audioVideoContent) {
+ mediaContent = audioVideoAltContent;
+ duration = 101840;
+ } else {
+ mediaContent = audioVideoContent;
+ duration = 141000;
+ }
+ m_player->setMedia(*mediaContent);
+ }
+
+ void setStreamingContent3gp()
+ {
+ mediaContent = streamingContent3gp;
+
+ m_player->setMedia(*mediaContent);
+ }
+
+ void setAudioStreamingContent()
+ {
+ mediaContent = audioStreamingContent;
+
+ m_player->setMedia(*mediaContent);
+ }
+
+
+ QMediaContent* audioOnlyContent;
+ QMediaContent* videoOnlyContent;
+ QMediaContent* audioVideoContent;
+ QMediaContent* audioVideoAltContent;
+ QMediaContent* mediaContent;
+ QMediaContent* streamingContent3gp;
+ QMediaContent* audioStreamingContent;
+ //for access-point requirement
+ QList<QNetworkConfiguration> accesspointlist;
+ QList<QNetworkConfiguration> secaccesspoint;
+ QNetworkConfigurationManager manager;
+
+ qint64 duration;
+ QMediaPlayer *m_player;
+ QVideoWidget *m_widget;
+ QWidget *m_windowWidget;
+};
+
+#endif // TST_QMEDIAPLAYER_XA_H
diff --git a/tests/auto/qmediaplayerbackend/qmediaplayerbackend.pro b/tests/auto/qmediaplayerbackend/qmediaplayerbackend.pro
new file mode 100644
index 000000000..5d6c46b77
--- /dev/null
+++ b/tests/auto/qmediaplayerbackend/qmediaplayerbackend.pro
@@ -0,0 +1,23 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qmediaplayerbackend
+# CONFIG += testcase
+
+symbian*: {
+ PLAYLIST_TESTDATA.sources = testdata/*
+ PLAYLIST_TESTDATA.path = testdata
+ DEPLOYMENT += PLAYLIST_TESTDATA
+}
+
+wince* {
+ DEFINES+= TESTDATA_DIR=\\\"./\\\"
+}else:!symbian {
+ DEFINES += TESTDATA_DIR=\\\"$$PWD/\\\"
+}
+
+SOURCES += \
+ tst_qmediaplayerbackend.cpp
+
+maemo*:CONFIG += insignificant_test
diff --git a/tests/auto/qmediaplayerbackend/testdata/test.wav b/tests/auto/qmediaplayerbackend/testdata/test.wav
new file mode 100644
index 000000000..4dd022661
--- /dev/null
+++ b/tests/auto/qmediaplayerbackend/testdata/test.wav
Binary files differ
diff --git a/tests/auto/qmediaplayerbackend/tst_qmediaplayerbackend.cpp b/tests/auto/qmediaplayerbackend/tst_qmediaplayerbackend.cpp
new file mode 100644
index 000000000..ec46dfa14
--- /dev/null
+++ b/tests/auto/qmediaplayerbackend/tst_qmediaplayerbackend.cpp
@@ -0,0 +1,462 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 <QtTest/QtTest>
+#include <QDebug>
+#include "qmediaservice.h"
+#include "qmediaplayer.h"
+
+//TESTED_COMPONENT=src/multimedia
+
+#ifndef TESTDATA_DIR
+#define TESTDATA_DIR "./"
+#endif
+
+QT_USE_NAMESPACE
+
+// Eventually these will make it into qtestcase.h
+// but we might need to tweak the timeout values here.
+#ifndef QTRY_COMPARE
+#define QTRY_COMPARE(__expr, __expected) \
+ do { \
+ const int __step = 50; \
+ const int __timeout = 5000; \
+ if ((__expr) != (__expected)) { \
+ QTest::qWait(0); \
+ } \
+ for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \
+ QTest::qWait(__step); \
+ } \
+ QCOMPARE(__expr, __expected); \
+ } while(0)
+#endif
+
+#ifndef QTRY_VERIFY
+#define QTRY_VERIFY(__expr) \
+ do { \
+ const int __step = 50; \
+ const int __timeout = 5000; \
+ if (!(__expr)) { \
+ QTest::qWait(0); \
+ } \
+ for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \
+ QTest::qWait(__step); \
+ } \
+ QVERIFY(__expr); \
+ } while(0)
+#endif
+
+
+#define QTRY_WAIT(code, __expr) \
+ do { \
+ const int __step = 50; \
+ const int __timeout = 5000; \
+ if (!(__expr)) { \
+ QTest::qWait(0); \
+ } \
+ for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \
+ do { code } while(0); \
+ QTest::qWait(__step); \
+ } \
+ } while(0)
+
+
+/*
+ This is the backend conformance test.
+
+ Since it relies on platform media framework and sound hardware
+ it may be less stable.
+*/
+
+class tst_QMediaPlayerBackend : public QObject
+{
+ Q_OBJECT
+public slots:
+ void init();
+ void cleanup();
+ void initTestCase();
+
+private slots:
+ void construction();
+ void loadMedia();
+ void unloadMedia();
+ void playPauseStop();
+ void processEOS();
+ void volumeAndMuted();
+ void volumeAcrossFiles_data();
+ void volumeAcrossFiles();
+
+private:
+ //one second local wav file
+ QMediaContent localWavFile;
+};
+
+void tst_QMediaPlayerBackend::init()
+{
+}
+
+void tst_QMediaPlayerBackend::initTestCase()
+{
+ QFileInfo wavFile(QLatin1String(TESTDATA_DIR "testdata/test.wav"));
+ QVERIFY(wavFile.exists());
+
+ localWavFile = QMediaContent(QUrl::fromLocalFile(wavFile.absoluteFilePath()));
+
+ qRegisterMetaType<QMediaContent>();
+}
+
+void tst_QMediaPlayerBackend::cleanup()
+{
+}
+
+void tst_QMediaPlayerBackend::construction()
+{
+ QMediaPlayer player;
+ QVERIFY(player.isAvailable());
+}
+
+void tst_QMediaPlayerBackend::loadMedia()
+{
+ QMediaPlayer player;
+ QCOMPARE(player.state(), QMediaPlayer::StoppedState);
+ QCOMPARE(player.mediaStatus(), QMediaPlayer::NoMedia);
+
+ QSignalSpy stateSpy(&player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ QSignalSpy mediaSpy(&player, SIGNAL(mediaChanged(QMediaContent)));
+
+ player.setMedia(localWavFile);
+
+ QCOMPARE(player.state(), QMediaPlayer::StoppedState);
+
+ QVERIFY(player.mediaStatus() != QMediaPlayer::NoMedia);
+ QVERIFY(player.mediaStatus() != QMediaPlayer::InvalidMedia);
+ QVERIFY(player.media() == localWavFile);
+
+ QCOMPARE(stateSpy.count(), 0);
+ QVERIFY(statusSpy.count() > 0);
+ QCOMPARE(mediaSpy.count(), 1);
+ QCOMPARE(mediaSpy.last()[0].value<QMediaContent>(), localWavFile);
+
+ QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::LoadedMedia);
+
+ QVERIFY(player.isAudioAvailable());
+ QVERIFY(!player.isVideoAvailable());
+}
+
+void tst_QMediaPlayerBackend::unloadMedia()
+{
+ QMediaPlayer player;
+ player.setNotifyInterval(50);
+
+ QSignalSpy stateSpy(&player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ QSignalSpy mediaSpy(&player, SIGNAL(mediaChanged(QMediaContent)));
+ QSignalSpy positionSpy(&player, SIGNAL(positionChanged(qint64)));
+ QSignalSpy durationSpy(&player, SIGNAL(positionChanged(qint64)));
+
+ player.setMedia(localWavFile);
+
+ QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::LoadedMedia);
+
+ QVERIFY(player.position() == 0);
+ QVERIFY(player.duration() > 0);
+
+ player.play();
+
+ QTest::qWait(250);
+ QVERIFY(player.position() > 0);
+ QVERIFY(player.duration() > 0);
+
+ stateSpy.clear();
+ statusSpy.clear();
+ mediaSpy.clear();
+ positionSpy.clear();
+ durationSpy.clear();
+
+ player.setMedia(QMediaContent());
+
+ QVERIFY(player.position() <= 0);
+ QVERIFY(player.duration() <= 0);
+ QCOMPARE(player.state(), QMediaPlayer::StoppedState);
+ QCOMPARE(player.mediaStatus(), QMediaPlayer::NoMedia);
+ QCOMPARE(player.media(), QMediaContent());
+
+ QVERIFY(!stateSpy.isEmpty());
+ QVERIFY(!statusSpy.isEmpty());
+ QVERIFY(!mediaSpy.isEmpty());
+ QVERIFY(!positionSpy.isEmpty());
+}
+
+
+void tst_QMediaPlayerBackend::playPauseStop()
+{
+ QMediaPlayer player;
+ player.setNotifyInterval(50);
+
+ QSignalSpy stateSpy(&player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ QSignalSpy positionSpy(&player, SIGNAL(positionChanged(qint64)));
+
+ player.setMedia(localWavFile);
+
+ QCOMPARE(player.position(), qint64(0));
+
+ player.play();
+
+ QCOMPARE(player.state(), QMediaPlayer::PlayingState);
+
+ QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ QCOMPARE(stateSpy.count(), 1);
+ QCOMPARE(stateSpy.last()[0].value<QMediaPlayer::State>(), QMediaPlayer::PlayingState);
+ QTRY_VERIFY(statusSpy.count() > 0 &&
+ statusSpy.last()[0].value<QMediaPlayer::MediaStatus>() == QMediaPlayer::BufferedMedia);
+
+ QTest::qWait(500);
+ QVERIFY(player.position() > 0);
+ QVERIFY(player.duration() > 0);
+ QVERIFY(positionSpy.count() > 0);
+ QVERIFY(positionSpy.last()[0].value<qint64>() > 0);
+
+ stateSpy.clear();
+ statusSpy.clear();
+
+ player.pause();
+
+ QCOMPARE(player.state(), QMediaPlayer::PausedState);
+ QCOMPARE(player.mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ QCOMPARE(stateSpy.count(), 1);
+ QCOMPARE(stateSpy.last()[0].value<QMediaPlayer::State>(), QMediaPlayer::PausedState);
+
+ stateSpy.clear();
+ statusSpy.clear();
+
+ player.stop();
+
+ QCOMPARE(player.state(), QMediaPlayer::StoppedState);
+ QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::LoadedMedia);
+
+ QCOMPARE(stateSpy.count(), 1);
+ QCOMPARE(stateSpy.last()[0].value<QMediaPlayer::State>(), QMediaPlayer::StoppedState);
+ //it's allowed to emit statusChanged() signal async
+ QTRY_COMPARE(statusSpy.count(), 1);
+ QCOMPARE(statusSpy.last()[0].value<QMediaPlayer::MediaStatus>(), QMediaPlayer::LoadedMedia);
+
+ //ensure the position is reset to 0 at stop and positionChanged(0) is emitted
+ QCOMPARE(player.position(), qint64(0));
+ QCOMPARE(positionSpy.last()[0].value<qint64>(), qint64(0));
+ QVERIFY(player.duration() > 0);
+}
+
+
+void tst_QMediaPlayerBackend::processEOS()
+{
+ QMediaPlayer player;
+ player.setNotifyInterval(50);
+
+ QSignalSpy stateSpy(&player, SIGNAL(stateChanged(QMediaPlayer::State)));
+ QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ QSignalSpy positionSpy(&player, SIGNAL(positionChanged(qint64)));
+
+ player.setMedia(localWavFile);
+
+ player.play();
+ player.setPosition(900);
+
+ //wait up to 5 seconds for EOS
+ QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::EndOfMedia);
+
+ QVERIFY(statusSpy.count() > 0);
+ QCOMPARE(statusSpy.last()[0].value<QMediaPlayer::MediaStatus>(), QMediaPlayer::EndOfMedia);
+
+ //at EOS the position stays at the end of file
+ QVERIFY(player.position() > 900);
+
+ stateSpy.clear();
+ statusSpy.clear();
+
+ player.play();
+
+ //position is reset to start
+ QTRY_VERIFY(player.position() < 100);
+
+ QCOMPARE(player.state(), QMediaPlayer::PlayingState);
+ QCOMPARE(player.mediaStatus(), QMediaPlayer::BufferedMedia);
+
+ QCOMPARE(stateSpy.count(), 1);
+ QCOMPARE(stateSpy.last()[0].value<QMediaPlayer::State>(), QMediaPlayer::PlayingState);
+ QVERIFY(statusSpy.count() > 0);
+ QCOMPARE(statusSpy.last()[0].value<QMediaPlayer::MediaStatus>(), QMediaPlayer::BufferedMedia);
+
+ player.setPosition(900);
+ //wait up to 5 seconds for EOS
+ QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::EndOfMedia);
+
+ //ensure the positionChanged() signal is emitted
+ QVERIFY(positionSpy.count() > 0);
+
+ QCOMPARE(player.mediaStatus(), QMediaPlayer::EndOfMedia);
+ //position stays at the end of file
+ QVERIFY(player.position() > 900);
+
+ //after setPosition EndOfMedia status should be reset to Loaded
+ stateSpy.clear();
+ statusSpy.clear();
+ player.setPosition(500);
+
+ //this transition can be async, so allow backend to perform it
+ QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::LoadedMedia);
+
+ QCOMPARE(stateSpy.count(), 0);
+ QTRY_VERIFY(statusSpy.count() > 0 &&
+ statusSpy.last()[0].value<QMediaPlayer::MediaStatus>() == QMediaPlayer::LoadedMedia);
+}
+
+void tst_QMediaPlayerBackend::volumeAndMuted()
+{
+ //volume and muted properties should be independent
+ QMediaPlayer player;
+ QVERIFY(player.volume() > 0);
+ QVERIFY(!player.isMuted());
+
+ player.setMedia(localWavFile);
+ player.pause();
+
+ QVERIFY(player.volume() > 0);
+ QVERIFY(!player.isMuted());
+
+ QSignalSpy volumeSpy(&player, SIGNAL(volumeChanged(int)));
+ QSignalSpy mutedSpy(&player, SIGNAL(mutedChanged(bool)));
+
+ //setting volume to 0 should not trigger muted
+ player.setVolume(0);
+ QTRY_COMPARE(player.volume(), 0);
+ QVERIFY(!player.isMuted());
+ QCOMPARE(volumeSpy.count(), 1);
+ QCOMPARE(volumeSpy.last()[0].toInt(), player.volume());
+ QCOMPARE(mutedSpy.count(), 0);
+
+ player.setVolume(50);
+ QTRY_COMPARE(player.volume(), 50);
+ QVERIFY(!player.isMuted());
+ QCOMPARE(volumeSpy.count(), 2);
+ QCOMPARE(volumeSpy.last()[0].toInt(), player.volume());
+ QCOMPARE(mutedSpy.count(), 0);
+
+ player.setMuted(true);
+ QTRY_VERIFY(player.isMuted());
+ QVERIFY(player.volume() > 0);
+ QCOMPARE(volumeSpy.count(), 2);
+ QCOMPARE(mutedSpy.count(), 1);
+ QCOMPARE(mutedSpy.last()[0].toBool(), player.isMuted());
+
+ player.setMuted(false);
+ QTRY_VERIFY(!player.isMuted());
+ QVERIFY(player.volume() > 0);
+ QCOMPARE(volumeSpy.count(), 2);
+ QCOMPARE(mutedSpy.count(), 2);
+ QCOMPARE(mutedSpy.last()[0].toBool(), player.isMuted());
+
+}
+
+void tst_QMediaPlayerBackend::volumeAcrossFiles_data()
+{
+ QTest::addColumn<int>("volume");
+ QTest::addColumn<bool>("muted");
+
+ QTest::newRow("100 unmuted") << 100 << false;
+ QTest::newRow("50 unmuted") << 50 << false;
+ QTest::newRow("0 unmuted") << 0 << false;
+ QTest::newRow("100 muted") << 100 << true;
+ QTest::newRow("50 muted") << 50 << true;
+ QTest::newRow("0 muted") << 0 << true;
+}
+
+void tst_QMediaPlayerBackend::volumeAcrossFiles()
+{
+ QFETCH(int, volume);
+ QFETCH(bool, muted);
+
+ QMediaPlayer player;
+
+ //volume and muted should not be preserved between player instances
+ QVERIFY(player.volume() > 0);
+ QVERIFY(!player.isMuted());
+
+ player.setVolume(volume);
+ player.setMuted(muted);
+
+ QTRY_COMPARE(player.volume(), volume);
+ QTRY_COMPARE(player.isMuted(), muted);
+
+ player.setMedia(localWavFile);
+ QCOMPARE(player.volume(), volume);
+ QCOMPARE(player.isMuted(), muted);
+
+ player.pause();
+
+ //to ensure the backend doesn't change volume/muted
+ //async during file loading.
+ QTest::qWait(50);
+
+ QCOMPARE(player.volume(), volume);
+ QCOMPARE(player.isMuted(), muted);
+
+ player.setMedia(QMediaContent());
+ QTest::qWait(50);
+ QCOMPARE(player.volume(), volume);
+ QCOMPARE(player.isMuted(), muted);
+
+ player.setMedia(localWavFile);
+ player.pause();
+
+ QTest::qWait(50);
+
+ QCOMPARE(player.volume(), volume);
+ QCOMPARE(player.isMuted(), muted);
+}
+
+
+QTEST_MAIN(tst_QMediaPlayerBackend)
+#include "tst_qmediaplayerbackend.moc"
+
diff --git a/tests/auto/qmediaplaylist/qmediaplaylist.pro b/tests/auto/qmediaplaylist/qmediaplaylist.pro
new file mode 100644
index 000000000..bd1ad114e
--- /dev/null
+++ b/tests/auto/qmediaplaylist/qmediaplaylist.pro
@@ -0,0 +1,29 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qmediaplaylist
+# CONFIG += testcase
+
+symbian*: {
+ PLAYLIST_TESTDATA.sources = testdata/*
+ PLAYLIST_TESTDATA.path = testdata
+ DEPLOYMENT += PLAYLIST_TESTDATA
+}
+
+wince* {
+ DEFINES+= TESTDATA_DIR=\\\"./\\\"
+}else:!symbian {
+ DEFINES += TESTDATA_DIR=\\\"$$PWD/\\\"
+}
+
+HEADERS += \
+ $$QT.multimediakit.sources/../plugins/m3u/qm3uhandler.h
+
+SOURCES += \
+ tst_qmediaplaylist.cpp \
+ $$QT.multimediakit.sources/../plugins/m3u/qm3uhandler.cpp
+
+INCLUDEPATH += $$QT.multimediakit.sources/../plugins/m3u
+
+maemo*:CONFIG += insignificant_test
diff --git a/tests/auto/qmediaplaylist/testdata/test.m3u b/tests/auto/qmediaplaylist/testdata/test.m3u
new file mode 100644
index 000000000..e5cb7c828
--- /dev/null
+++ b/tests/auto/qmediaplaylist/testdata/test.m3u
@@ -0,0 +1,11 @@
+#comment
+
+http://test.host/path
+ http://test.host/path
+testfile
+
+
+testdir/testfile
+/testdir/testfile
+file://path/name#suffix
+testfile2#suffix
diff --git a/tests/auto/qmediaplaylist/testdata/testfile b/tests/auto/qmediaplaylist/testdata/testfile
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/qmediaplaylist/testdata/testfile
diff --git a/tests/auto/qmediaplaylist/testdata/testfile2#suffix b/tests/auto/qmediaplaylist/testdata/testfile2#suffix
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/qmediaplaylist/testdata/testfile2#suffix
diff --git a/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp b/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp
new file mode 100644
index 000000000..1a0395a54
--- /dev/null
+++ b/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp
@@ -0,0 +1,666 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 <QtTest/QtTest>
+#include <QDebug>
+#include "qmediaservice.h"
+#include "qmediaplaylist.h"
+#include "qmediaplaylistcontrol.h"
+#include "qmediaplaylistnavigator.h"
+#include <private/qmediapluginloader_p.h>
+
+#include "qm3uhandler.h"
+
+//TESTED_COMPONENT=src/multimedia
+
+#ifndef TESTDATA_DIR
+#define TESTDATA_DIR "./"
+#endif
+
+QT_USE_NAMESPACE
+class MockReadOnlyPlaylistProvider : public QMediaPlaylistProvider
+{
+ Q_OBJECT
+public:
+ MockReadOnlyPlaylistProvider(QObject *parent)
+ :QMediaPlaylistProvider(parent)
+ {
+ m_items.append(QMediaContent(QUrl(QLatin1String("file:///1"))));
+ m_items.append(QMediaContent(QUrl(QLatin1String("file:///2"))));
+ m_items.append(QMediaContent(QUrl(QLatin1String("file:///3"))));
+ }
+
+ int mediaCount() const { return m_items.size(); }
+ QMediaContent media(int index) const
+ {
+ return index >=0 && index < mediaCount() ? m_items.at(index) : QMediaContent();
+ }
+
+private:
+ QList<QMediaContent> m_items;
+};
+
+class MockPlaylistControl : public QMediaPlaylistControl
+{
+ Q_OBJECT
+public:
+ MockPlaylistControl(QObject *parent) : QMediaPlaylistControl(parent)
+ {
+ m_navigator = new QMediaPlaylistNavigator(new MockReadOnlyPlaylistProvider(this), this);
+ }
+
+ ~MockPlaylistControl()
+ {
+ }
+
+ QMediaPlaylistProvider* playlistProvider() const { return m_navigator->playlist(); }
+ bool setPlaylistProvider(QMediaPlaylistProvider *playlist) { m_navigator->setPlaylist(playlist); return true; }
+
+ int currentIndex() const { return m_navigator->currentIndex(); }
+ void setCurrentIndex(int position) { m_navigator->jump(position); }
+ int nextIndex(int steps) const { return m_navigator->nextIndex(steps); }
+ int previousIndex(int steps) const { return m_navigator->previousIndex(steps); }
+
+ void next() { m_navigator->next(); }
+ void previous() { m_navigator->previous(); }
+
+ QMediaPlaylist::PlaybackMode playbackMode() const { return m_navigator->playbackMode(); }
+ void setPlaybackMode(QMediaPlaylist::PlaybackMode mode) { m_navigator->setPlaybackMode(mode); }
+
+private:
+ QMediaPlaylistNavigator *m_navigator;
+};
+
+class MockPlaylistService : public QMediaService
+{
+ Q_OBJECT
+
+public:
+ MockPlaylistService():QMediaService(0)
+ {
+ mockControl = new MockPlaylistControl(this);
+ }
+
+ ~MockPlaylistService()
+ {
+ }
+
+ QMediaControl* requestControl(const char *iid)
+ {
+ if (qstrcmp(iid, QMediaPlaylistControl_iid) == 0)
+ return mockControl;
+ return 0;
+ }
+
+ void releaseControl(QMediaControl *)
+ {
+ }
+
+ MockPlaylistControl *mockControl;
+};
+
+class MockReadOnlyPlaylistObject : public QMediaObject
+{
+ Q_OBJECT
+public:
+ MockReadOnlyPlaylistObject(QObject *parent = 0)
+ :QMediaObject(parent, new MockPlaylistService)
+ {
+ }
+};
+
+
+class tst_QMediaPlaylist : public QObject
+{
+ Q_OBJECT
+public slots:
+ void init();
+ void cleanup();
+ void initTestCase();
+
+private slots:
+ void construction();
+ void append();
+ void insert();
+ void clear();
+ void removeMedia();
+ void currentItem();
+ void saveAndLoad();
+ void loadM3uFile();
+ void playbackMode();
+ void playbackMode_data();
+ void shuffle();
+ void readOnlyPlaylist();
+ void setMediaObject();
+
+private:
+ QMediaContent content1;
+ QMediaContent content2;
+ QMediaContent content3;
+};
+
+void tst_QMediaPlaylist::init()
+{
+}
+
+void tst_QMediaPlaylist::initTestCase()
+{
+ content1 = QMediaContent(QUrl(QLatin1String("file:///1")));
+ content2 = QMediaContent(QUrl(QLatin1String("file:///2")));
+ content3 = QMediaContent(QUrl(QLatin1String("file:///3")));
+
+ QMediaPluginLoader::setStaticPlugins(QLatin1String("playlistformats"), QObjectList() << new QM3uPlaylistPlugin(this));
+}
+
+void tst_QMediaPlaylist::cleanup()
+{
+}
+
+void tst_QMediaPlaylist::construction()
+{
+ QMediaPlaylist playlist;
+ QCOMPARE(playlist.mediaCount(), 0);
+ QVERIFY(playlist.isEmpty());
+}
+
+void tst_QMediaPlaylist::append()
+{
+ QMediaPlaylist playlist;
+ QVERIFY(!playlist.isReadOnly());
+
+ playlist.addMedia(content1);
+ QCOMPARE(playlist.mediaCount(), 1);
+ QCOMPARE(playlist.media(0), content1);
+
+ QSignalSpy aboutToBeInsertedSignalSpy(&playlist, SIGNAL(mediaAboutToBeInserted(int,int)));
+ QSignalSpy insertedSignalSpy(&playlist, SIGNAL(mediaInserted(int,int)));
+ playlist.addMedia(content2);
+ QCOMPARE(playlist.mediaCount(), 2);
+ QCOMPARE(playlist.media(1), content2);
+
+ QCOMPARE(aboutToBeInsertedSignalSpy.count(), 1);
+ QCOMPARE(aboutToBeInsertedSignalSpy.first()[0].toInt(), 1);
+ QCOMPARE(aboutToBeInsertedSignalSpy.first()[1].toInt(), 1);
+
+ QCOMPARE(insertedSignalSpy.count(), 1);
+ QCOMPARE(insertedSignalSpy.first()[0].toInt(), 1);
+ QCOMPARE(insertedSignalSpy.first()[1].toInt(), 1);
+
+ aboutToBeInsertedSignalSpy.clear();
+ insertedSignalSpy.clear();
+
+ QMediaContent content4(QUrl(QLatin1String("file:///4")));
+ QMediaContent content5(QUrl(QLatin1String("file:///5")));
+ playlist.addMedia(QList<QMediaContent>() << content3 << content4 << content5);
+ QCOMPARE(playlist.mediaCount(), 5);
+ QCOMPARE(playlist.media(2), content3);
+ QCOMPARE(playlist.media(3), content4);
+ QCOMPARE(playlist.media(4), content5);
+
+ QCOMPARE(aboutToBeInsertedSignalSpy.count(), 1);
+ QCOMPARE(aboutToBeInsertedSignalSpy[0][0].toInt(), 2);
+ QCOMPARE(aboutToBeInsertedSignalSpy[0][1].toInt(), 4);
+
+ QCOMPARE(insertedSignalSpy.count(), 1);
+ QCOMPARE(insertedSignalSpy[0][0].toInt(), 2);
+ QCOMPARE(insertedSignalSpy[0][1].toInt(), 4);
+
+ aboutToBeInsertedSignalSpy.clear();
+ insertedSignalSpy.clear();
+
+ playlist.addMedia(QList<QMediaContent>());
+ QCOMPARE(aboutToBeInsertedSignalSpy.count(), 0);
+ QCOMPARE(insertedSignalSpy.count(), 0);
+}
+
+void tst_QMediaPlaylist::insert()
+{
+ QMediaPlaylist playlist;
+ QVERIFY(!playlist.isReadOnly());
+
+ playlist.addMedia(content1);
+ QCOMPARE(playlist.mediaCount(), 1);
+ QCOMPARE(playlist.media(0), content1);
+
+ playlist.addMedia(content2);
+ QCOMPARE(playlist.mediaCount(), 2);
+ QCOMPARE(playlist.media(1), content2);
+
+ QSignalSpy aboutToBeInsertedSignalSpy(&playlist, SIGNAL(mediaAboutToBeInserted(int,int)));
+ QSignalSpy insertedSignalSpy(&playlist, SIGNAL(mediaInserted(int,int)));
+
+ playlist.insertMedia(1, content3);
+ QCOMPARE(playlist.mediaCount(), 3);
+ QCOMPARE(playlist.media(0), content1);
+ QCOMPARE(playlist.media(1), content3);
+ QCOMPARE(playlist.media(2), content2);
+
+ QCOMPARE(aboutToBeInsertedSignalSpy.count(), 1);
+ QCOMPARE(aboutToBeInsertedSignalSpy.first()[0].toInt(), 1);
+ QCOMPARE(aboutToBeInsertedSignalSpy.first()[1].toInt(), 1);
+
+ QCOMPARE(insertedSignalSpy.count(), 1);
+ QCOMPARE(insertedSignalSpy.first()[0].toInt(), 1);
+ QCOMPARE(insertedSignalSpy.first()[1].toInt(), 1);
+
+ aboutToBeInsertedSignalSpy.clear();
+ insertedSignalSpy.clear();
+
+ QMediaContent content4(QUrl(QLatin1String("file:///4")));
+ QMediaContent content5(QUrl(QLatin1String("file:///5")));
+ playlist.insertMedia(1, QList<QMediaContent>() << content4 << content5);
+
+ QCOMPARE(playlist.media(0), content1);
+ QCOMPARE(playlist.media(1), content4);
+ QCOMPARE(playlist.media(2), content5);
+ QCOMPARE(playlist.media(3), content3);
+ QCOMPARE(playlist.media(4), content2);
+ QCOMPARE(aboutToBeInsertedSignalSpy.count(), 1);
+ QCOMPARE(aboutToBeInsertedSignalSpy[0][0].toInt(), 1);
+ QCOMPARE(aboutToBeInsertedSignalSpy[0][1].toInt(), 2);
+
+ QCOMPARE(insertedSignalSpy.count(), 1);
+ QCOMPARE(insertedSignalSpy[0][0].toInt(), 1);
+ QCOMPARE(insertedSignalSpy[0][1].toInt(), 2);
+
+ aboutToBeInsertedSignalSpy.clear();
+ insertedSignalSpy.clear();
+
+ playlist.insertMedia(1, QList<QMediaContent>());
+ QCOMPARE(aboutToBeInsertedSignalSpy.count(), 0);
+ QCOMPARE(insertedSignalSpy.count(), 0);
+}
+
+
+void tst_QMediaPlaylist::currentItem()
+{
+ QMediaPlaylist playlist;
+ playlist.addMedia(content1);
+ playlist.addMedia(content2);
+
+ QCOMPARE(playlist.currentIndex(), -1);
+ QCOMPARE(playlist.currentMedia(), QMediaContent());
+
+ QCOMPARE(playlist.nextIndex(), 0);
+ QCOMPARE(playlist.nextIndex(2), 1);
+ QCOMPARE(playlist.previousIndex(), 1);
+ QCOMPARE(playlist.previousIndex(2), 0);
+
+ playlist.setCurrentIndex(0);
+ QCOMPARE(playlist.currentIndex(), 0);
+ QCOMPARE(playlist.currentMedia(), content1);
+
+ QCOMPARE(playlist.nextIndex(), 1);
+ QCOMPARE(playlist.nextIndex(2), -1);
+ QCOMPARE(playlist.previousIndex(), -1);
+ QCOMPARE(playlist.previousIndex(2), -1);
+
+ playlist.setCurrentIndex(1);
+ QCOMPARE(playlist.currentIndex(), 1);
+ QCOMPARE(playlist.currentMedia(), content2);
+
+ QCOMPARE(playlist.nextIndex(), -1);
+ QCOMPARE(playlist.nextIndex(2), -1);
+ QCOMPARE(playlist.previousIndex(), 0);
+ QCOMPARE(playlist.previousIndex(2), -1);
+
+ QTest::ignoreMessage(QtWarningMsg, "QMediaPlaylistNavigator: Jump outside playlist range ");
+ playlist.setCurrentIndex(2);
+
+ QCOMPARE(playlist.currentIndex(), -1);
+ QCOMPARE(playlist.currentMedia(), QMediaContent());
+}
+
+void tst_QMediaPlaylist::clear()
+{
+ QMediaPlaylist playlist;
+ playlist.addMedia(content1);
+ playlist.addMedia(content2);
+
+ playlist.clear();
+ QVERIFY(playlist.isEmpty());
+ QCOMPARE(playlist.mediaCount(), 0);
+}
+
+void tst_QMediaPlaylist::removeMedia()
+{
+ QMediaPlaylist playlist;
+ playlist.addMedia(content1);
+ playlist.addMedia(content2);
+ playlist.addMedia(content3);
+
+ QSignalSpy aboutToBeRemovedSignalSpy(&playlist, SIGNAL(mediaAboutToBeRemoved(int,int)));
+ QSignalSpy removedSignalSpy(&playlist, SIGNAL(mediaRemoved(int,int)));
+ playlist.removeMedia(1);
+ QCOMPARE(playlist.mediaCount(), 2);
+ QCOMPARE(playlist.media(1), content3);
+
+ QCOMPARE(aboutToBeRemovedSignalSpy.count(), 1);
+ QCOMPARE(aboutToBeRemovedSignalSpy.first()[0].toInt(), 1);
+ QCOMPARE(aboutToBeRemovedSignalSpy.first()[1].toInt(), 1);
+
+ QCOMPARE(removedSignalSpy.count(), 1);
+ QCOMPARE(removedSignalSpy.first()[0].toInt(), 1);
+ QCOMPARE(removedSignalSpy.first()[1].toInt(), 1);
+
+ aboutToBeRemovedSignalSpy.clear();
+ removedSignalSpy.clear();
+
+ playlist.removeMedia(0,1);
+ QVERIFY(playlist.isEmpty());
+
+ QCOMPARE(aboutToBeRemovedSignalSpy.count(), 1);
+ QCOMPARE(aboutToBeRemovedSignalSpy.first()[0].toInt(), 0);
+ QCOMPARE(aboutToBeRemovedSignalSpy.first()[1].toInt(), 1);
+
+ QCOMPARE(removedSignalSpy.count(), 1);
+ QCOMPARE(removedSignalSpy.first()[0].toInt(), 0);
+ QCOMPARE(removedSignalSpy.first()[1].toInt(), 1);
+
+
+ playlist.addMedia(content1);
+ playlist.addMedia(content2);
+ playlist.addMedia(content3);
+
+ playlist.removeMedia(0,1);
+ QCOMPARE(playlist.mediaCount(), 1);
+ QCOMPARE(playlist.media(0), content3);
+}
+
+void tst_QMediaPlaylist::saveAndLoad()
+{
+ QMediaPlaylist playlist;
+ playlist.addMedia(content1);
+ playlist.addMedia(content2);
+ playlist.addMedia(content3);
+
+ QCOMPARE(playlist.error(), QMediaPlaylist::NoError);
+ QVERIFY(playlist.errorString().isEmpty());
+
+ QBuffer buffer;
+ buffer.open(QBuffer::ReadWrite);
+
+ bool res = playlist.save(&buffer, "unsupported_format");
+ QVERIFY(!res);
+ QVERIFY(playlist.error() != QMediaPlaylist::NoError);
+ QVERIFY(!playlist.errorString().isEmpty());
+
+ QSignalSpy errorSignal(&playlist, SIGNAL(loadFailed()));
+ playlist.load(&buffer, "unsupported_format");
+ QCOMPARE(errorSignal.size(), 1);
+ QVERIFY(playlist.error() != QMediaPlaylist::NoError);
+ QVERIFY(!playlist.errorString().isEmpty());
+
+ res = playlist.save(QUrl(QLatin1String("tmp.unsupported_format")), "unsupported_format");
+ QVERIFY(!res);
+ QVERIFY(playlist.error() != QMediaPlaylist::NoError);
+ QVERIFY(!playlist.errorString().isEmpty());
+
+ errorSignal.clear();
+ playlist.load(QUrl(QLatin1String("tmp.unsupported_format")), "unsupported_format");
+ QCOMPARE(errorSignal.size(), 1);
+ QVERIFY(playlist.error() != QMediaPlaylist::NoError);
+ QVERIFY(!playlist.errorString().isEmpty());
+
+ res = playlist.save(&buffer, "m3u");
+
+ QVERIFY(res);
+ QVERIFY(buffer.pos() > 0);
+ buffer.seek(0);
+
+ QMediaPlaylist playlist2;
+ playlist2.load(&buffer, "m3u");
+ QCOMPARE(playlist.error(), QMediaPlaylist::NoError);
+
+ QCOMPARE(playlist.mediaCount(), playlist2.mediaCount());
+ QCOMPARE(playlist.media(0), playlist2.media(0));
+ QCOMPARE(playlist.media(1), playlist2.media(1));
+ QCOMPARE(playlist.media(3), playlist2.media(3));
+#ifdef Q_OS_SYMBIAN
+ res = playlist.save(QUrl(QLatin1String("file:///c:/data/test_m3u.m3u")), "m3u");
+#else
+ res = playlist.save(QUrl(QLatin1String("tmp.m3u")), "m3u");
+#endif
+ QVERIFY(res);
+
+ playlist2.clear();
+ QVERIFY(playlist2.isEmpty());
+#ifdef Q_OS_SYMBIAN
+ playlist2.load(QUrl(QLatin1String("file:///c:/data/test_m3u.m3u")), "m3u");
+#else
+ playlist2.load(QUrl(QLatin1String("tmp.m3u")), "m3u");
+#endif
+ QCOMPARE(playlist.error(), QMediaPlaylist::NoError);
+
+ QCOMPARE(playlist.mediaCount(), playlist2.mediaCount());
+ QCOMPARE(playlist.media(0), playlist2.media(0));
+ QCOMPARE(playlist.media(1), playlist2.media(1));
+ QCOMPARE(playlist.media(3), playlist2.media(3));
+}
+
+void tst_QMediaPlaylist::loadM3uFile()
+{
+ QMediaPlaylist playlist;
+
+ playlist.load(QUrl::fromLocalFile(QLatin1String(TESTDATA_DIR "testdata/missing_file.m3u")));
+ QVERIFY(playlist.error() != QMediaPlaylist::NoError);
+
+ playlist.load(QUrl::fromLocalFile(QLatin1String(TESTDATA_DIR "testdata/test.m3u")));
+ QCOMPARE(playlist.error(), QMediaPlaylist::NoError);
+ QCOMPARE(playlist.mediaCount(), 7);
+
+ QCOMPARE(playlist.media(0).canonicalUrl(), QUrl(QLatin1String("http://test.host/path")));
+ QCOMPARE(playlist.media(1).canonicalUrl(), QUrl(QLatin1String("http://test.host/path")));
+ QCOMPARE(playlist.media(2).canonicalUrl(),
+ QUrl(QLatin1String("file://" TESTDATA_DIR "testdata/testfile")));
+ QCOMPARE(playlist.media(3).canonicalUrl(),
+ QUrl(QLatin1String("file://" TESTDATA_DIR "testdata/testdir/testfile")));
+ QCOMPARE(playlist.media(4).canonicalUrl(), QUrl(QLatin1String("file:///testdir/testfile")));
+ QCOMPARE(playlist.media(5).canonicalUrl(), QUrl(QLatin1String("file://path/name#suffix")));
+ //ensure #2 suffix is not stripped from path
+ QCOMPARE(playlist.media(6).canonicalUrl(), QUrl::fromLocalFile(TESTDATA_DIR "testdata/testfile2#suffix"));
+}
+
+void tst_QMediaPlaylist::playbackMode_data()
+{
+ QTest::addColumn<QMediaPlaylist::PlaybackMode>("playbackMode");
+ QTest::addColumn<int>("expectedPrevious");
+ QTest::addColumn<int>("pos");
+ QTest::addColumn<int>("expectedNext");
+
+ QTest::newRow("Sequential, 0") << QMediaPlaylist::Sequential << -1 << 0 << 1;
+ QTest::newRow("Sequential, 1") << QMediaPlaylist::Sequential << 0 << 1 << 2;
+ QTest::newRow("Sequential, 2") << QMediaPlaylist::Sequential << 1 << 2 << -1;
+
+ QTest::newRow("Loop, 0") << QMediaPlaylist::Loop << 2 << 0 << 1;
+ QTest::newRow("Loop, 1") << QMediaPlaylist::Loop << 0 << 1 << 2;
+ QTest::newRow("Lopp, 2") << QMediaPlaylist::Loop << 1 << 2 << 0;
+
+ QTest::newRow("ItemOnce, 1") << QMediaPlaylist::CurrentItemOnce << -1 << 1 << -1;
+ QTest::newRow("ItemInLoop, 1") << QMediaPlaylist::CurrentItemInLoop << 1 << 1 << 1;
+
+}
+
+void tst_QMediaPlaylist::playbackMode()
+{
+ QFETCH(QMediaPlaylist::PlaybackMode, playbackMode);
+ QFETCH(int, expectedPrevious);
+ QFETCH(int, pos);
+ QFETCH(int, expectedNext);
+
+ QMediaPlaylist playlist;
+ playlist.addMedia(content1);
+ playlist.addMedia(content2);
+ playlist.addMedia(content3);
+
+ QCOMPARE(playlist.playbackMode(), QMediaPlaylist::Sequential);
+ QCOMPARE(playlist.currentIndex(), -1);
+
+ playlist.setPlaybackMode(playbackMode);
+ QCOMPARE(playlist.playbackMode(), playbackMode);
+
+ playlist.setCurrentIndex(pos);
+ QCOMPARE(playlist.currentIndex(), pos);
+ QCOMPARE(playlist.nextIndex(), expectedNext);
+ QCOMPARE(playlist.previousIndex(), expectedPrevious);
+
+ playlist.next();
+ QCOMPARE(playlist.currentIndex(), expectedNext);
+
+ playlist.setCurrentIndex(pos);
+ playlist.previous();
+ QCOMPARE(playlist.currentIndex(), expectedPrevious);
+}
+
+void tst_QMediaPlaylist::shuffle()
+{
+ QMediaPlaylist playlist;
+ QList<QMediaContent> contentList;
+
+ for (int i=0; i<100; i++) {
+ QMediaContent content(QUrl(QString::number(i)));
+ contentList.append(content);
+ playlist.addMedia(content);
+ }
+
+ playlist.shuffle();
+
+ QList<QMediaContent> shuffledContentList;
+ for (int i=0; i<playlist.mediaCount(); i++)
+ shuffledContentList.append(playlist.media(i));
+
+ QVERIFY(contentList != shuffledContentList);
+
+}
+
+void tst_QMediaPlaylist::readOnlyPlaylist()
+{
+ MockReadOnlyPlaylistObject mediaObject;
+ QMediaPlaylist playlist;
+ mediaObject.bind(&playlist);
+
+ QVERIFY(playlist.isReadOnly());
+ QVERIFY(!playlist.isEmpty());
+ QCOMPARE(playlist.mediaCount(), 3);
+
+ QCOMPARE(playlist.media(0), content1);
+ QCOMPARE(playlist.media(1), content2);
+ QCOMPARE(playlist.media(2), content3);
+ QCOMPARE(playlist.media(3), QMediaContent());
+
+ //it's a read only playlist, so all the modification should fail
+ QVERIFY(!playlist.addMedia(content1));
+ QCOMPARE(playlist.mediaCount(), 3);
+ QVERIFY(!playlist.addMedia(QList<QMediaContent>() << content1 << content2));
+ QCOMPARE(playlist.mediaCount(), 3);
+ QVERIFY(!playlist.insertMedia(1, content1));
+ QCOMPARE(playlist.mediaCount(), 3);
+ QVERIFY(!playlist.insertMedia(1, QList<QMediaContent>() << content1 << content2));
+ QCOMPARE(playlist.mediaCount(), 3);
+ QVERIFY(!playlist.removeMedia(1));
+ QCOMPARE(playlist.mediaCount(), 3);
+ QVERIFY(!playlist.removeMedia(0,2));
+ QCOMPARE(playlist.mediaCount(), 3);
+ QVERIFY(!playlist.clear());
+ QCOMPARE(playlist.mediaCount(), 3);
+
+ //but it is still allowed to append/insert an empty list
+ QVERIFY(playlist.addMedia(QList<QMediaContent>()));
+ QVERIFY(playlist.insertMedia(1, QList<QMediaContent>()));
+
+ playlist.shuffle();
+ //it's still the same
+ QCOMPARE(playlist.media(0), content1);
+ QCOMPARE(playlist.media(1), content2);
+ QCOMPARE(playlist.media(2), content3);
+ QCOMPARE(playlist.media(3), QMediaContent());
+
+
+ //load to read only playlist should fail,
+ //unless underlaying provider supports it
+ QBuffer buffer;
+ buffer.open(QBuffer::ReadWrite);
+ buffer.write(QByteArray("file:///1\nfile:///2"));
+ buffer.seek(0);
+
+ QSignalSpy errorSignal(&playlist, SIGNAL(loadFailed()));
+ playlist.load(&buffer, "m3u");
+ QCOMPARE(errorSignal.size(), 1);
+ QCOMPARE(playlist.error(), QMediaPlaylist::AccessDeniedError);
+ QVERIFY(!playlist.errorString().isEmpty());
+ QCOMPARE(playlist.mediaCount(), 3);
+
+ errorSignal.clear();
+ playlist.load(QUrl(QLatin1String("tmp.m3u")), "m3u");
+
+ QCOMPARE(errorSignal.size(), 1);
+ QCOMPARE(playlist.error(), QMediaPlaylist::AccessDeniedError);
+ QVERIFY(!playlist.errorString().isEmpty());
+ QCOMPARE(playlist.mediaCount(), 3);
+}
+
+void tst_QMediaPlaylist::setMediaObject()
+{
+ MockReadOnlyPlaylistObject mediaObject;
+
+ QMediaPlaylist playlist;
+ QVERIFY(playlist.mediaObject() == 0);
+ QVERIFY(!playlist.isReadOnly());
+
+ mediaObject.bind(&playlist);
+ QCOMPARE(playlist.mediaObject(), qobject_cast<QMediaObject*>(&mediaObject));
+ QCOMPARE(playlist.mediaCount(), 3);
+ QVERIFY(playlist.isReadOnly());
+
+ mediaObject.unbind(&playlist);
+ QVERIFY(playlist.mediaObject() == 0);
+ QCOMPARE(playlist.mediaCount(), 0);
+ QVERIFY(!playlist.isReadOnly());
+
+ mediaObject.bind(&playlist);
+ QCOMPARE(playlist.mediaObject(), qobject_cast<QMediaObject*>(&mediaObject));
+ QCOMPARE(playlist.mediaCount(), 3);
+ QVERIFY(playlist.isReadOnly());
+}
+
+QTEST_MAIN(tst_QMediaPlaylist)
+#include "tst_qmediaplaylist.moc"
+
diff --git a/tests/auto/qmediaplaylistnavigator/qmediaplaylistnavigator.pro b/tests/auto/qmediaplaylistnavigator/qmediaplaylistnavigator.pro
new file mode 100644
index 000000000..f5252c63b
--- /dev/null
+++ b/tests/auto/qmediaplaylistnavigator/qmediaplaylistnavigator.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qmediaplaylistnavigator
+# CONFIG += testcase
+
+SOURCES += tst_qmediaplaylistnavigator.cpp
+
diff --git a/tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp b/tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp
new file mode 100644
index 000000000..f6d19a950
--- /dev/null
+++ b/tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp
@@ -0,0 +1,318 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <QtTest/QtTest>
+#include <QDebug>
+#include "qlocalmediaplaylistprovider.h"
+#include "qmediaplaylistnavigator.h"
+
+QT_USE_NAMESPACE
+class tst_QMediaPlaylistNavigator : public QObject
+{
+ Q_OBJECT
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void construction();
+ void setPlaylist();
+ void linearPlayback();
+ void loopPlayback();
+ void currentItemOnce();
+ void currentItemInLoop();
+ void randomPlayback();
+};
+
+void tst_QMediaPlaylistNavigator::init()
+{
+}
+
+void tst_QMediaPlaylistNavigator::cleanup()
+{
+}
+
+void tst_QMediaPlaylistNavigator::construction()
+{
+ QLocalMediaPlaylistProvider playlist;
+ QCOMPARE(playlist.mediaCount(), 0);
+
+ QMediaPlaylistNavigator navigator(&playlist);
+ QVERIFY(navigator.currentItem().isNull());
+ QCOMPARE(navigator.currentIndex(), -1);
+}
+
+void tst_QMediaPlaylistNavigator::setPlaylist()
+{
+ QMediaPlaylistNavigator navigator(0);
+ QVERIFY(navigator.playlist() != 0);
+ QCOMPARE(navigator.playlist()->mediaCount(), 0);
+ QCOMPARE(navigator.playlist()->media(0), QMediaContent());
+ QVERIFY(navigator.playlist()->isReadOnly() );
+
+ QLocalMediaPlaylistProvider playlist;
+ QCOMPARE(playlist.mediaCount(), 0);
+
+ navigator.setPlaylist(&playlist);
+ QCOMPARE(navigator.playlist(), (QMediaPlaylistProvider*)&playlist);
+ QCOMPARE(navigator.playlist()->mediaCount(), 0);
+ QVERIFY(!navigator.playlist()->isReadOnly() );
+}
+
+void tst_QMediaPlaylistNavigator::linearPlayback()
+{
+ QLocalMediaPlaylistProvider playlist;
+ QMediaPlaylistNavigator navigator(&playlist);
+
+ navigator.setPlaybackMode(QMediaPlaylist::Sequential);
+ QTest::ignoreMessage(QtWarningMsg, "QMediaPlaylistNavigator: Jump outside playlist range ");
+ navigator.jump(0);//it's ok to have warning here
+ QVERIFY(navigator.currentItem().isNull());
+ QCOMPARE(navigator.currentIndex(), -1);
+
+ QMediaContent content1(QUrl(QLatin1String("file:///1")));
+ playlist.addMedia(content1);
+ navigator.jump(0);
+ QVERIFY(!navigator.currentItem().isNull());
+
+ QCOMPARE(navigator.currentIndex(), 0);
+ QCOMPARE(navigator.currentItem(), content1);
+ QCOMPARE(navigator.nextItem(), QMediaContent());
+ QCOMPARE(navigator.nextItem(2), QMediaContent());
+ QCOMPARE(navigator.previousItem(), QMediaContent());
+ QCOMPARE(navigator.previousItem(2), QMediaContent());
+
+ QMediaContent content2(QUrl(QLatin1String("file:///2")));
+ playlist.addMedia(content2);
+ QCOMPARE(navigator.currentIndex(), 0);
+ QCOMPARE(navigator.currentItem(), content1);
+ QCOMPARE(navigator.nextItem(), content2);
+ QCOMPARE(navigator.nextItem(2), QMediaContent());
+ QCOMPARE(navigator.previousItem(), QMediaContent());
+ QCOMPARE(navigator.previousItem(2), QMediaContent());
+
+ navigator.jump(1);
+ QCOMPARE(navigator.currentIndex(), 1);
+ QCOMPARE(navigator.currentItem(), content2);
+ QCOMPARE(navigator.nextItem(), QMediaContent());
+ QCOMPARE(navigator.nextItem(2), QMediaContent());
+ QCOMPARE(navigator.previousItem(), content1);
+ QCOMPARE(navigator.previousItem(2), QMediaContent());
+
+ navigator.jump(0);
+ navigator.next();
+ QCOMPARE(navigator.currentIndex(), 1);
+ navigator.next();
+ QCOMPARE(navigator.currentIndex(), -1);
+ navigator.next();//jump to the first item
+ QCOMPARE(navigator.currentIndex(), 0);
+
+ navigator.previous();
+ QCOMPARE(navigator.currentIndex(), -1);
+ navigator.previous();//jump to the last item
+ QCOMPARE(navigator.currentIndex(), 1);
+}
+
+void tst_QMediaPlaylistNavigator::loopPlayback()
+{
+ QLocalMediaPlaylistProvider playlist;
+ QMediaPlaylistNavigator navigator(&playlist);
+
+ navigator.setPlaybackMode(QMediaPlaylist::Loop);
+ QTest::ignoreMessage(QtWarningMsg, "QMediaPlaylistNavigator: Jump outside playlist range ");
+ navigator.jump(0);
+ QVERIFY(navigator.currentItem().isNull());
+ QCOMPARE(navigator.currentIndex(), -1);
+
+ QMediaContent content1(QUrl(QLatin1String("file:///1")));
+ playlist.addMedia(content1);
+ navigator.jump(0);
+ QVERIFY(!navigator.currentItem().isNull());
+
+ QCOMPARE(navigator.currentIndex(), 0);
+ QCOMPARE(navigator.currentItem(), content1);
+ QCOMPARE(navigator.nextItem(), content1);
+ QCOMPARE(navigator.nextItem(2), content1);
+ QCOMPARE(navigator.previousItem(), content1);
+ QCOMPARE(navigator.previousItem(2), content1);
+
+ QMediaContent content2(QUrl(QLatin1String("file:///2")));
+ playlist.addMedia(content2);
+ QCOMPARE(navigator.currentIndex(), 0);
+ QCOMPARE(navigator.currentItem(), content1);
+ QCOMPARE(navigator.nextItem(), content2);
+ QCOMPARE(navigator.nextItem(2), content1); //loop over end of the list
+ QCOMPARE(navigator.previousItem(), content2);
+ QCOMPARE(navigator.previousItem(2), content1);
+
+ navigator.jump(1);
+ QCOMPARE(navigator.currentIndex(), 1);
+ QCOMPARE(navigator.currentItem(), content2);
+ QCOMPARE(navigator.nextItem(), content1);
+ QCOMPARE(navigator.nextItem(2), content2);
+ QCOMPARE(navigator.previousItem(), content1);
+ QCOMPARE(navigator.previousItem(2), content2);
+
+ navigator.jump(0);
+ navigator.next();
+ QCOMPARE(navigator.currentIndex(), 1);
+ navigator.next();
+ QCOMPARE(navigator.currentIndex(), 0);
+ navigator.previous();
+ QCOMPARE(navigator.currentIndex(), 1);
+ navigator.previous();
+ QCOMPARE(navigator.currentIndex(), 0);
+}
+
+void tst_QMediaPlaylistNavigator::currentItemOnce()
+{
+ QLocalMediaPlaylistProvider playlist;
+ QMediaPlaylistNavigator navigator(&playlist);
+
+ navigator.setPlaybackMode(QMediaPlaylist::CurrentItemOnce);
+
+ QCOMPARE(navigator.playbackMode(), QMediaPlaylist::CurrentItemOnce);
+ QCOMPARE(navigator.currentIndex(), -1);
+
+ playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///1"))));
+ playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///2"))));
+ playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///3"))));
+
+ QCOMPARE(navigator.currentIndex(), -1);
+ navigator.next();
+ QCOMPARE(navigator.currentIndex(), -1);
+
+ navigator.jump(1);
+ QCOMPARE(navigator.currentIndex(), 1);
+ navigator.next();
+ QCOMPARE(navigator.currentIndex(), -1);
+ navigator.next();
+ QCOMPARE(navigator.currentIndex(), -1);
+ navigator.previous();
+ QCOMPARE(navigator.currentIndex(), -1);
+ navigator.jump(1);
+ navigator.previous();
+ QCOMPARE(navigator.currentIndex(), -1);
+}
+
+void tst_QMediaPlaylistNavigator::currentItemInLoop()
+{
+ QLocalMediaPlaylistProvider playlist;
+ QMediaPlaylistNavigator navigator(&playlist);
+
+ navigator.setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
+
+ QCOMPARE(navigator.playbackMode(), QMediaPlaylist::CurrentItemInLoop);
+ QCOMPARE(navigator.currentIndex(), -1);
+
+ playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///1"))));
+ playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///2"))));
+ playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///3"))));
+
+ QCOMPARE(navigator.currentIndex(), -1);
+ navigator.next();
+ QCOMPARE(navigator.currentIndex(), -1);
+ navigator.jump(1);
+ navigator.next();
+ QCOMPARE(navigator.currentIndex(), 1);
+ navigator.next();
+ QCOMPARE(navigator.currentIndex(), 1);
+ navigator.previous();
+ QCOMPARE(navigator.currentIndex(), 1);
+ navigator.previous();
+ QCOMPARE(navigator.currentIndex(), 1);
+}
+
+void tst_QMediaPlaylistNavigator::randomPlayback()
+{
+ QLocalMediaPlaylistProvider playlist;
+ QMediaPlaylistNavigator navigator(&playlist);
+
+ navigator.setPlaybackMode(QMediaPlaylist::Random);
+
+ QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
+ QCOMPARE(navigator.currentIndex(), -1);
+
+ playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///1"))));
+ playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///2"))));
+ playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///3"))));
+
+ playlist.shuffle();
+
+ QCOMPARE(navigator.currentIndex(), -1);
+ navigator.next();
+ int pos1 = navigator.currentIndex();
+ navigator.next();
+ int pos2 = navigator.currentIndex();
+ navigator.next();
+ int pos3 = navigator.currentIndex();
+
+ QVERIFY(pos1 != -1);
+ QVERIFY(pos2 != -1);
+ QVERIFY(pos3 != -1);
+
+ navigator.previous();
+ QCOMPARE(navigator.currentIndex(), pos2);
+ navigator.next();
+ QCOMPARE(navigator.currentIndex(), pos3);
+ navigator.next();
+ int pos4 = navigator.currentIndex();
+ navigator.previous();
+ QCOMPARE(navigator.currentIndex(), pos3);
+ navigator.previous();
+ QCOMPARE(navigator.currentIndex(), pos2);
+ navigator.previous();
+ QCOMPARE(navigator.currentIndex(), pos1);
+ navigator.previous();
+ int pos0 = navigator.currentIndex();
+ QVERIFY(pos0 != -1);
+ navigator.next();
+ navigator.next();
+ navigator.next();
+ navigator.next();
+ QCOMPARE(navigator.currentIndex(), pos4);
+
+}
+
+QTEST_MAIN(tst_QMediaPlaylistNavigator)
+#include "tst_qmediaplaylistnavigator.moc"
diff --git a/tests/auto/qmediapluginloader/qmediapluginloader.pro b/tests/auto/qmediapluginloader/qmediapluginloader.pro
new file mode 100644
index 000000000..55f134495
--- /dev/null
+++ b/tests/auto/qmediapluginloader/qmediapluginloader.pro
@@ -0,0 +1,15 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qmediapluginloader
+# CONFIG += testcase
+
+SOURCES += tst_qmediapluginloader.cpp
+
+wince* {
+ PLUGIN_DEPLOY.sources = $$OUTPUT_DIR/plugins/mediaservice/*.dll
+ PLUGIN_DEPLOY.path = mediaservice
+ DEPLOYMENT += PLUGIN_DEPLOY
+}
+
diff --git a/tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp b/tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp
new file mode 100644
index 000000000..5d6bb7c8c
--- /dev/null
+++ b/tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <private/qmediapluginloader_p.h>
+#include <qmediaserviceproviderplugin.h>
+
+#include <QtTest/QtTest>
+#include <QDebug>
+
+QT_USE_NAMESPACE
+
+class tst_QMediaPluginLoader : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void testInstance();
+ void testInstances();
+ void testInvalidKey();
+
+private:
+ QMediaPluginLoader *loader;
+};
+
+void tst_QMediaPluginLoader::initTestCase()
+{
+ loader = new QMediaPluginLoader(QMediaServiceProviderFactoryInterface_iid,
+ QLatin1String("/mediaservice"),
+ Qt::CaseInsensitive);
+}
+
+void tst_QMediaPluginLoader::cleanupTestCase()
+{
+ delete loader;
+}
+
+void tst_QMediaPluginLoader::testInstance()
+{
+ const QStringList keys = loader->keys();
+
+ if (keys.isEmpty()) // Test is invalidated, skip.
+ QSKIP("No plug-ins available", SkipAll);
+
+ foreach (const QString &key, keys)
+ QVERIFY(loader->instance(key) != 0);
+}
+
+void tst_QMediaPluginLoader::testInstances()
+{
+ const QStringList keys = loader->keys();
+
+ if (keys.isEmpty()) // Test is invalidated, skip.
+ QSKIP("No plug-ins available", SkipAll);
+
+ foreach (const QString &key, keys)
+ QVERIFY(loader->instances(key).size() > 0);
+}
+
+// Last so as to not interfere with the other tests if there is a failure.
+void tst_QMediaPluginLoader::testInvalidKey()
+{
+ const QString key(QLatin1String("invalid-key"));
+
+ // This test assumes there is no 'invalid-key' in the key list, verify that.
+ if (loader->keys().contains(key))
+ QSKIP("a plug-in includes the invalid key", SkipAll);
+
+ QVERIFY(loader->instance(key) == 0);
+
+ // Test looking up the key hasn't inserted it into the list. See QMap::operator[].
+ QVERIFY(!loader->keys().contains(key));
+
+ QVERIFY(loader->instances(key).isEmpty());
+ QVERIFY(!loader->keys().contains(key));
+}
+
+QTEST_MAIN(tst_QMediaPluginLoader)
+
+#include "tst_qmediapluginloader.moc"
diff --git a/tests/auto/qmediarecorder/main.cpp b/tests/auto/qmediarecorder/main.cpp
new file mode 100755
index 000000000..816a55ea7
--- /dev/null
+++ b/tests/auto/qmediarecorder/main.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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.h>
+#include <QtTest/QtTest>
+
+#include "tst_qmediarecorder.h"
+
+#ifdef Q_OS_SYMBIAN
+#include "s60common.h"
+#include "tst_qmediarecorder_xa.h"
+#include "tst_qmediarecorder_mmf.h"
+#endif
+
+int main(int argc, char**argv)
+{
+ QApplication app(argc,argv);
+ int ret;
+ tst_QMediaRecorder test_api;
+ ret = QTest::qExec(&test_api, argc, argv);
+#ifdef Q_OS_SYMBIAN
+ char *new_argv[3];
+ QString str = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + ".log";
+ QByteArray bytes = str.toAscii();
+ char arg1[] = "-o";
+ new_argv[0] = argv[0];
+ new_argv[1] = arg1;
+ new_argv[2] = bytes.data();
+ tst_QMediaRecorder_xa test_xa;
+ ret = QTest::qExec(&test_xa, 3, new_argv);
+ char *new_argv1[3];
+ QString str1 = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_s60.log";
+ QByteArray bytes1 = str1.toAscii();
+ char arg2[] = "-o";
+ new_argv1[0] = argv[0];
+ new_argv1[1] = arg2;
+ new_argv1[2] = bytes1.data();
+ tst_QMediaRecorder_mmf test_mmf;
+ ret = QTest::qExec(&test_mmf, 3, new_argv1);
+
+#endif
+ return ret;
+}
diff --git a/tests/auto/qmediarecorder/qmediarecorder.pro b/tests/auto/qmediarecorder/qmediarecorder.pro
new file mode 100644
index 000000000..41e708fe7
--- /dev/null
+++ b/tests/auto/qmediarecorder/qmediarecorder.pro
@@ -0,0 +1,18 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qmediarecorder
+# CONFIG += testcase
+
+symbian {
+ HEADERS += s60common.h
+ HEADERS += tst_qmediarecorder_xa.h
+ SOURCES += tst_qmediarecorder_xa.cpp
+ HEADERS += tst_qmediarecorder_mmf.h
+ SOURCES += tst_qmediarecorder_mmf.cpp
+ TARGET.CAPABILITY = UserEnvironment ReadDeviceData WriteDeviceData AllFiles
+}
+HEADERS += tst_qmediarecorder.h
+SOURCES += main.cpp tst_qmediarecorder.cpp
+
diff --git a/tests/auto/qmediarecorder/s60common.h b/tests/auto/qmediarecorder/s60common.h
new file mode 100755
index 000000000..4e55004f8
--- /dev/null
+++ b/tests/auto/qmediarecorder/s60common.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** 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 S60COMMON_H
+#define S60COMMON_H
+
+QT_USE_NAMESPACE
+
+#define QTRY_COMPARE(a,e) \
+ for (int _i = 0; _i < 5000; _i += 100) { \
+ if ((a) == (e)) break; \
+ QTest::qWait(100); \
+ } \
+ QCOMPARE(a, e)
+
+#define QTRY_VERIFY(a) \
+ for (int _i = 0; _i < 5000; _i += 100) { \
+ if (a) break; \
+ QTest::qWait(100); \
+ } \
+ QVERIFY(a)
+
+#endif //S60COMMON_H
diff --git a/tests/auto/qmediarecorder/tst_qmediarecorder.cpp b/tests/auto/qmediarecorder/tst_qmediarecorder.cpp
new file mode 100644
index 000000000..b006efb4a
--- /dev/null
+++ b/tests/auto/qmediarecorder/tst_qmediarecorder.cpp
@@ -0,0 +1,796 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include "tst_qmediarecorder.h"
+
+QT_USE_NAMESPACE
+
+void tst_QMediaRecorder::initTestCase()
+{
+ qRegisterMetaType<QMediaRecorder::State>("QMediaRecorder::State");
+ qRegisterMetaType<QMediaRecorder::Error>("QMediaRecorder::Error");
+
+ mock = new MockProvider(this);
+ service = new MockService(this, mock);
+ object = new MockObject(this, service);
+ capture = new QMediaRecorder(object);
+
+ audio = qobject_cast<QAudioEndpointSelector*>(service->requestControl(QAudioEndpointSelector_iid));
+ encode = qobject_cast<QAudioEncoderControl*>(service->requestControl(QAudioEncoderControl_iid));
+ videoEncode = qobject_cast<QVideoEncoderControl*>(service->requestControl(QVideoEncoderControl_iid));
+}
+
+void tst_QMediaRecorder::cleanupTestCase()
+{
+ delete capture;
+ delete object;
+ delete service;
+ delete mock;
+}
+
+void tst_QMediaRecorder::testNullService()
+{
+ const QString id(QLatin1String("application/x-format"));
+
+ MockObject object(0, 0);
+ QMediaRecorder recorder(&object);
+
+ QCOMPARE(recorder.outputLocation(), QUrl());
+ QCOMPARE(recorder.state(), QMediaRecorder::StoppedState);
+ QCOMPARE(recorder.error(), QMediaRecorder::NoError);
+ QCOMPARE(recorder.duration(), qint64(0));
+ QCOMPARE(recorder.supportedContainers(), QStringList());
+ QCOMPARE(recorder.containerDescription(id), QString());
+ QCOMPARE(recorder.supportedAudioCodecs(), QStringList());
+ QCOMPARE(recorder.audioCodecDescription(id), QString());
+ QCOMPARE(recorder.supportedAudioSampleRates(), QList<int>());
+ QCOMPARE(recorder.supportedVideoCodecs(), QStringList());
+ QCOMPARE(recorder.videoCodecDescription(id), QString());
+ bool continuous = true;
+ QCOMPARE(recorder.supportedResolutions(QVideoEncoderSettings(), &continuous), QList<QSize>());
+ QCOMPARE(continuous, false);
+ continuous = true;
+ QCOMPARE(recorder.supportedFrameRates(QVideoEncoderSettings(), &continuous), QList<qreal>());
+ QCOMPARE(continuous, false);
+ QCOMPARE(recorder.audioSettings(), QAudioEncoderSettings());
+ QCOMPARE(recorder.videoSettings(), QVideoEncoderSettings());
+ QCOMPARE(recorder.containerMimeType(), QString());
+ QVERIFY(!recorder.isMuted());
+ recorder.setMuted(true);
+ QVERIFY(!recorder.isMuted());
+}
+
+void tst_QMediaRecorder::testNullControls()
+{
+ const QString id(QLatin1String("application/x-format"));
+
+ MockService service(0, 0);
+ service.hasControls = false;
+ MockObject object(0, &service);
+ QMediaRecorder recorder(&object);
+
+ QCOMPARE(recorder.outputLocation(), QUrl());
+ QCOMPARE(recorder.state(), QMediaRecorder::StoppedState);
+ QCOMPARE(recorder.error(), QMediaRecorder::NoError);
+ QCOMPARE(recorder.duration(), qint64(0));
+ QCOMPARE(recorder.supportedContainers(), QStringList());
+ QCOMPARE(recorder.containerDescription(id), QString());
+ QCOMPARE(recorder.supportedAudioCodecs(), QStringList());
+ QCOMPARE(recorder.audioCodecDescription(id), QString());
+ QCOMPARE(recorder.supportedAudioSampleRates(), QList<int>());
+ QCOMPARE(recorder.supportedVideoCodecs(), QStringList());
+ QCOMPARE(recorder.videoCodecDescription(id), QString());
+ bool continuous = true;
+ QCOMPARE(recorder.supportedResolutions(QVideoEncoderSettings(), &continuous), QList<QSize>());
+ QCOMPARE(continuous, false);
+ continuous = true;
+ QCOMPARE(recorder.supportedFrameRates(QVideoEncoderSettings(), &continuous), QList<qreal>());
+ QCOMPARE(continuous, false);
+ QCOMPARE(recorder.audioSettings(), QAudioEncoderSettings());
+ QCOMPARE(recorder.videoSettings(), QVideoEncoderSettings());
+ QCOMPARE(recorder.containerMimeType(), QString());
+
+ recorder.setOutputLocation(QUrl("file://test/save/file.mp4"));
+ QCOMPARE(recorder.outputLocation(), QUrl());
+
+ QAudioEncoderSettings audio;
+ audio.setCodec(id);
+ audio.setQuality(QtMultimediaKit::LowQuality);
+
+ QVideoEncoderSettings video;
+ video.setCodec(id);
+ video.setResolution(640, 480);
+
+ recorder.setEncodingSettings(audio, video, id);
+
+ QCOMPARE(recorder.audioSettings(), QAudioEncoderSettings());
+ QCOMPARE(recorder.videoSettings(), QVideoEncoderSettings());
+ QCOMPARE(recorder.containerMimeType(), QString());
+
+ QSignalSpy spy(&recorder, SIGNAL(stateChanged(QMediaRecorder::State)));
+
+ recorder.record();
+ QCOMPARE(recorder.state(), QMediaRecorder::StoppedState);
+ QCOMPARE(recorder.error(), QMediaRecorder::NoError);
+ QCOMPARE(spy.count(), 0);
+
+ recorder.pause();
+ QCOMPARE(recorder.state(), QMediaRecorder::StoppedState);
+ QCOMPARE(recorder.error(), QMediaRecorder::NoError);
+ QCOMPARE(spy.count(), 0);
+
+ recorder.stop();
+ QCOMPARE(recorder.state(), QMediaRecorder::StoppedState);
+ QCOMPARE(recorder.error(), QMediaRecorder::NoError);
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QMediaRecorder::testError()
+{
+ const QString errorString(QLatin1String("format error"));
+
+ QSignalSpy spy(capture, SIGNAL(error(QMediaRecorder::Error)));
+
+ QCOMPARE(capture->error(), QMediaRecorder::NoError);
+ QCOMPARE(capture->errorString(), QString());
+
+ mock->error(QMediaRecorder::FormatError, errorString);
+ QCOMPARE(capture->error(), QMediaRecorder::FormatError);
+ QCOMPARE(capture->errorString(), errorString);
+ QCOMPARE(spy.count(), 1);
+
+ QCOMPARE(spy.last()[0].value<QMediaRecorder::Error>(), QMediaRecorder::FormatError);
+}
+
+void tst_QMediaRecorder::testSink()
+{
+ capture->setOutputLocation(QUrl("test.tmp"));
+ QUrl s = capture->outputLocation();
+ QCOMPARE(s.toString(), QString("test.tmp"));
+}
+
+void tst_QMediaRecorder::testRecord()
+{
+ QSignalSpy stateSignal(capture,SIGNAL(stateChanged(QMediaRecorder::State)));
+ QSignalSpy progressSignal(capture, SIGNAL(durationChanged(qint64)));
+ capture->record();
+ QCOMPARE(capture->state(), QMediaRecorder::RecordingState);
+ QCOMPARE(capture->error(), QMediaRecorder::NoError);
+ QCOMPARE(capture->errorString(), QString());
+ QTestEventLoop::instance().enterLoop(1);
+ QCOMPARE(stateSignal.count(), 1);
+ QCOMPARE(stateSignal.last()[0].value<QMediaRecorder::State>(), QMediaRecorder::RecordingState);
+ QVERIFY(progressSignal.count() > 0);
+ capture->pause();
+ QCOMPARE(capture->state(), QMediaRecorder::PausedState);
+ QTestEventLoop::instance().enterLoop(1);
+ QCOMPARE(stateSignal.count(), 2);
+ capture->stop();
+ QCOMPARE(capture->state(), QMediaRecorder::StoppedState);
+ QTestEventLoop::instance().enterLoop(1);
+ QCOMPARE(stateSignal.count(), 3);
+ mock->stop();
+ QCOMPARE(stateSignal.count(), 3);
+
+}
+
+void tst_QMediaRecorder::testMute()
+{
+ QSignalSpy mutedChanged(capture, SIGNAL(mutedChanged(bool)));
+ QVERIFY(!capture->isMuted());
+ capture->setMuted(true);
+
+ QCOMPARE(mutedChanged.size(), 1);
+ QCOMPARE(mutedChanged[0][0].toBool(), true);
+ QVERIFY(capture->isMuted());
+
+ capture->setMuted(false);
+
+ QCOMPARE(mutedChanged.size(), 2);
+ QCOMPARE(mutedChanged[1][0].toBool(), false);
+ QVERIFY(!capture->isMuted());
+
+ capture->setMuted(false);
+ QCOMPARE(mutedChanged.size(), 2);
+}
+
+void tst_QMediaRecorder::testAudioDeviceControl()
+{
+ QSignalSpy readSignal(audio,SIGNAL(activeEndpointChanged(QString)));
+ QVERIFY(audio->availableEndpoints().size() == 3);
+ QVERIFY(audio->defaultEndpoint().compare("device1") == 0);
+ audio->setActiveEndpoint("device2");
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(audio->activeEndpoint().compare("device2") == 0);
+ QVERIFY(readSignal.count() == 1);
+ QVERIFY(audio->endpointDescription("device2").compare("dev2 comment") == 0);
+}
+
+void tst_QMediaRecorder::testAudioEncodeControl()
+{
+ QStringList codecs = capture->supportedAudioCodecs();
+ QVERIFY(codecs.count() == 2);
+ QVERIFY(capture->audioCodecDescription("audio/pcm") == "Pulse Code Modulation");
+ QStringList options = encode->supportedEncodingOptions("audio/mpeg");
+ QCOMPARE(options.count(), 4);
+ QVERIFY(encode->encodingOption("audio/mpeg","bitrate").isNull());
+ encode->setEncodingOption("audio/mpeg", "bitrate", QString("vbr"));
+ QCOMPARE(encode->encodingOption("audio/mpeg","bitrate").toString(), QString("vbr"));
+ QCOMPARE(capture->supportedAudioSampleRates(), QList<int>() << 44100);
+}
+
+void tst_QMediaRecorder::testMediaFormatsControl()
+{
+ QCOMPARE(capture->supportedContainers(), QStringList() << "wav" << "mp3" << "mov");
+
+ QCOMPARE(capture->containerDescription("wav"), QString("WAV format"));
+ QCOMPARE(capture->containerDescription("mp3"), QString("MP3 format"));
+ QCOMPARE(capture->containerDescription("ogg"), QString());
+}
+
+void tst_QMediaRecorder::testVideoEncodeControl()
+{
+ bool continuous = false;
+ QList<QSize> sizes = capture->supportedResolutions(QVideoEncoderSettings(), &continuous);
+ QCOMPARE(sizes.count(), 2);
+ QCOMPARE(continuous, true);
+
+ QList<qreal> rates = capture->supportedFrameRates(QVideoEncoderSettings(), &continuous);
+ QCOMPARE(rates.count(), 3);
+ QCOMPARE(continuous, false);
+
+ QStringList vCodecs = capture->supportedVideoCodecs();
+ QVERIFY(vCodecs.count() == 2);
+ QCOMPARE(capture->videoCodecDescription("video/3gpp"), QString("video/3gpp"));
+
+ QStringList options = videoEncode->supportedEncodingOptions("video/3gpp");
+ QCOMPARE(options.count(), 2);
+
+ QVERIFY(encode->encodingOption("video/3gpp","me").isNull());
+ encode->setEncodingOption("video/3gpp", "me", QString("dia"));
+ QCOMPARE(encode->encodingOption("video/3gpp","me").toString(), QString("dia"));
+
+}
+
+void tst_QMediaRecorder::testEncodingSettings()
+{
+ QAudioEncoderSettings audioSettings = capture->audioSettings();
+ QCOMPARE(audioSettings.codec(), QString("audio/pcm"));
+ QCOMPARE(audioSettings.bitRate(), 128*1024);
+ QCOMPARE(audioSettings.sampleRate(), -1);
+ QCOMPARE(audioSettings.quality(), QtMultimediaKit::NormalQuality);
+ QCOMPARE(audioSettings.channelCount(), -1);
+
+ QCOMPARE(audioSettings.encodingMode(), QtMultimediaKit::ConstantQualityEncoding);
+
+ QVideoEncoderSettings videoSettings = capture->videoSettings();
+ QCOMPARE(videoSettings.codec(), QString());
+ QCOMPARE(videoSettings.bitRate(), -1);
+ QCOMPARE(videoSettings.resolution(), QSize());
+ QCOMPARE(videoSettings.frameRate(), 0.0);
+ QCOMPARE(videoSettings.quality(), QtMultimediaKit::NormalQuality);
+ QCOMPARE(videoSettings.encodingMode(), QtMultimediaKit::ConstantQualityEncoding);
+
+ QString format = capture->containerMimeType();
+ QCOMPARE(format, QString());
+
+ audioSettings.setCodec("audio/mpeg");
+ audioSettings.setSampleRate(44100);
+ audioSettings.setBitRate(256*1024);
+ audioSettings.setQuality(QtMultimediaKit::HighQuality);
+ audioSettings.setEncodingMode(QtMultimediaKit::AverageBitRateEncoding);
+
+ videoSettings.setCodec("video/3gpp");
+ videoSettings.setBitRate(800);
+ videoSettings.setFrameRate(24*1024);
+ videoSettings.setResolution(QSize(800,600));
+ videoSettings.setQuality(QtMultimediaKit::HighQuality);
+ audioSettings.setEncodingMode(QtMultimediaKit::TwoPassEncoding);
+
+ format = QString("mov");
+
+ capture->setEncodingSettings(audioSettings,videoSettings,format);
+
+ QCOMPARE(capture->audioSettings(), audioSettings);
+ QCOMPARE(capture->videoSettings(), videoSettings);
+ QCOMPARE(capture->containerMimeType(), format);
+}
+
+void tst_QMediaRecorder::testAudioSettings()
+{
+ QAudioEncoderSettings settings;
+ QVERIFY(settings.isNull());
+ QVERIFY(settings == QAudioEncoderSettings());
+
+ QCOMPARE(settings.codec(), QString());
+ settings.setCodec(QLatin1String("codecName"));
+ QCOMPARE(settings.codec(), QLatin1String("codecName"));
+ QVERIFY(!settings.isNull());
+ QVERIFY(settings != QAudioEncoderSettings());
+
+ settings = QAudioEncoderSettings();
+ QCOMPARE(settings.bitRate(), -1);
+ settings.setBitRate(128000);
+ QCOMPARE(settings.bitRate(), 128000);
+ QVERIFY(!settings.isNull());
+
+ settings = QAudioEncoderSettings();
+ QCOMPARE(settings.quality(), QtMultimediaKit::NormalQuality);
+ settings.setQuality(QtMultimediaKit::HighQuality);
+ QCOMPARE(settings.quality(), QtMultimediaKit::HighQuality);
+ QVERIFY(!settings.isNull());
+
+ settings = QAudioEncoderSettings();
+ QCOMPARE(settings.sampleRate(), -1);
+ settings.setSampleRate(44100);
+ QCOMPARE(settings.sampleRate(), 44100);
+ QVERIFY(!settings.isNull());
+
+ settings = QAudioEncoderSettings();
+ QCOMPARE(settings.channelCount(), -1);
+ settings.setChannelCount(2);
+ QCOMPARE(settings.channelCount(), 2);
+ QVERIFY(!settings.isNull());
+
+ settings = QAudioEncoderSettings();
+ QVERIFY(settings.isNull());
+ QCOMPARE(settings.codec(), QString());
+ QCOMPARE(settings.bitRate(), -1);
+ QCOMPARE(settings.quality(), QtMultimediaKit::NormalQuality);
+ QCOMPARE(settings.sampleRate(), -1);
+
+ {
+ QAudioEncoderSettings settings1;
+ QAudioEncoderSettings settings2;
+ QCOMPARE(settings2, settings1);
+
+ settings2 = settings1;
+ QCOMPARE(settings2, settings1);
+ QVERIFY(settings2.isNull());
+
+ settings1.setQuality(QtMultimediaKit::HighQuality);
+
+ QVERIFY(settings2.isNull());
+ QVERIFY(!settings1.isNull());
+ QVERIFY(settings1 != settings2);
+ }
+
+ {
+ QAudioEncoderSettings settings1;
+ QAudioEncoderSettings settings2(settings1);
+ QCOMPARE(settings2, settings1);
+
+ settings2 = settings1;
+ QCOMPARE(settings2, settings1);
+ QVERIFY(settings2.isNull());
+
+ settings1.setQuality(QtMultimediaKit::HighQuality);
+
+ QVERIFY(settings2.isNull());
+ QVERIFY(!settings1.isNull());
+ QVERIFY(settings1 != settings2);
+ }
+
+ QAudioEncoderSettings settings1;
+ settings1.setBitRate(1);
+ QAudioEncoderSettings settings2;
+ settings2.setBitRate(1);
+ QVERIFY(settings1 == settings2);
+ settings2.setBitRate(2);
+ QVERIFY(settings1 != settings2);
+
+ settings1 = QAudioEncoderSettings();
+ settings1.setChannelCount(1);
+ settings2 = QAudioEncoderSettings();
+ settings2.setChannelCount(1);
+ QVERIFY(settings1 == settings2);
+ settings2.setChannelCount(2);
+ QVERIFY(settings1 != settings2);
+
+ settings1 = QAudioEncoderSettings();
+ settings1.setCodec("codec1");
+ settings2 = QAudioEncoderSettings();
+ settings2.setCodec("codec1");
+ QVERIFY(settings1 == settings2);
+ settings2.setCodec("codec2");
+ QVERIFY(settings1 != settings2);
+
+ settings1 = QAudioEncoderSettings();
+ settings1.setEncodingMode(QtMultimediaKit::ConstantBitRateEncoding);
+ settings2 = QAudioEncoderSettings();
+ settings2.setEncodingMode(QtMultimediaKit::ConstantBitRateEncoding);
+ QVERIFY(settings1 == settings2);
+ settings2.setEncodingMode(QtMultimediaKit::TwoPassEncoding);
+ QVERIFY(settings1 != settings2);
+
+ settings1 = QAudioEncoderSettings();
+ settings1.setQuality(QtMultimediaKit::NormalQuality);
+ settings2 = QAudioEncoderSettings();
+ settings2.setQuality(QtMultimediaKit::NormalQuality);
+ QVERIFY(settings1 == settings2);
+ settings2.setQuality(QtMultimediaKit::LowQuality);
+ QVERIFY(settings1 != settings2);
+
+ settings1 = QAudioEncoderSettings();
+ settings1.setSampleRate(1);
+ settings2 = QAudioEncoderSettings();
+ settings2.setSampleRate(1);
+ QVERIFY(settings1 == settings2);
+ settings2.setSampleRate(2);
+ QVERIFY(settings1 != settings2);
+}
+
+void tst_QMediaRecorder::testVideoSettings()
+{
+ QVideoEncoderSettings settings;
+ QVERIFY(settings.isNull());
+ QVERIFY(settings == QVideoEncoderSettings());
+
+ QCOMPARE(settings.codec(), QString());
+ settings.setCodec(QLatin1String("codecName"));
+ QCOMPARE(settings.codec(), QLatin1String("codecName"));
+ QVERIFY(!settings.isNull());
+ QVERIFY(settings != QVideoEncoderSettings());
+
+ settings = QVideoEncoderSettings();
+ QCOMPARE(settings.bitRate(), -1);
+ settings.setBitRate(128000);
+ QCOMPARE(settings.bitRate(), 128000);
+ QVERIFY(!settings.isNull());
+
+ settings = QVideoEncoderSettings();
+ QCOMPARE(settings.quality(), QtMultimediaKit::NormalQuality);
+ settings.setQuality(QtMultimediaKit::HighQuality);
+ QCOMPARE(settings.quality(), QtMultimediaKit::HighQuality);
+ QVERIFY(!settings.isNull());
+
+ settings = QVideoEncoderSettings();
+ QCOMPARE(settings.frameRate(), qreal());
+ settings.setFrameRate(30000.0/10001);
+ QVERIFY(qFuzzyCompare(settings.frameRate(), qreal(30000.0/10001)));
+ settings.setFrameRate(24.0);
+ QVERIFY(qFuzzyCompare(settings.frameRate(), qreal(24.0)));
+ QVERIFY(!settings.isNull());
+
+ settings = QVideoEncoderSettings();
+ QCOMPARE(settings.resolution(), QSize());
+ settings.setResolution(QSize(320,240));
+ QCOMPARE(settings.resolution(), QSize(320,240));
+ settings.setResolution(800,600);
+ QCOMPARE(settings.resolution(), QSize(800,600));
+ QVERIFY(!settings.isNull());
+
+ settings = QVideoEncoderSettings();
+ QVERIFY(settings.isNull());
+ QCOMPARE(settings.codec(), QString());
+ QCOMPARE(settings.bitRate(), -1);
+ QCOMPARE(settings.quality(), QtMultimediaKit::NormalQuality);
+ QCOMPARE(settings.frameRate(), qreal());
+ QCOMPARE(settings.resolution(), QSize());
+
+ {
+ QVideoEncoderSettings settings1;
+ QVideoEncoderSettings settings2;
+ QCOMPARE(settings2, settings1);
+
+ settings2 = settings1;
+ QCOMPARE(settings2, settings1);
+ QVERIFY(settings2.isNull());
+
+ settings1.setQuality(QtMultimediaKit::HighQuality);
+
+ QVERIFY(settings2.isNull());
+ QVERIFY(!settings1.isNull());
+ QVERIFY(settings1 != settings2);
+ }
+
+ {
+ QVideoEncoderSettings settings1;
+ QVideoEncoderSettings settings2(settings1);
+ QCOMPARE(settings2, settings1);
+
+ settings2 = settings1;
+ QCOMPARE(settings2, settings1);
+ QVERIFY(settings2.isNull());
+
+ settings1.setQuality(QtMultimediaKit::HighQuality);
+
+ QVERIFY(settings2.isNull());
+ QVERIFY(!settings1.isNull());
+ QVERIFY(settings1 != settings2);
+ }
+
+ QVideoEncoderSettings settings1;
+ settings1.setBitRate(1);
+ QVideoEncoderSettings settings2;
+ settings2.setBitRate(1);
+ QVERIFY(settings1 == settings2);
+ settings2.setBitRate(2);
+ QVERIFY(settings1 != settings2);
+
+ settings1 = QVideoEncoderSettings();
+ settings1.setResolution(800,600);
+ settings2 = QVideoEncoderSettings();
+ settings2.setResolution(QSize(800,600));
+ QVERIFY(settings1 == settings2);
+ settings2.setResolution(QSize(400,300));
+ QVERIFY(settings1 != settings2);
+
+ settings1 = QVideoEncoderSettings();
+ settings1.setCodec("codec1");
+ settings2 = QVideoEncoderSettings();
+ settings2.setCodec("codec1");
+ QVERIFY(settings1 == settings2);
+ settings2.setCodec("codec2");
+ QVERIFY(settings1 != settings2);
+
+ settings1 = QVideoEncoderSettings();
+ settings1.setEncodingMode(QtMultimediaKit::ConstantBitRateEncoding);
+ settings2 = QVideoEncoderSettings();
+ settings2.setEncodingMode(QtMultimediaKit::ConstantBitRateEncoding);
+ QVERIFY(settings1 == settings2);
+ settings2.setEncodingMode(QtMultimediaKit::TwoPassEncoding);
+ QVERIFY(settings1 != settings2);
+
+ settings1 = QVideoEncoderSettings();
+ settings1.setQuality(QtMultimediaKit::NormalQuality);
+ settings2 = QVideoEncoderSettings();
+ settings2.setQuality(QtMultimediaKit::NormalQuality);
+ QVERIFY(settings1 == settings2);
+ settings2.setQuality(QtMultimediaKit::LowQuality);
+ QVERIFY(settings1 != settings2);
+
+ settings1 = QVideoEncoderSettings();
+ settings1.setFrameRate(1);
+ settings2 = QVideoEncoderSettings();
+ settings2.setFrameRate(1);
+ QVERIFY(settings1 == settings2);
+ settings2.setFrameRate(2);
+ QVERIFY(settings1 != settings2);
+}
+
+
+void tst_QMediaRecorder::nullMetaDataControl()
+{
+ const QString titleKey(QLatin1String("Title"));
+ const QString title(QLatin1String("Host of Seraphim"));
+
+ MockProvider recorderControl(0);
+ MockService service(0, &recorderControl);
+ service.hasControls = false;
+ MockObject object(0, &service);
+
+ QMediaRecorder recorder(&object);
+
+ QSignalSpy spy(&recorder, SIGNAL(metaDataChanged()));
+
+ QCOMPARE(recorder.isMetaDataAvailable(), false);
+ QCOMPARE(recorder.isMetaDataWritable(), false);
+
+ recorder.setMetaData(QtMultimediaKit::Title, title);
+ recorder.setExtendedMetaData(titleKey, title);
+
+ QCOMPARE(recorder.metaData(QtMultimediaKit::Title).toString(), QString());
+ QCOMPARE(recorder.extendedMetaData(titleKey).toString(), QString());
+ QCOMPARE(recorder.availableMetaData(), QList<QtMultimediaKit::MetaData>());
+ QCOMPARE(recorder.availableExtendedMetaData(), QStringList());
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QMediaRecorder::isMetaDataAvailable()
+{
+ MockProvider recorderControl(0);
+ MockService service(0, &recorderControl);
+ service.mockMetaDataControl->setMetaDataAvailable(false);
+ MockObject object(0, &service);
+
+ QMediaRecorder recorder(&object);
+ QCOMPARE(recorder.isMetaDataAvailable(), false);
+
+ QSignalSpy spy(&recorder, SIGNAL(metaDataAvailableChanged(bool)));
+ service.mockMetaDataControl->setMetaDataAvailable(true);
+
+ QCOMPARE(recorder.isMetaDataAvailable(), true);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), true);
+
+ service.mockMetaDataControl->setMetaDataAvailable(false);
+
+ QCOMPARE(recorder.isMetaDataAvailable(), false);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.at(1).at(0).toBool(), false);
+}
+
+void tst_QMediaRecorder::isWritable()
+{
+ MockProvider recorderControl(0);
+ MockService service(0, &recorderControl);
+ service.mockMetaDataControl->setWritable(false);
+
+ MockObject object(0, &service);
+
+ QMediaRecorder recorder(&object);
+
+ QSignalSpy spy(&recorder, SIGNAL(metaDataWritableChanged(bool)));
+
+ QCOMPARE(recorder.isMetaDataWritable(), false);
+
+ service.mockMetaDataControl->setWritable(true);
+
+ QCOMPARE(recorder.isMetaDataWritable(), true);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toBool(), true);
+
+ service.mockMetaDataControl->setWritable(false);
+
+ QCOMPARE(recorder.isMetaDataWritable(), false);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.at(1).at(0).toBool(), false);
+}
+
+void tst_QMediaRecorder::metaDataChanged()
+{
+ MockProvider recorderControl(0);
+ MockService service(0, &recorderControl);
+ MockObject object(0, &service);
+
+ QMediaRecorder recorder(&object);
+
+ QSignalSpy spy(&recorder, SIGNAL(metaDataChanged()));
+
+ service.mockMetaDataControl->metaDataChanged();
+ QCOMPARE(spy.count(), 1);
+
+ service.mockMetaDataControl->metaDataChanged();
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_QMediaRecorder::metaData_data()
+{
+ QTest::addColumn<QString>("artist");
+ QTest::addColumn<QString>("title");
+ QTest::addColumn<QString>("genre");
+
+ QTest::newRow("")
+ << QString::fromLatin1("Dead Can Dance")
+ << QString::fromLatin1("Host of Seraphim")
+ << QString::fromLatin1("Awesome");
+}
+
+void tst_QMediaRecorder::metaData()
+{
+ QFETCH(QString, artist);
+ QFETCH(QString, title);
+ QFETCH(QString, genre);
+
+ MockProvider recorderControl(0);
+ MockService service(0, &recorderControl);
+ service.mockMetaDataControl->populateMetaData();
+
+ MockObject object(0, &service);
+
+ QMediaRecorder recorder(&object);
+ QVERIFY(object.availableMetaData().isEmpty());
+
+ service.mockMetaDataControl->m_data.insert(QtMultimediaKit::AlbumArtist, artist);
+ service.mockMetaDataControl->m_data.insert(QtMultimediaKit::Title, title);
+ service.mockMetaDataControl->m_data.insert(QtMultimediaKit::Genre, genre);
+
+ QCOMPARE(recorder.metaData(QtMultimediaKit::AlbumArtist).toString(), artist);
+ QCOMPARE(recorder.metaData(QtMultimediaKit::Title).toString(), title);
+
+ QList<QtMultimediaKit::MetaData> metaDataKeys = recorder.availableMetaData();
+ QCOMPARE(metaDataKeys.size(), 3);
+ QVERIFY(metaDataKeys.contains(QtMultimediaKit::AlbumArtist));
+ QVERIFY(metaDataKeys.contains(QtMultimediaKit::Title));
+ QVERIFY(metaDataKeys.contains(QtMultimediaKit::Genre));
+}
+
+void tst_QMediaRecorder::setMetaData_data()
+{
+ QTest::addColumn<QString>("title");
+
+ QTest::newRow("")
+ << QString::fromLatin1("In the Kingdom of the Blind the One eyed are Kings");
+}
+
+void tst_QMediaRecorder::setMetaData()
+{
+ QFETCH(QString, title);
+
+ MockProvider recorderControl(0);
+ MockService service(0, &recorderControl);
+ service.mockMetaDataControl->populateMetaData();
+
+ MockObject object(0, &service);
+
+ QMediaRecorder recorder(&object);
+
+ recorder.setMetaData(QtMultimediaKit::Title, title);
+ QCOMPARE(recorder.metaData(QtMultimediaKit::Title).toString(), title);
+ QCOMPARE(service.mockMetaDataControl->m_data.value(QtMultimediaKit::Title).toString(), title);
+}
+
+void tst_QMediaRecorder::extendedMetaData()
+{
+ QFETCH(QString, artist);
+ QFETCH(QString, title);
+ QFETCH(QString, genre);
+
+ MockProvider recorderControl(0);
+ MockService service(0, &recorderControl);
+ MockObject object(0, &service);
+
+ QMediaRecorder recorder(&object);
+ QVERIFY(recorder.availableExtendedMetaData().isEmpty());
+
+ service.mockMetaDataControl->m_extendedData.insert(QLatin1String("Artist"), artist);
+ service.mockMetaDataControl->m_extendedData.insert(QLatin1String("Title"), title);
+ service.mockMetaDataControl->m_extendedData.insert(QLatin1String("Genre"), genre);
+
+ QCOMPARE(recorder.extendedMetaData(QLatin1String("Artist")).toString(), artist);
+ QCOMPARE(recorder.extendedMetaData(QLatin1String("Title")).toString(), title);
+
+ QStringList extendedKeys = recorder.availableExtendedMetaData();
+ QCOMPARE(extendedKeys.size(), 3);
+ QVERIFY(extendedKeys.contains(QLatin1String("Artist")));
+ QVERIFY(extendedKeys.contains(QLatin1String("Title")));
+ QVERIFY(extendedKeys.contains(QLatin1String("Genre")));
+}
+
+void tst_QMediaRecorder::setExtendedMetaData()
+{
+ MockProvider recorderControl(0);
+ MockService service(0, &recorderControl);
+ service.mockMetaDataControl->populateMetaData();
+
+ MockObject object(0, &service);
+
+ QMediaRecorder recorder(&object);
+
+ QString title(QLatin1String("In the Kingdom of the Blind the One eyed are Kings"));
+
+ recorder.setExtendedMetaData(QLatin1String("Title"), title);
+ QCOMPARE(recorder.extendedMetaData(QLatin1String("Title")).toString(), title);
+ QCOMPARE(service.mockMetaDataControl->m_extendedData.value(QLatin1String("Title")).toString(), title);
+}
diff --git a/tests/auto/qmediarecorder/tst_qmediarecorder.h b/tests/auto/qmediarecorder/tst_qmediarecorder.h
new file mode 100755
index 000000000..4ac7bfbab
--- /dev/null
+++ b/tests/auto/qmediarecorder/tst_qmediarecorder.h
@@ -0,0 +1,516 @@
+/****************************************************************************
+**
+** 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 TST_QMEDIARECORDER_H
+#define TST_QMEDIARECORDER_H
+
+#include <QtTest/QtTest>
+#include <QDebug>
+#include <qmediaobject.h>
+#include <qmediacontrol.h>
+#include <qmediaservice.h>
+#include <qmediarecordercontrol.h>
+#include <qmediarecorder.h>
+#include <qmetadatawritercontrol.h>
+#include <qaudioendpointselector.h>
+#include <qaudioencodercontrol.h>
+#include <qmediacontainercontrol.h>
+#include <qvideoencodercontrol.h>
+
+#include <qaudioformat.h>
+
+QT_USE_NAMESPACE
+class MockMediaContainerControl : public QMediaContainerControl
+{
+ Q_OBJECT
+public:
+ MockMediaContainerControl(QObject *parent):
+ QMediaContainerControl(parent)
+ {
+ m_supportedContainers.append("wav");
+ m_supportedContainers.append("mp3");
+ m_supportedContainers.append("mov");
+
+ m_descriptions.insert("wav", "WAV format");
+ m_descriptions.insert("mp3", "MP3 format");
+ m_descriptions.insert("mov", "MOV format");
+ }
+
+ virtual ~MockMediaContainerControl() {};
+
+ QStringList supportedContainers() const
+ {
+ return m_supportedContainers;
+ }
+
+ QString containerMimeType() const
+ {
+ return m_format;
+ }
+
+ void setContainerMimeType(const QString &formatMimeType)
+ {
+ if (m_supportedContainers.contains(formatMimeType))
+ m_format = formatMimeType;
+ }
+
+ QString containerDescription(const QString &formatMimeType) const
+ {
+ return m_descriptions.value(formatMimeType);
+ }
+
+private:
+ QStringList m_supportedContainers;
+ QMap<QString, QString> m_descriptions;
+ QString m_format;
+};
+
+class MockVideoEncodeProvider : public QVideoEncoderControl
+{
+ Q_OBJECT
+public:
+ MockVideoEncodeProvider(QObject *parent):
+ QVideoEncoderControl(parent)
+ {
+ m_supportedEncodeOptions.insert("video/3gpp", QStringList() << "quantizer" << "me");
+ m_supportedEncodeOptions.insert("video/H264", QStringList() << "quantizer" << "me" << "bframes");
+ m_videoCodecs << "video/3gpp" << "video/H264";
+ m_sizes << QSize(320,240) << QSize(640,480);
+ m_framerates << 30 << 15 << 1;
+ }
+ ~MockVideoEncodeProvider() {}
+
+ QVideoEncoderSettings videoSettings() const { return m_videoSettings; }
+ void setVideoSettings(const QVideoEncoderSettings &settings) { m_videoSettings = settings; };
+
+ QList<QSize> supportedResolutions(const QVideoEncoderSettings & = QVideoEncoderSettings(),
+ bool *continuous = 0) const
+ {
+ if (continuous)
+ *continuous = true;
+
+ return m_sizes;
+ }
+
+ QList<qreal> supportedFrameRates(const QVideoEncoderSettings & = QVideoEncoderSettings(),
+ bool *continuous = 0) const
+ {
+ if (continuous)
+ *continuous = false;
+
+ return m_framerates;
+ }
+
+ QStringList supportedVideoCodecs() const { return m_videoCodecs; }
+ QString videoCodecDescription(const QString &codecName) const { return codecName; }
+
+ QStringList supportedEncodingOptions(const QString &codec) const
+ {
+ return m_supportedEncodeOptions.value(codec);
+ }
+
+ QVariant encodingOption(const QString &codec, const QString &name) const
+ {
+ return m_encodeOptions[codec].value(name);
+ }
+
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value)
+ {
+ m_encodeOptions[codec][name] = value;
+ }
+
+private:
+ QVideoEncoderSettings m_videoSettings;
+
+ QMap<QString, QStringList> m_supportedEncodeOptions;
+ QMap< QString, QMap<QString, QVariant> > m_encodeOptions;
+
+ QStringList m_videoCodecs;
+ QList<QSize> m_sizes;
+ QList<qreal> m_framerates;
+};
+
+class MockAudioEncodeProvider : public QAudioEncoderControl
+{
+ Q_OBJECT
+public:
+ MockAudioEncodeProvider(QObject *parent):
+ QAudioEncoderControl(parent)
+ {
+ m_codecs << "audio/pcm" << "audio/mpeg";
+ m_supportedEncodeOptions.insert("audio/pcm", QStringList());
+ m_supportedEncodeOptions.insert("audio/mpeg", QStringList() << "quality" << "bitrate" << "mode" << "vbr");
+ m_audioSettings.setCodec("audio/pcm");
+ m_audioSettings.setBitRate(128*1024);
+ }
+
+ ~MockAudioEncodeProvider() {}
+
+ QAudioEncoderSettings audioSettings() const { return m_audioSettings; }
+ void setAudioSettings(const QAudioEncoderSettings &settings) { m_audioSettings = settings; }
+
+ QList<int> supportedSampleRates(const QAudioEncoderSettings & = QAudioEncoderSettings(), bool *continuous = 0) const
+ {
+ if (continuous)
+ *continuous = false;
+
+ return QList<int>() << 44100;
+ }
+
+ QStringList supportedAudioCodecs() const
+ {
+ return m_codecs;
+ }
+
+ QString codecDescription(const QString &codecName) const
+ {
+ if (codecName == "audio/pcm")
+ return QString("Pulse Code Modulation");
+
+ if (codecName == "audio/mpeg")
+ return QString("MP3 audio format");
+
+ return QString();
+ }
+
+
+ QStringList supportedEncodingOptions(const QString &codec) const
+ {
+ return m_supportedEncodeOptions.value(codec);
+ }
+
+ QVariant encodingOption(const QString &codec, const QString &name) const
+ {
+ return m_encodeOptions[codec].value(name);
+ }
+
+ void setEncodingOption(const QString &codec, const QString &name, const QVariant &value)
+ {
+ m_encodeOptions[codec][name] = value;
+ }
+
+private:
+ QAudioEncoderSettings m_audioSettings;
+
+ QStringList m_codecs;
+ QStringList m_codecsDesc;
+
+ QMap<QString, QStringList> m_supportedEncodeOptions;
+ QMap< QString, QMap<QString, QVariant> > m_encodeOptions;
+
+};
+
+class MockAudioEndpointSelectorProvider : public QAudioEndpointSelector
+{
+ Q_OBJECT
+public:
+ MockAudioEndpointSelectorProvider(QObject *parent):
+ QAudioEndpointSelector(parent)
+ {
+ m_names << "device1" << "device2" << "device3";
+ m_descriptions << "dev1 comment" << "dev2 comment" << "dev3 comment";
+ emit availableEndpointsChanged();
+ }
+ ~MockAudioEndpointSelectorProvider() {};
+
+ QList<QString> availableEndpoints() const
+ {
+ return m_names;
+ }
+
+ QString endpointDescription(const QString& name) const
+ {
+ QString desc;
+
+ for(int i = 0; i < m_names.count(); i++) {
+ if (m_names.at(i).compare(name) == 0) {
+ desc = m_descriptions.at(i);
+ break;
+ }
+ }
+ return desc;
+ }
+
+ QString defaultEndpoint() const
+ {
+ return m_names.at(0);
+ }
+
+ QString activeEndpoint() const
+ {
+ return m_audioInput;
+ }
+
+public Q_SLOTS:
+
+ void setActiveEndpoint(const QString& name)
+ {
+ m_audioInput = name;
+ emit activeEndpointChanged(name);
+ }
+
+private:
+ QString m_audioInput;
+ QList<QString> m_names;
+ QList<QString> m_descriptions;
+};
+
+class MockProvider : public QMediaRecorderControl
+{
+ Q_OBJECT
+
+public:
+ MockProvider(QObject *parent):
+ QMediaRecorderControl(parent),
+ m_state(QMediaRecorder::StoppedState),
+ m_position(0),
+ m_muted(false) {}
+
+ QUrl outputLocation() const
+ {
+ return m_sink;
+ }
+
+ bool setOutputLocation(const QUrl &sink)
+ {
+ m_sink = sink;
+ return true;
+ }
+
+ QMediaRecorder::State state() const
+ {
+ return m_state;
+ }
+
+ qint64 duration() const
+ {
+ return m_position;
+ }
+
+ bool isMuted() const
+ {
+ return m_muted;
+ }
+
+ void applySettings() {}
+
+ using QMediaRecorderControl::error;
+
+public slots:
+ void record()
+ {
+ m_state = QMediaRecorder::RecordingState;
+ m_position=1;
+ emit stateChanged(m_state);
+ emit durationChanged(m_position);
+ }
+
+ void pause()
+ {
+ m_state = QMediaRecorder::PausedState;
+ emit stateChanged(m_state);
+ }
+
+ void stop()
+ {
+ m_position=0;
+ m_state = QMediaRecorder::StoppedState;
+ emit stateChanged(m_state);
+ }
+
+ void setMuted(bool muted)
+ {
+ if (m_muted != muted)
+ emit mutedChanged(m_muted = muted);
+ }
+
+public:
+ QUrl m_sink;
+ QMediaRecorder::State m_state;
+ qint64 m_position;
+ bool m_muted;
+};
+
+
+class QtTestMetaDataProvider : public QMetaDataWriterControl
+{
+ Q_OBJECT
+public:
+ QtTestMetaDataProvider(QObject *parent = 0)
+ : QMetaDataWriterControl(parent)
+ , m_available(false)
+ , m_writable(false)
+ {
+ }
+
+ bool isMetaDataAvailable() const { return m_available; }
+ void setMetaDataAvailable(bool available) {
+ if (m_available != available)
+ emit metaDataAvailableChanged(m_available = available);
+ }
+ QList<QtMultimediaKit::MetaData> availableMetaData() const { return m_data.keys(); }
+
+ bool isWritable() const { return m_writable; }
+ void setWritable(bool writable) { emit writableChanged(m_writable = writable); }
+
+ QVariant metaData(QtMultimediaKit::MetaData key) const { return m_data.value(key); }
+ void setMetaData(QtMultimediaKit::MetaData key, const QVariant &value) {
+ m_data.insert(key, value); }
+
+ QVariant extendedMetaData(const QString &key) const { return m_extendedData.value(key); }
+ void setExtendedMetaData(const QString &key, const QVariant &value) {
+ m_extendedData.insert(key, value); }
+
+ QStringList availableExtendedMetaData() const { return m_extendedData.keys(); }
+
+ using QMetaDataWriterControl::metaDataChanged;
+
+ void populateMetaData()
+ {
+ m_available = true;
+ }
+
+ bool m_available;
+ bool m_writable;
+ QMap<QtMultimediaKit::MetaData, QVariant> m_data;
+ QMap<QString, QVariant> m_extendedData;
+};
+
+class MockService : public QMediaService
+{
+ Q_OBJECT
+public:
+ MockService(QObject *parent, QMediaControl *control):
+ QMediaService(parent),
+ mockControl(control),
+ hasControls(true)
+ {
+ mockAudioEndpointSelector = new MockAudioEndpointSelectorProvider(parent);
+ mockAudioEncodeControl = new MockAudioEncodeProvider(parent);
+ mockFormatControl = new MockMediaContainerControl(parent);
+ mockVideoEncodeControl = new MockVideoEncodeProvider(parent);
+ mockMetaDataControl = new QtTestMetaDataProvider(parent);
+ }
+
+ QMediaControl* requestControl(const char *name)
+ {
+ if(hasControls && qstrcmp(name,QAudioEncoderControl_iid) == 0)
+ return mockAudioEncodeControl;
+ if(hasControls && qstrcmp(name,QAudioEndpointSelector_iid) == 0)
+ return mockAudioEndpointSelector;
+ if(hasControls && qstrcmp(name,QMediaRecorderControl_iid) == 0)
+ return mockControl;
+ if(hasControls && qstrcmp(name,QMediaContainerControl_iid) == 0)
+ return mockFormatControl;
+ if(hasControls && qstrcmp(name,QVideoEncoderControl_iid) == 0)
+ return mockVideoEncodeControl;
+ if (hasControls && qstrcmp(name, QMetaDataWriterControl_iid) == 0)
+ return mockMetaDataControl;
+
+ return 0;
+ }
+
+ void releaseControl(QMediaControl*) {}
+
+ QMediaControl *mockControl;
+ QAudioEndpointSelector *mockAudioEndpointSelector;
+ QAudioEncoderControl *mockAudioEncodeControl;
+ QMediaContainerControl *mockFormatControl;
+ QVideoEncoderControl *mockVideoEncodeControl;
+ QtTestMetaDataProvider *mockMetaDataControl;
+ bool hasControls;
+};
+
+class MockObject : public QMediaObject
+{
+ Q_OBJECT
+public:
+ MockObject(QObject *parent, MockService *service):
+ QMediaObject(parent, service)
+ {
+ }
+};
+
+class tst_QMediaRecorder: public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void testNullService();
+ void testNullControls();
+ void testError();
+ void testSink();
+ void testRecord();
+ void testMute();
+ void testAudioDeviceControl();
+ void testAudioEncodeControl();
+ void testMediaFormatsControl();
+ void testVideoEncodeControl();
+ void testEncodingSettings();
+ void testAudioSettings();
+ void testVideoSettings();
+
+ void nullMetaDataControl();
+ void isMetaDataAvailable();
+ void isWritable();
+ void metaDataChanged();
+ void metaData_data();
+ void metaData();
+ void setMetaData_data();
+ void setMetaData();
+ void extendedMetaData_data() { metaData_data(); }
+ void extendedMetaData();
+ void setExtendedMetaData_data() { extendedMetaData_data(); }
+ void setExtendedMetaData();
+
+private:
+ QAudioEncoderControl* encode;
+ QAudioEndpointSelector* audio;
+ MockObject *object;
+ MockService *service;
+ MockProvider *mock;
+ QMediaRecorder *capture;
+ QVideoEncoderControl* videoEncode;
+};
+#endif //TST_QMEDIARECORDER_H
diff --git a/tests/auto/qmediarecorder/tst_qmediarecorder_mmf.cpp b/tests/auto/qmediarecorder/tst_qmediarecorder_mmf.cpp
new file mode 100755
index 000000000..48327bdd0
--- /dev/null
+++ b/tests/auto/qmediarecorder/tst_qmediarecorder_mmf.cpp
@@ -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 "tst_qmediarecorder_mmf.h"
+
+QT_USE_NAMESPACE
+
+void tst_QMediaRecorder_mmf::initTestCase()
+{
+ qRegisterMetaType<QMediaRecorder::State>("QMediaRecorder::State");
+ qRegisterMetaType<QMediaRecorder::Error>("QMediaRecorder::Error");
+
+ captureSource = new QAudioCaptureSource;
+ audiocapture = new QMediaRecorder(captureSource);
+
+ QVERIFY(captureSource->service());
+
+ audioEndpoint = qobject_cast<QAudioEndpointSelector*>(captureSource->service()->requestControl(QAudioEndpointSelector_iid));
+ audioEncoder = qobject_cast<QAudioEncoderControl*>(captureSource->service()->requestControl(QAudioEncoderControl_iid));
+}
+
+void tst_QMediaRecorder_mmf::cleanupTestCase()
+{
+ delete audiocapture;
+ delete captureSource;
+}
+
+QUrl tst_QMediaRecorder_mmf::recordPathAudio(QDir outputDir)
+{
+ int lastImage = 0;
+ int fileCount = 0;
+ foreach( QString fileName, outputDir.entryList(QStringList() << "testclip_*.amr") ) {
+ int imgNumber = fileName.mid(5, fileName.size()-9).toInt();
+ lastImage = qMax(lastImage, imgNumber);
+ if (outputDir.exists(fileName))
+ fileCount+=1;
+ }
+ lastImage+=fileCount;
+
+ QUrl location(QDir::toNativeSeparators(outputDir.canonicalPath()+QString("/testclip_%1.amr").arg(lastImage+1,4,10,QLatin1Char('0'))));
+ return location;
+}
+
+void tst_QMediaRecorder_mmf::testAudioSink()
+{
+ audiocapture->setOutputLocation(QUrl("test.tmp"));
+ QUrl s = audiocapture->outputLocation();
+ QCOMPARE(s.toString(), QString("test.tmp"));
+}
+
+void tst_QMediaRecorder_mmf::testAudioRecord()
+{
+ QSignalSpy stateSignal(audiocapture,SIGNAL(stateChanged(QMediaRecorder::State)));
+ QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
+ QTest::qWait(500); // wait for recorder to initialize itself
+ audiocapture->setOutputLocation(recordPathAudio(QDir::rootPath()));
+ audiocapture->record();
+ QTRY_COMPARE(stateSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QCOMPARE(audiocapture->state(), QMediaRecorder::RecordingState);
+ QCOMPARE(audiocapture->error(), QMediaRecorder::NoError);
+ QCOMPARE(audiocapture->errorString(), QString());
+ QCOMPARE(stateSignal.count(), 1);
+ audiocapture->pause();
+ QTRY_COMPARE(stateSignal.count(), 2); // wait for callbacks to complete in symbian API
+ QCOMPARE(audiocapture->state(), QMediaRecorder::PausedState);
+ QCOMPARE(stateSignal.count(), 2);
+ audiocapture->stop();
+ QTRY_COMPARE(stateSignal.count(), 3); // wait for callbacks to complete in symbian API
+ QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
+ QCOMPARE(stateSignal.count(), 3);
+}
+
+void tst_QMediaRecorder_mmf::testAudioRecordWithAMR()
+{
+ QSignalSpy stateSignal(audiocapture,SIGNAL(stateChanged(QMediaRecorder::State)));
+ QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
+ audiocapture->setOutputLocation(recordPathAudio(QDir::rootPath()));
+ QAudioEncoderSettings audioSettings;
+ QVideoEncoderSettings videoSettings;
+ audioSettings.setCodec("AMR");
+ QString format = audiocapture->containerMimeType();
+ format = QString("audio/amr");
+ audiocapture->setEncodingSettings(audioSettings,videoSettings,format);
+ audiocapture->record();
+ QTRY_COMPARE(stateSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QCOMPARE(audiocapture->state(), QMediaRecorder::RecordingState);
+ QCOMPARE(audiocapture->error(), QMediaRecorder::NoError);
+ QCOMPARE(audiocapture->errorString(), QString());
+ QCOMPARE(stateSignal.count(), 1);
+ audiocapture->pause();
+ QTRY_COMPARE(stateSignal.count(), 2); // wait for callbacks to complete in symbian API
+ QCOMPARE(audiocapture->state(), QMediaRecorder::PausedState);
+ QCOMPARE(stateSignal.count(), 2);
+ audiocapture->stop();
+ QTRY_COMPARE(stateSignal.count(), 3); // wait for callbacks to complete in symbian API
+ QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
+ QCOMPARE(stateSignal.count(), 3);
+}
+
+void tst_QMediaRecorder_mmf::testAudioEndPointSelector()
+{
+ QSignalSpy audioSignal(audioEndpoint,SIGNAL(activeEndpointChanged(QString)));
+ QVERIFY(audioEndpoint->availableEndpoints().count() == 1);
+ QVERIFY(audioEndpoint->defaultEndpoint().compare("default") == 0);
+ audioEndpoint->setActiveEndpoint("device2");
+ QVERIFY(audioEndpoint->activeEndpoint().compare("device2") == 0);
+ QVERIFY(audioSignal.count() == 1);
+ QVERIFY(audioEndpoint->endpointDescription("device2").compare("") == 0);
+}
+
+void tst_QMediaRecorder_mmf::testAudioEncoderControl()
+{
+ QStringList codecs = audiocapture->supportedAudioCodecs();
+ QVERIFY(codecs.count() == 2);
+ QVERIFY(audiocapture->audioCodecDescription("PCM") == "Pulse code modulation");
+ QStringList options = audioEncoder->supportedEncodingOptions("PCM");
+ QCOMPARE(options.count(), 3);
+ QCOMPARE(audiocapture->supportedAudioSampleRates().count(), 12);
+ audioEncoder->setEncodingOption("PCM", "channels", QVariant(2));
+ QCOMPARE(audioEncoder->encodingOption("PCM","channels").toInt(), 2);
+ audioEncoder->setEncodingOption("PCM", "quality", QVariant(int(QtMultimediaKit::NormalQuality)));
+ QCOMPARE(audioEncoder->encodingOption("PCM","quality").toInt(), int(QtMultimediaKit::NormalQuality));
+ audioEncoder->setEncodingOption("PCM", "samplerate", QVariant(44100));
+ QCOMPARE(audioEncoder->encodingOption("PCM","samplerate").toInt(), 44100);
+}
+
+void tst_QMediaRecorder_mmf::testMediaFormatsControl()
+{
+ //audioocontainer types
+ // Containers supported are dynamically queried from MMF. We cannot guarentee that 2 platforms
+ // will support the same set.
+ //QCOMPARE(audiocapture->supportedContainers(), QStringList() << "audio/wav" << "audio/amr");
+ QCOMPARE(audiocapture->containerDescription("audio/wav"), QString("WAV Write Format"));
+ QCOMPARE(audiocapture->containerDescription("audio/amr"), QString("AMR Write Format"));
+}
+
+void tst_QMediaRecorder_mmf::testDefaultAudioEncodingSettings()
+{
+ QAudioEncoderSettings audioSettings = audiocapture->audioSettings();
+ QCOMPARE(audioSettings.codec(), QString("AMR"));
+ QString format = audiocapture->containerMimeType();
+ QCOMPARE(format, QString("audio/amr"));
+}
diff --git a/tests/auto/qmediarecorder/tst_qmediarecorder_mmf.h b/tests/auto/qmediarecorder/tst_qmediarecorder_mmf.h
new file mode 100755
index 000000000..83058a214
--- /dev/null
+++ b/tests/auto/qmediarecorder/tst_qmediarecorder_mmf.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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 TST_QMEDIARECORDER_MMF
+#define TST_QMEDIARECORDER_MMF
+
+#include <QtTest/QtTest>
+#include <QDebug>
+#include <qmediaobject.h>
+#include <qmediacontrol.h>
+#include <qmediaservice.h>
+#include <qmediarecordercontrol.h>
+#include <qmediarecorder.h>
+#include <qaudioendpointselector.h>
+#include <qaudioencodercontrol.h>
+#include <qmediacontainercontrol.h>
+#include <qaudioformat.h>
+#include <qaudiocapturesource.h>
+
+#include "s60common.h"
+
+QT_USE_NAMESPACE
+class tst_QMediaRecorder_mmf: public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void testAudioSink();
+ void testAudioRecord();
+ void testAudioRecordWithAMR();
+ void testAudioEndPointSelector();
+ void testAudioEncoderControl();
+ void testMediaFormatsControl();
+ void testDefaultAudioEncodingSettings();
+
+private:
+ QUrl recordPathAudio(QDir outputDir);
+
+ QAudioEncoderControl *audioEncoder;
+ QAudioEndpointSelector *audioEndpoint;
+ QMediaRecorder *audiocapture;
+ QAudioCaptureSource *captureSource;
+};
+#endif
diff --git a/tests/auto/qmediarecorder/tst_qmediarecorder_xa.cpp b/tests/auto/qmediarecorder/tst_qmediarecorder_xa.cpp
new file mode 100755
index 000000000..b8777b4fc
--- /dev/null
+++ b/tests/auto/qmediarecorder/tst_qmediarecorder_xa.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 "tst_qmediarecorder_xa.h"
+
+QT_USE_NAMESPACE
+
+void tst_QMediaRecorder_xa::initTestCase()
+{
+ audiosource = new QAudioCaptureSource;
+ audiocapture = new QMediaRecorder(audiosource);
+}
+
+void tst_QMediaRecorder_xa::cleanupTestCase()
+{
+ delete audiocapture;
+ delete audiosource;
+}
+
+void tst_QMediaRecorder_xa::testMediaRecorderObject()
+{
+ //audioocontainer types
+ QCOMPARE(audiocapture->audioCodecDescription("pcm"), QString("pcm"));
+ QCOMPARE(audiocapture->audioCodecDescription("amr"), QString("amr"));
+ QCOMPARE(audiocapture->audioCodecDescription("aac"), QString("aac"));
+ QCOMPARE(audiocapture->containerDescription("audio/wav"), QString("wav container"));
+ QCOMPARE(audiocapture->containerDescription("audio/amr"), QString("amr File format"));
+ QCOMPARE(audiocapture->containerDescription("audio/mpeg"), QString("mpeg container"));
+ QCOMPARE(audiocapture->containerMimeType(), QString("audio/wav"));
+ QCOMPARE(audiocapture->error(), QMediaRecorder::NoError);
+ QCOMPARE(audiocapture->errorString(), QString());
+ QCOMPARE(audiocapture->outputLocation().toLocalFile(), QString());
+ QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
+ QCOMPARE(audiocapture->supportedAudioCodecs().count(), 3); // "pcm", "amr", "aac"
+ QAudioEncoderSettings settings;
+ settings.setCodec("pcm");
+ QCOMPARE(audiocapture->supportedAudioSampleRates(settings).count(), 5);
+ bool isContinuous;
+ audiocapture->supportedAudioSampleRates(settings, &isContinuous);
+ QCOMPARE(isContinuous, false);
+ QCOMPARE(audiocapture->supportedContainers().count(), 3); // "audio/wav", "audio/amr", "audio/mpeg"
+}
+
+void tst_QMediaRecorder_xa::testDefaultAudioEncodingSettings()
+{
+ QAudioEncoderSettings audioSettings = audiocapture->audioSettings();
+ QCOMPARE(audioSettings.codec(), QString("pcm"));
+ QCOMPARE(audiocapture->containerMimeType(), QString("audio/wav"));
+ QCOMPARE(audioSettings.bitRate(), 0);
+ QCOMPARE(audioSettings.channelCount(), -1);
+ QCOMPARE(audioSettings.encodingMode(), QtMultimediaKit::ConstantQualityEncoding);
+ QCOMPARE(audioSettings.quality(), QtMultimediaKit::NormalQuality);
+ QCOMPARE(audioSettings.sampleRate(), -1);
+}
+
+void tst_QMediaRecorder_xa::testAudioRecordingLocationOnly()
+{
+ QSignalSpy stateSignal(audiocapture,SIGNAL(stateChanged(QMediaRecorder::State)));
+ QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
+ QTest::qWait(500); // wait for recorder to initialize itself
+ audiocapture->setOutputLocation(nextFileName(QDir::rootPath(), "locationonly", "wav"));
+ audiocapture->record();
+ QTRY_COMPARE(stateSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QCOMPARE(audiocapture->state(), QMediaRecorder::RecordingState);
+ QCOMPARE(audiocapture->error(), QMediaRecorder::NoError);
+ QCOMPARE(audiocapture->errorString(), QString());
+ QCOMPARE(stateSignal.count(), 1);
+ QTest::qWait(5000); // wait for 5 seconds
+ audiocapture->pause();
+ QTRY_COMPARE(stateSignal.count(), 2); // wait for callbacks to complete in symbian API
+ QCOMPARE(audiocapture->state(), QMediaRecorder::PausedState);
+ QCOMPARE(stateSignal.count(), 2);
+ audiocapture->stop();
+ QTRY_COMPARE(stateSignal.count(), 3); // wait for callbacks to complete in symbian API
+ QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
+ QCOMPARE(stateSignal.count(), 3);
+}
+
+void tst_QMediaRecorder_xa::testAudioRecording_data()
+{
+ QTest::addColumn<QString>("mime"); // "audio/wav", "audio/amr", "audio/mpeg"
+ QTest::addColumn<QString>("codec"); // "pcm", "amr", "aac"
+ QTest::addColumn<QString>("filename_desc");
+ QTest::addColumn<QString>("filename_ext"); // "wav", "amr", "mp4"
+ QTest::addColumn<QString>("settings");
+ QTest::addColumn<int>("bitrate");
+ QTest::addColumn<int>("samplerate");
+ QTest::addColumn<int>("channels");
+
+ QTest::newRow("wav default") << "audio/wav" << "pcm" << "default" << "wav" << "default" << 0 << 0 << 0;
+ QTest::newRow("amr default") << "audio/amr" << "amr" << "default" << "amr" << "default" << 4750 << 8000 << -1;
+ QTest::newRow("aac default") << "audio/mpeg" << "aac" << "default" << "mp4" << "default" << 0 << 48000 << -1;
+ QTest::newRow("wav 08kHz Mono") << "audio/wav" << "pcm" << "Sr08kHzMono" << "wav" << "user" << 0 << 8000 << 1;
+ QTest::newRow("wav 08kHz Stereo") << "audio/wav" << "pcm" << "Sr08kHzStereo" << "wav" << "user" << 0 << 8000 << 2;
+ QTest::newRow("wav 16kHz Mono") << "audio/wav" << "pcm" << "Sr16kHzMono" << "wav" << "user" << 0 << 16000 << 1;
+ QTest::newRow("wav 16kHz Stereo") << "audio/wav" << "pcm" << "Sr16kHzStereo" << "wav" << "user" << 0 << 16000 << 2;
+ QTest::newRow("wav 32kHz Mono") << "audio/wav" << "pcm" << "Sr32kHzMono" << "wav" << "user" << 0 << 32000 << 1;
+ QTest::newRow("wav 32kHz Stereo") << "audio/wav" << "pcm" << "Sr32kHzStereo" << "wav" << "user" << 0<< 32000 << 2;
+ QTest::newRow("wav 48kHz Mono") << "audio/wav" << "pcm" << "Sr48kHzMono" << "wav" << "user" << 0 << 48000 << 1;
+ QTest::newRow("wav 48kHz Stereo") << "audio/wav" << "pcm" << "Sr48kHzStereo" << "wav" << "user" << 0 << 48000 << 2;
+ QTest::newRow("amr Br04750bps") << "audio/amr" << "amr" << "Br04750bps" << "amr" << "user" << 4750 << 8000 << 1;
+ QTest::newRow("amr Br05150bps") << "audio/amr" << "amr" << "Br05150bps" << "amr" << "user" << 5150 << 8000 << 1;
+ QTest::newRow("amr Br05900bps") << "audio/amr" << "amr" << "Br05900bps" << "amr" << "user" << 5900 << 8000 << 1;
+ QTest::newRow("amr Br06700bps") << "audio/amr" << "amr" << "Br06700bps" << "amr" << "user" << 6700 << 8000 << 1;
+ QTest::newRow("amr Br07400bps") << "audio/amr" << "amr" << "Br07400bps" << "amr" << "user" << 7400 << 8000 << 1;
+ QTest::newRow("amr Br07950bps") << "audio/amr" << "amr" << "Br07950bps" << "amr" << "user" << 7950 << 8000 << 1;
+ QTest::newRow("amr Br10200bps") << "audio/amr" << "amr" << "Br10200bps" << "amr" << "user" << 10200 << 8000 << 1;
+ QTest::newRow("amr Br12200bps") << "audio/amr" << "amr" << "Br12200bps" << "amr" << "user" << 10200 << 8000 << 1;
+ QTest::newRow("amr verylowqual") << "audio/amr" << "amr" << "verylowqual" << "amr" << "preset" << -1 << 8000 << -1;
+ QTest::newRow("amr lowqual") << "audio/amr" << "amr" << "lowqual" << "amr" << "preset" << -2 << 8000 << -1;
+ QTest::newRow("amr normalqual") << "audio/amr" << "amr" << "normalqual" << "amr" << "preset" << -3 << 8000 << -1;
+ QTest::newRow("amr highqual") << "audio/amr" << "amr" << "highqual" << "amr" << "preset" << -4 << 8000 << -1;
+ QTest::newRow("amr veryhighqual") << "audio/amr" << "amr" << "veryhighqual" << "amr" << "preset" << -5 << 8000 << -1;
+
+ // Combinations supported for sample rate 8kHz
+ QTest::newRow("aac Br32k Sr8kHz Mono") << "audio/mpeg" << "aac" << "Br32kSr8kHzMono" << "mp4" << "user" << 32000 << 8000 << 1;
+ QTest::newRow("aac Br32k Sr8kHz Stereo") << "audio/mpeg" << "aac" << "Br32kSr8kHzStereo" << "mp4" << "user" << 32000 << 8000 << 2;
+ QTest::newRow("aac Br64k Sr8kHz Stereo") << "audio/mpeg" << "aac" << "Br64kSr8kHzStereo" << "mp4" << "user" << 64000 << 8000 << 2;
+ // Combinations supported for sample rate 16kHz
+ QTest::newRow("aac Br32k Sr16kHz Mono") << "audio/mpeg" << "aac" << "Br32kSr16kHzMono" << "mp4" << "user" << 32000 << 16000 << 1;
+ QTest::newRow("aac Br64k Sr16kHz Mono") << "audio/mpeg" << "aac" << "Br64kSr16kHzMonoo" << "mp4" << "user" << 64000 << 16000 << 1;
+ QTest::newRow("aac Br32k Sr16kHz Stereo") << "audio/mpeg" << "aac" << "Br32kSr16kHzStereo" << "mp4" << "user" << 32000 << 16000 << 2;
+ QTest::newRow("aac Br64k Sr16kHz Stereo") << "audio/mpeg" << "aac" << "Br64kSr16kHzStereo" << "mp4" << "user" << 64000 << 16000 << 2;
+ QTest::newRow("aac Br96k Sr16kHz Stereo") << "audio/mpeg" << "aac" << "Br96kSr16kHzStereo" << "mp4" << "user" << 96000 << 16000 << 2;
+ QTest::newRow("aac Br128k Sr16kHz Stereo") << "audio/mpeg" << "aac" << "Br128kSr16kHzStereo" << "mp4" << "user" << 128000 << 16000 << 2;
+ QTest::newRow("aac Br160k Sr16kHz Stereo") << "audio/mpeg" << "aac" << "Br160kSr16kHzStereo" << "mp4" << "user" << 160000 << 16000 << 2;
+ // Combinations supported for sample rate 24kHz
+ QTest::newRow("aac Br32k Sr24kHz Mono") << "audio/mpeg" << "aac" << "Br32kSr24kHzMono" << "mp4" << "user" << 32000 << 24000 << 1;
+ QTest::newRow("aac Br64k Sr24kHz Mono") << "audio/mpeg" << "aac" << "Br64kSr24kHzMono" << "mp4" << "user" << 64000 << 24000 << 1;
+ QTest::newRow("aac Br96k Sr24kHz Mono") << "audio/mpeg" << "aac" << "Br96kSr24kHzMono" << "mp4" << "user" << 96000 << 24000 << 1;
+ QTest::newRow("aac Br32k Sr24kHz Stereo") << "audio/mpeg" << "aac" << "Br32kSr24kHzStereo" << "mp4" << "user" << 32000 << 24000 << 2;
+ QTest::newRow("aac Br64k Sr24kHz Stereo") << "audio/mpeg" << "aac" << "Br64kSr24kHzStereo" << "mp4" << "user" << 64000 << 24000 << 2;
+ QTest::newRow("aac Br96k Sr24kHz Stereo") << "audio/mpeg" << "aac" << "Br96kSr24kHzStereo" << "mp4" << "user" << 96000 << 24000 << 2;
+ QTest::newRow("aac Br128k Sr24kHz Stereo") << "audio/mpeg" << "aac" << "Br128kSr24kHzStereo" << "mp4" << "user" << 128000 << 24000 << 2;
+ QTest::newRow("aac Br160k Sr24kHz Stereo") << "audio/mpeg" << "aac" << "Br160kSr24kHzStereo" << "mp4" << "user" << 160000 << 24000 << 2;
+ QTest::newRow("aac Br192k Sr24kHz Stereo") << "audio/mpeg" << "aac" << "Br192kSr24kHzStereo" << "mp4" << "user" << 192000 << 24000 << 2;
+ // Combinations supported for sample rate 32kHz
+ QTest::newRow("aac Br32k Sr32kHz Mono") << "audio/mpeg" << "aac" << "Br32kSr32kHzMono" << "mp4" << "user" << 32000 << 32000 << 1;
+ QTest::newRow("aac Br64k Sr32kHz Mono") << "audio/mpeg" << "aac" << "Br64kSr32kHzMono" << "mp4" << "user" << 64000 << 32000 << 1;
+ QTest::newRow("aac Br96k Sr32kHz Mono") << "audio/mpeg" << "aac" << "Br96kSr32kHzMono" << "mp4" << "user" << 96000 << 32000 << 1;
+ QTest::newRow("aac Br128k Sr32kHz Mono") << "audio/mpeg" << "aac" << "Br128kSr32kHzMono" << "mp4" << "user" << 128000 << 32000 << 1;
+ QTest::newRow("aac Br160k Sr32kHz Mono") << "audio/mpeg" << "aac" << "Br160kSr32kHzMono" << "mp4" << "user" << 160000 << 32000 << 1;
+ QTest::newRow("aac Br32k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br32kSr32kHzStereo" << "mp4" << "user" << 32000 << 32000 << 2;
+ QTest::newRow("aac Br64k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br64kSr32kHzStereo" << "mp4" << "user" << 64000 << 32000 << 2;
+ QTest::newRow("aac Br96k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br96kSr32kHzStereo" << "mp4" << "user" << 96000 << 32000 << 2;
+ QTest::newRow("aac Br128k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br128kSr32kHzStereo" << "mp4" << "user" << 128000 << 32000 << 2;
+ QTest::newRow("aac Br160k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br160kSr32kHzStereo" << "mp4" << "user" << 160000 << 32000 << 2;
+ QTest::newRow("aac Br192k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br192kSr32kHzStereo" << "mp4" << "user" << 192000 << 32000 << 2;
+ QTest::newRow("aac Br224k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br224kSr32kHzStereo" << "mp4" << "user" << 224000 << 32000 << 2;
+ QTest::newRow("aac Br256k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br256kSr32kHzStereo" << "mp4" << "user" << 256000 << 32000 << 2;
+ // Combinations supported for sample rate 48kHz
+ QTest::newRow("aac Br32k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br32kSr48kHzMono" << "mp4" << "user" << 32000 << 48000 << 1;
+ QTest::newRow("aac Br64k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br64kSr48kHzMono" << "mp4" << "user" << 64000 << 48000 << 1;
+ QTest::newRow("aac Br96k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br96kSr48kHzMono" << "mp4" << "user" << 96000 << 48000 << 1;
+ QTest::newRow("aac Br128k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br128kSr48kHzMono" << "mp4" << "user" << 128000 << 48000 << 1;
+ QTest::newRow("aac Br160k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br160kSr48kHzMono" << "mp4" << "user" << 160000 << 48000 << 1;
+ QTest::newRow("aac Br192k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br192kSr48kHzMono" << "mp4" << "user" << 192000 << 48000 << 1;
+ QTest::newRow("aac Br224k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br224kSr48kHzMono" << "mp4" << "user" << 224000 << 48000 << 1;
+ QTest::newRow("aac Br32k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br32kSr48kHzStereo" << "mp4" << "user" << 32000 << 48000 << 2;
+ QTest::newRow("aac Br64k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br64kSr48kHzStereo" << "mp4" << "user" << 64000 << 48000 << 2;
+ QTest::newRow("aac Br96k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br96kSr48kHzStereo" << "mp4" << "user" << 96000 << 48000 << 2;
+ QTest::newRow("aac Br128k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br128kSr48kHzStereo" << "mp4" << "user" << 128000 << 48000 << 2;
+ QTest::newRow("aac Br160k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br160kSr48kHzStereo" << "mp4" << "user" << 160000 << 48000 << 2;
+ QTest::newRow("aac Br192k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br192kSr48kHzStereo" << "mp4" << "user" << 192000 << 48000 << 2;
+ QTest::newRow("aac Br224k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br224kSr48kHzStereo" << "mp4" << "user" << 224000 << 48000 << 2;
+ QTest::newRow("aac Br256k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br256kSr48kHzStereo" << "mp4" << "user" << 256000 << 48000 << 2;
+ QTest::newRow("aac verylowqual") << "audio/mpeg" << "aac" << "verylowqual" << "mp4" << "preset" << -1 << 8000 << -1;
+ QTest::newRow("aac lowqual") << "audio/mpeg" << "aac" << "lowqual" << "mp4" << "preset" << -2 << 24000 << -1;
+ QTest::newRow("aac normalqual") << "audio/mpeg" << "aac" << "normalqual" << "mp4" << "preset" << -3 << 32000 << -1;
+ QTest::newRow("aac highqual") << "audio/mpeg" << "aac" << "highqual" << "mp4" << "preset" << -4 << 48000 << -1;
+ QTest::newRow("aac veryhighqual") << "audio/mpeg" << "aac" << "veryhighqual" << "mp4" << "preset" << -5 << 48000 << -1;
+ }
+
+void tst_QMediaRecorder_xa::testAudioRecording()
+{
+ QFETCH(QString, mime);
+ QFETCH(QString, codec);
+ QFETCH(QString, filename_desc);
+ QFETCH(QString, filename_ext);
+ QFETCH(QString, settings);
+
+ QSignalSpy stateSignal(audiocapture,SIGNAL(stateChanged(QMediaRecorder::State)));
+ audiocapture->setOutputLocation(nextFileName(QDir::rootPath(), filename_desc, filename_ext));
+ QAudioEncoderSettings audioSettings;
+ audioSettings.setCodec(codec);
+ if (settings.compare("default") == 0) {
+ audioSettings.setSampleRate(-1);
+ }
+ else if (settings.compare("user") == 0) {
+ QFETCH(int, bitrate);
+ QFETCH(int, samplerate);
+ QFETCH(int, channels);
+ audioSettings.setEncodingMode(QtMultimediaKit::ConstantBitRateEncoding);
+ if (bitrate > 0)
+ audioSettings.setBitRate(bitrate);
+ if (samplerate > 0)
+ audioSettings.setSampleRate(samplerate);
+ if ((channels > 0) || (channels == -1))
+ audioSettings.setChannelCount(channels);
+ }
+ else if (settings.compare("preset") == 0) {
+ QFETCH(int, bitrate);
+ QFETCH(int, samplerate);
+ QFETCH(int, channels);
+ audioSettings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding);
+ QtMultimediaKit::EncodingQuality quality = QtMultimediaKit::NormalQuality;
+ switch(bitrate) {
+ case -1:
+ quality = QtMultimediaKit::VeryLowQuality;
+ break;
+ case -2:
+ quality = QtMultimediaKit::LowQuality;
+ break;
+ default:
+ case -3:
+ quality = QtMultimediaKit::NormalQuality;
+ break;
+ case -4:
+ quality = QtMultimediaKit::HighQuality;
+ break;
+ case -5:
+ quality = QtMultimediaKit::VeryHighQuality;
+ break;
+ }
+ audioSettings.setQuality(quality);
+ if (samplerate > 0)
+ audioSettings.setSampleRate(samplerate);
+ if ((channels > 0) || (channels == -1))
+ audioSettings.setChannelCount(channels);
+ }
+ QVideoEncoderSettings videoSettings;
+ audiocapture->setEncodingSettings(audioSettings, videoSettings, mime);
+ QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
+ QTest::qWait(500); // wait for recorder to initialize itself
+ int expectedSignalCount = 1;
+ audiocapture->record();
+ QTRY_COMPARE(stateSignal.count(), expectedSignalCount); // wait for callbacks to complete in symbian API
+ QCOMPARE(audiocapture->state(), QMediaRecorder::RecordingState);
+ QCOMPARE(audiocapture->error(), QMediaRecorder::NoError);
+ QCOMPARE(audiocapture->errorString(), QString());
+ QCOMPARE(stateSignal.count(), expectedSignalCount);
+ QTest::qWait(5000); // wait for 5 seconds
+ // If we are not testing aac recording to mp4 container
+ if (!((mime.compare("audio/mpeg") == 0) && (codec.compare("aac") == 0))) {
+ expectedSignalCount++;
+ audiocapture->pause();
+ QTRY_COMPARE(stateSignal.count(), expectedSignalCount); // wait for callbacks to complete in symbian API
+ QCOMPARE(audiocapture->state(), QMediaRecorder::PausedState);
+ QCOMPARE(stateSignal.count(), expectedSignalCount);
+ }
+ expectedSignalCount++;
+ audiocapture->stop();
+ QTRY_COMPARE(stateSignal.count(), expectedSignalCount); // wait for callbacks to complete in symbian API
+ QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState);
+ QCOMPARE(stateSignal.count(), expectedSignalCount);
+ /* testAudioRecording() function gets executed for each rown in the table.
+ * If and when all tests in the table passes, test log will just contain one
+ * entry 'PASS : tst_QMediaRecorder_xa::testAudioRecording()'. To figure out
+ * which test in the loop completed successfully, just print a debug message
+ * which also goes into the test log generated.*/
+ qDebug() << "----> PASS";
+}
+
+void tst_QMediaRecorder_xa::testOutputLocation()
+{
+ audiocapture->setOutputLocation(QUrl("test.wav"));
+ QUrl s = audiocapture->outputLocation();
+ QCOMPARE(s.toString(), QString("test.wav"));
+}
+
+QUrl tst_QMediaRecorder_xa::nextFileName(QDir outputDir, QString appendName, QString ext)
+{
+ int lastImage = 0;
+ int fileCount = 0;
+ foreach( QString fileName, outputDir.entryList(QStringList() << "testclip_*." + ext) ) {
+ int imgNumber = fileName.mid(5, fileName.size()-9).toInt();
+ lastImage = qMax(lastImage, imgNumber);
+ if (outputDir.exists(fileName))
+ fileCount+=1;
+ }
+ lastImage+=fileCount;
+
+ QUrl location(QDir::toNativeSeparators(outputDir.canonicalPath() + QString("/testclip_%1").arg(lastImage+1 , 4, 10, QLatin1Char('0')) + appendName + "." + ext));
+ return location;
+}
diff --git a/tests/auto/qmediarecorder/tst_qmediarecorder_xa.h b/tests/auto/qmediarecorder/tst_qmediarecorder_xa.h
new file mode 100755
index 000000000..c7fe415e4
--- /dev/null
+++ b/tests/auto/qmediarecorder/tst_qmediarecorder_xa.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this 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 TST_QMEDIARECORDER_XA_H
+#define TST_QMEDIARECORDER_XA_H
+
+#include <QtTest/QtTest>
+#include <qmediarecorder.h>
+#include <qaudiocapturesource.h>
+
+#include "s60common.h"
+
+QT_USE_NAMESPACE
+
+class tst_QMediaRecorder_xa: public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void testMediaRecorderObject(); //1
+ void testDefaultAudioEncodingSettings(); //2
+ void testOutputLocation(); //3
+ void testAudioRecordingLocationOnly(); //4
+ void testAudioRecording_data(); //5
+ void testAudioRecording(); //6
+
+private:
+ QUrl nextFileName(QDir outputDir, QString appendName, QString ext);
+
+private:
+ QAudioCaptureSource* audiosource;
+ QMediaRecorder* audiocapture;
+
+};
+
+#endif /* TST_QMEDIARECORDER_XA_H */
diff --git a/tests/auto/qmediaresource/qmediaresource.pro b/tests/auto/qmediaresource/qmediaresource.pro
new file mode 100644
index 000000000..dcd2a2f45
--- /dev/null
+++ b/tests/auto/qmediaresource/qmediaresource.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += network multimediakit-private
+
+# TARGET = tst_qmediaresource
+# CONFIG += testcase
+
+SOURCES += tst_qmediaresource.cpp
+
diff --git a/tests/auto/qmediaresource/tst_qmediaresource.cpp b/tests/auto/qmediaresource/tst_qmediaresource.cpp
new file mode 100644
index 000000000..602b1fba4
--- /dev/null
+++ b/tests/auto/qmediaresource/tst_qmediaresource.cpp
@@ -0,0 +1,528 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <QtTest/QtTest>
+
+#include "qmediaresource.h"
+
+QT_USE_NAMESPACE
+class tst_QMediaResource : public QObject
+{
+ Q_OBJECT
+private slots:
+ void constructNull();
+ void construct_data();
+ void construct();
+ void setResolution();
+ void equality();
+ void copy();
+ void assign();
+};
+
+void tst_QMediaResource::constructNull()
+{
+ QMediaResource resource;
+
+ QCOMPARE(resource.isNull(), true);
+ QCOMPARE(resource.url(), QUrl());
+ QCOMPARE(resource.request(), QNetworkRequest());
+ QCOMPARE(resource.mimeType(), QString());
+ QCOMPARE(resource.language(), QString());
+ QCOMPARE(resource.audioCodec(), QString());
+ QCOMPARE(resource.videoCodec(), QString());
+ QCOMPARE(resource.dataSize(), qint64(0));
+ QCOMPARE(resource.audioBitRate(), 0);
+ QCOMPARE(resource.sampleRate(), 0);
+ QCOMPARE(resource.channelCount(), 0);
+ QCOMPARE(resource.videoBitRate(), 0);
+ QCOMPARE(resource.resolution(), QSize());
+}
+
+void tst_QMediaResource::construct_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<QNetworkRequest>("request");
+ QTest::addColumn<QString>("mimeType");
+ QTest::addColumn<QString>("language");
+ QTest::addColumn<QString>("audioCodec");
+ QTest::addColumn<QString>("videoCodec");
+ QTest::addColumn<qint64>("dataSize");
+ QTest::addColumn<int>("audioBitRate");
+ QTest::addColumn<int>("sampleRate");
+ QTest::addColumn<int>("channelCount");
+ QTest::addColumn<int>("videoBitRate");
+ QTest::addColumn<QSize>("resolution");
+
+ QTest::newRow("audio content")
+ << QUrl(QString::fromLatin1("http:://test.com/test.mp3"))
+ << QNetworkRequest(QUrl(QString::fromLatin1("http:://test.com/test.mp3")))
+ << QString::fromLatin1("audio/mpeg")
+ << QString::fromLatin1("eng")
+ << QString::fromLatin1("mp3")
+ << QString()
+ << qint64(5465433)
+ << 128000
+ << 44100
+ << 2
+ << 0
+ << QSize();
+ QTest::newRow("image content")
+ << QUrl(QString::fromLatin1("http:://test.com/test.jpg"))
+ << QNetworkRequest(QUrl(QString::fromLatin1("http:://test.com/test.jpg")))
+ << QString::fromLatin1("image/jpeg")
+ << QString()
+ << QString()
+ << QString()
+ << qint64(23600)
+ << 0
+ << 0
+ << 0
+ << 0
+ << QSize(640, 480);
+ QTest::newRow("video content")
+ << QUrl(QString::fromLatin1("http:://test.com/test.mp4"))
+ << QNetworkRequest(QUrl(QString::fromLatin1("http:://test.com/test.mp4")))
+ << QString::fromLatin1("video/mp4")
+ << QString()
+ << QString::fromLatin1("aac")
+ << QString::fromLatin1("h264")
+ << qint64(36245851)
+ << 96000
+ << 44000
+ << 5
+ << 750000
+ << QSize(720, 576);
+ QTest::newRow("thumbnail")
+ << QUrl(QString::fromLatin1("file::///thumbs/test.png"))
+ << QNetworkRequest(QUrl(QString::fromLatin1("file::///thumbs/test.png")))
+ << QString::fromLatin1("image/png")
+ << QString()
+ << QString()
+ << QString()
+ << qint64(2360)
+ << 0
+ << 0
+ << 0
+ << 0
+ << QSize(128, 128);
+}
+
+void tst_QMediaResource::construct()
+{
+ QFETCH(QUrl, url);
+ QFETCH(QNetworkRequest, request);
+ QFETCH(QString, mimeType);
+ QFETCH(QString, language);
+ QFETCH(QString, audioCodec);
+ QFETCH(QString, videoCodec);
+ QFETCH(qint64, dataSize);
+ QFETCH(int, audioBitRate);
+ QFETCH(int, sampleRate);
+ QFETCH(int, channelCount);
+ QFETCH(int, videoBitRate);
+ QFETCH(QSize, resolution);
+
+ {
+ QMediaResource resource(url);
+
+ QCOMPARE(resource.isNull(), false);
+ QCOMPARE(resource.url(), url);
+ QCOMPARE(resource.mimeType(), QString());
+ QCOMPARE(resource.language(), QString());
+ QCOMPARE(resource.audioCodec(), QString());
+ QCOMPARE(resource.videoCodec(), QString());
+ QCOMPARE(resource.dataSize(), qint64(0));
+ QCOMPARE(resource.audioBitRate(), 0);
+ QCOMPARE(resource.sampleRate(), 0);
+ QCOMPARE(resource.channelCount(), 0);
+ QCOMPARE(resource.videoBitRate(), 0);
+ QCOMPARE(resource.resolution(), QSize());
+ }
+ {
+ QMediaResource resource(url, mimeType);
+
+ QCOMPARE(resource.isNull(), false);
+ QCOMPARE(resource.url(), url);
+ QCOMPARE(resource.request(), request);
+ QCOMPARE(resource.mimeType(), mimeType);
+ QCOMPARE(resource.language(), QString());
+ QCOMPARE(resource.audioCodec(), QString());
+ QCOMPARE(resource.videoCodec(), QString());
+ QCOMPARE(resource.dataSize(), qint64(0));
+ QCOMPARE(resource.audioBitRate(), 0);
+ QCOMPARE(resource.sampleRate(), 0);
+ QCOMPARE(resource.channelCount(), 0);
+ QCOMPARE(resource.videoBitRate(), 0);
+ QCOMPARE(resource.resolution(), QSize());
+
+ resource.setLanguage(language);
+ resource.setAudioCodec(audioCodec);
+ resource.setVideoCodec(videoCodec);
+ resource.setDataSize(dataSize);
+ resource.setAudioBitRate(audioBitRate);
+ resource.setSampleRate(sampleRate);
+ resource.setChannelCount(channelCount);
+ resource.setVideoBitRate(videoBitRate);
+ resource.setResolution(resolution);
+
+ QCOMPARE(resource.language(), language);
+ QCOMPARE(resource.audioCodec(), audioCodec);
+ QCOMPARE(resource.videoCodec(), videoCodec);
+ QCOMPARE(resource.dataSize(), dataSize);
+ QCOMPARE(resource.audioBitRate(), audioBitRate);
+ QCOMPARE(resource.sampleRate(), sampleRate);
+ QCOMPARE(resource.channelCount(), channelCount);
+ QCOMPARE(resource.videoBitRate(), videoBitRate);
+ QCOMPARE(resource.resolution(), resolution);
+ }
+ {
+ QMediaResource resource(request, mimeType);
+
+ QCOMPARE(resource.isNull(), false);
+ QCOMPARE(resource.url(), url);
+ QCOMPARE(resource.request(), request);
+ QCOMPARE(resource.mimeType(), mimeType);
+ QCOMPARE(resource.language(), QString());
+ QCOMPARE(resource.audioCodec(), QString());
+ QCOMPARE(resource.videoCodec(), QString());
+ QCOMPARE(resource.dataSize(), qint64(0));
+ QCOMPARE(resource.audioBitRate(), 0);
+ QCOMPARE(resource.sampleRate(), 0);
+ QCOMPARE(resource.channelCount(), 0);
+ QCOMPARE(resource.videoBitRate(), 0);
+ QCOMPARE(resource.resolution(), QSize());
+
+ resource.setLanguage(language);
+ resource.setAudioCodec(audioCodec);
+ resource.setVideoCodec(videoCodec);
+ resource.setDataSize(dataSize);
+ resource.setAudioBitRate(audioBitRate);
+ resource.setSampleRate(sampleRate);
+ resource.setChannelCount(channelCount);
+ resource.setVideoBitRate(videoBitRate);
+ resource.setResolution(resolution);
+
+ QCOMPARE(resource.language(), language);
+ QCOMPARE(resource.audioCodec(), audioCodec);
+ QCOMPARE(resource.videoCodec(), videoCodec);
+ QCOMPARE(resource.dataSize(), dataSize);
+ QCOMPARE(resource.audioBitRate(), audioBitRate);
+ QCOMPARE(resource.sampleRate(), sampleRate);
+ QCOMPARE(resource.channelCount(), channelCount);
+ QCOMPARE(resource.videoBitRate(), videoBitRate);
+ QCOMPARE(resource.resolution(), resolution);
+ }
+}
+
+void tst_QMediaResource::setResolution()
+{
+ QMediaResource resource(
+ QUrl(QString::fromLatin1("file::///thumbs/test.png")),
+ QString::fromLatin1("image/png"));
+
+ QCOMPARE(resource.resolution(), QSize());
+
+ resource.setResolution(QSize(120, 80));
+ QCOMPARE(resource.resolution(), QSize(120, 80));
+
+ resource.setResolution(QSize(-1, 23));
+ QCOMPARE(resource.resolution(), QSize(-1, 23));
+
+ resource.setResolution(QSize(-43, 34));
+ QCOMPARE(resource.resolution(), QSize(-43, 34));
+
+ resource.setResolution(QSize(64, -1));
+ QCOMPARE(resource.resolution(), QSize(64, -1));
+
+ resource.setResolution(QSize(64, -83));
+ QCOMPARE(resource.resolution(), QSize(64, -83));
+
+ resource.setResolution(QSize(-12, -83));
+ QCOMPARE(resource.resolution(), QSize(-12, -83));
+
+ resource.setResolution(QSize());
+ QCOMPARE(resource.resolution(), QSize(-1, -1));
+
+ resource.setResolution(120, 80);
+ QCOMPARE(resource.resolution(), QSize(120, 80));
+
+ resource.setResolution(-1, 23);
+ QCOMPARE(resource.resolution(), QSize(-1, 23));
+
+ resource.setResolution(-43, 34);
+ QCOMPARE(resource.resolution(), QSize(-43, 34));
+
+ resource.setResolution(64, -1);
+ QCOMPARE(resource.resolution(), QSize(64, -1));
+
+ resource.setResolution(64, -83);
+ QCOMPARE(resource.resolution(), QSize(64, -83));
+
+ resource.setResolution(-12, -83);
+ QCOMPARE(resource.resolution(), QSize(-12, -83));
+
+ resource.setResolution(-1, -1);
+ QCOMPARE(resource.resolution(), QSize());
+}
+
+void tst_QMediaResource::equality()
+{
+ QMediaResource resource1(
+ QUrl(QString::fromLatin1("http://test.com/test.mp4")),
+ QString::fromLatin1("video/mp4"));
+ QMediaResource resource2(
+ QUrl(QString::fromLatin1("http://test.com/test.mp4")),
+ QString::fromLatin1("video/mp4"));
+ QMediaResource resource3(
+ QUrl(QString::fromLatin1("file:///thumbs/test.jpg")));
+ QMediaResource resource4(
+ QUrl(QString::fromLatin1("file:///thumbs/test.jpg")));
+ QMediaResource resource5(
+ QUrl(QString::fromLatin1("http://test.com/test.mp3")),
+ QString::fromLatin1("audio/mpeg"));
+
+ QNetworkRequest request(QUrl("http://test.com/test.mp3"));
+ QString requestMimeType("audio/mp3");
+
+ QMediaResource requestResource1(request, requestMimeType);
+ QMediaResource requestResource2(request, requestMimeType);
+
+ QCOMPARE(requestResource1 == requestResource2, true);
+ QCOMPARE(requestResource1 != requestResource2, false);
+ QCOMPARE(requestResource1 != resource5, true);
+
+ QCOMPARE(resource1 == resource2, true);
+ QCOMPARE(resource1 != resource2, false);
+
+ QCOMPARE(resource3 == resource4, true);
+ QCOMPARE(resource3 != resource4, false);
+
+ QCOMPARE(resource1 == resource3, false);
+ QCOMPARE(resource1 != resource3, true);
+
+ QCOMPARE(resource1 == resource5, false);
+ QCOMPARE(resource1 != resource5, true);
+
+ resource1.setAudioCodec(QString::fromLatin1("mp3"));
+ resource2.setAudioCodec(QString::fromLatin1("aac"));
+
+ // Not equal differing audio codecs.
+ QCOMPARE(resource1 == resource2, false);
+ QCOMPARE(resource1 != resource2, true);
+
+ resource1.setAudioCodec(QString::fromLatin1("aac"));
+
+ // Equal.
+ QCOMPARE(resource1 == resource2, true);
+ QCOMPARE(resource1 != resource2, false);
+
+ resource1.setVideoCodec(QString());
+
+ // Equal.
+ QCOMPARE(resource1 == resource2, true);
+ QCOMPARE(resource1 != resource2, false);
+
+ resource1.setVideoCodec(QString::fromLatin1("h264"));
+
+ // Not equal differing video codecs.
+ QCOMPARE(resource1 == resource2, false);
+ QCOMPARE(resource1 != resource2, true);
+
+ resource2.setVideoCodec(QString::fromLatin1("h264"));
+
+ // Equal.
+ QCOMPARE(resource1 == resource2, true);
+ QCOMPARE(resource1 != resource2, false);
+
+ resource2.setDataSize(0);
+
+ // Equal.
+ QCOMPARE(resource1 == resource2, true);
+ QCOMPARE(resource1 != resource2, false);
+
+ resource1.setDataSize(546423);
+
+ // Not equal differing video codecs.
+ QCOMPARE(resource1 == resource2, false);
+ QCOMPARE(resource1 != resource2, true);
+
+ resource2.setDataSize(546423);
+
+ // Equal.
+ QCOMPARE(resource1 == resource2, true);
+ QCOMPARE(resource1 != resource2, false);
+
+ resource1.setAudioBitRate(96000);
+ resource1.setSampleRate(48000);
+ resource2.setSampleRate(44100);
+ resource1.setChannelCount(0);
+ resource1.setVideoBitRate(900000);
+ resource2.setLanguage(QString::fromLatin1("eng"));
+
+ // Not equal, audio bit rate, sample rate, video bit rate, and
+ // language.
+ QCOMPARE(resource1 == resource2, false);
+ QCOMPARE(resource1 != resource2, true);
+
+ resource2.setAudioBitRate(96000);
+ resource1.setSampleRate(44100);
+
+ // Not equal, differing video bit rate, and language.
+ QCOMPARE(resource1 == resource2, false);
+ QCOMPARE(resource1 != resource2, true);
+
+ resource2.setVideoBitRate(900000);
+ resource1.setLanguage(QString::fromLatin1("eng"));
+
+ // Equal
+ QCOMPARE(resource1 == resource2, true);
+ QCOMPARE(resource1 != resource2, false);
+
+ resource1.setResolution(QSize());
+
+ // Equal
+ QCOMPARE(resource1 == resource2, true);
+ QCOMPARE(resource1 != resource2, false);
+
+ resource2.setResolution(-1, -1);
+
+ // Equal
+ QCOMPARE(resource1 == resource2, true);
+ QCOMPARE(resource1 != resource2, false);
+
+ resource1.setResolution(QSize(-640, -480));
+
+ // Not equal, differing resolution.
+ QCOMPARE(resource1 == resource2, false);
+ QCOMPARE(resource1 != resource2, true);
+ resource1.setResolution(QSize(640, 480));
+ resource2.setResolution(QSize(800, 600));
+
+ // Not equal, differing resolution.
+ QCOMPARE(resource1 == resource2, false);
+ QCOMPARE(resource1 != resource2, true);
+
+ resource1.setResolution(800, 600);
+
+ // Equal
+ QCOMPARE(resource1 == resource2, true);
+ QCOMPARE(resource1 != resource2, false);
+}
+
+void tst_QMediaResource::copy()
+{
+ const QUrl url(QString::fromLatin1("http://test.com/test.mp4"));
+ const QString mimeType(QLatin1String("video/mp4"));
+ const QString amrCodec(QLatin1String("amr"));
+ const QString mp3Codec(QLatin1String("mp3"));
+ const QString aacCodec(QLatin1String("aac"));
+ const QString h264Codec(QLatin1String("h264"));
+
+ QMediaResource original(url, mimeType);
+ original.setAudioCodec(amrCodec);
+
+ QMediaResource copy(original);
+
+ QCOMPARE(copy.url(), url);
+ QCOMPARE(copy.mimeType(), mimeType);
+ QCOMPARE(copy.audioCodec(), amrCodec);
+
+ QCOMPARE(original == copy, true);
+ QCOMPARE(original != copy, false);
+
+ original.setAudioCodec(mp3Codec);
+
+ QCOMPARE(copy.audioCodec(), amrCodec);
+ QCOMPARE(original == copy, false);
+ QCOMPARE(original != copy, true);
+
+ copy.setAudioCodec(aacCodec);
+ copy.setVideoCodec(h264Codec);
+
+ QCOMPARE(copy.url(), url);
+ QCOMPARE(copy.mimeType(), mimeType);
+
+ QCOMPARE(original.audioCodec(), mp3Codec);
+}
+
+void tst_QMediaResource::assign()
+{
+ const QUrl url(QString::fromLatin1("http://test.com/test.mp4"));
+ const QString mimeType(QLatin1String("video/mp4"));
+ const QString amrCodec(QLatin1String("amr"));
+ const QString mp3Codec(QLatin1String("mp3"));
+ const QString aacCodec(QLatin1String("aac"));
+ const QString h264Codec(QLatin1String("h264"));
+
+ QMediaResource copy(QUrl(QString::fromLatin1("file:///thumbs/test.jpg")));
+
+ QMediaResource original(url, mimeType);
+ original.setAudioCodec(amrCodec);
+
+ copy = original;
+
+ QCOMPARE(copy.url(), url);
+ QCOMPARE(copy.mimeType(), mimeType);
+ QCOMPARE(copy.audioCodec(), amrCodec);
+
+ QCOMPARE(original == copy, true);
+ QCOMPARE(original != copy, false);
+
+ original.setAudioCodec(mp3Codec);
+
+ QCOMPARE(copy.audioCodec(), amrCodec);
+ QCOMPARE(original == copy, false);
+ QCOMPARE(original != copy, true);
+
+ copy.setAudioCodec(aacCodec);
+ copy.setVideoCodec(h264Codec);
+
+ QCOMPARE(copy.url(), url);
+ QCOMPARE(copy.mimeType(), mimeType);
+
+ QCOMPARE(original.audioCodec(), mp3Codec);
+}
+
+QTEST_MAIN(tst_QMediaResource)
+
+#include "tst_qmediaresource.moc"
diff --git a/tests/auto/qmediaservice/qmediaservice.pro b/tests/auto/qmediaservice/qmediaservice.pro
new file mode 100644
index 000000000..d0397ad66
--- /dev/null
+++ b/tests/auto/qmediaservice/qmediaservice.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qmediaservice
+# CONFIG += testcase
+
+SOURCES += tst_qmediaservice.cpp
+
diff --git a/tests/auto/qmediaservice/tst_qmediaservice.cpp b/tests/auto/qmediaservice/tst_qmediaservice.cpp
new file mode 100644
index 000000000..9c23d6dc0
--- /dev/null
+++ b/tests/auto/qmediaservice/tst_qmediaservice.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <QtTest/QtTest>
+
+#include <qvideodevicecontrol.h>
+#include <qmediacontrol.h>
+#include <qmediaservice.h>
+
+#include <QtGui/qapplication.h>
+#include <QtGui/qstyle.h>
+
+QT_BEGIN_NAMESPACE
+
+class QtTestMediaService;
+
+class tst_QMediaService : public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase();
+
+ void control_iid();
+ void control();
+};
+
+
+class QtTestMediaControlA : public QMediaControl
+{
+ Q_OBJECT
+};
+
+#define QtTestMediaControlA_iid "com.nokia.QtTestMediaControlA"
+Q_MEDIA_DECLARE_CONTROL(QtTestMediaControlA, QtTestMediaControlA_iid)
+
+class QtTestMediaControlB : public QMediaControl
+{
+ Q_OBJECT
+};
+
+#define QtTestMediaControlB_iid "com.nokia.QtTestMediaControlB"
+Q_MEDIA_DECLARE_CONTROL(QtTestMediaControlB, QtTestMediaControlB_iid)
+
+
+class QtTestMediaControlC : public QMediaControl
+{
+ Q_OBJECT
+};
+
+#define QtTestMediaControlC_iid "com.nokia.QtTestMediaControlC"
+Q_MEDIA_DECLARE_CONTROL(QtTestMediaControlC, QtTestMediaControlA_iid) // Yes A.
+
+class QtTestMediaControlD : public QMediaControl
+{
+ Q_OBJECT
+};
+
+#define QtTestMediaControlD_iid "com.nokia.QtTestMediaControlD"
+Q_MEDIA_DECLARE_CONTROL(QtTestMediaControlD, QtTestMediaControlD_iid)
+
+class QtTestMediaControlE : public QMediaControl
+{
+ Q_OBJECT
+};
+
+class QtTestMediaService : public QMediaService
+{
+ Q_OBJECT
+public:
+ QtTestMediaService()
+ : QMediaService(0)
+ , refA(0)
+ , refB(0)
+ , refC(0)
+ {
+ }
+
+ QMediaControl *requestControl(const char *name)
+ {
+ if (strcmp(name, QtTestMediaControlA_iid) == 0) {
+ refA += 1;
+
+ return &controlA;
+ } else if (strcmp(name, QtTestMediaControlB_iid) == 0) {
+ refB += 1;
+
+ return &controlB;
+ } else if (strcmp(name, QtTestMediaControlC_iid) == 0) {
+ refA += 1;
+
+ return &controlA;
+ } else {
+ return 0;
+ }
+ }
+
+ void releaseControl(QMediaControl *control)
+ {
+ if (control == &controlA)
+ refA -= 1;
+ else if (control == &controlB)
+ refB -= 1;
+ else if (control == &controlC)
+ refC -= 1;
+ }
+
+ using QMediaService::requestControl;
+
+ int refA;
+ int refB;
+ int refC;
+ QtTestMediaControlA controlA;
+ QtTestMediaControlB controlB;
+ QtTestMediaControlC controlC;
+};
+
+void tst_QMediaService::initTestCase()
+{
+}
+
+void tst_QMediaService::control_iid()
+{
+ const char *nullString = 0;
+
+ // Default implementation.
+ QCOMPARE(qmediacontrol_iid<QtTestMediaControlE *>(), nullString);
+
+ // Partial template.
+ QVERIFY(qstrcmp(qmediacontrol_iid<QtTestMediaControlA *>(), QtTestMediaControlA_iid) == 0);
+}
+
+void tst_QMediaService::control()
+{
+ QtTestMediaService service;
+
+ QtTestMediaControlA *controlA = service.requestControl<QtTestMediaControlA *>();
+ QCOMPARE(controlA, &service.controlA);
+ service.releaseControl(controlA);
+
+ QtTestMediaControlB *controlB = service.requestControl<QtTestMediaControlB *>();
+ QCOMPARE(controlB, &service.controlB);
+ service.releaseControl(controlB);
+
+ QVERIFY(!service.requestControl<QtTestMediaControlC *>()); // Faulty implementation returns A.
+ QCOMPARE(service.refA, 0); // Verify the control was released.
+
+ QVERIFY(!service.requestControl<QtTestMediaControlD *>()); // No control of that type.
+}
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+QTEST_MAIN(tst_QMediaService)
+
+#include "tst_qmediaservice.moc"
diff --git a/tests/auto/qmediaserviceprovider/qmediaserviceprovider.pro b/tests/auto/qmediaserviceprovider/qmediaserviceprovider.pro
new file mode 100644
index 000000000..d107ff74f
--- /dev/null
+++ b/tests/auto/qmediaserviceprovider/qmediaserviceprovider.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qmediaserviceprovider
+# CONFIG += testcase
+
+SOURCES += tst_qmediaserviceprovider.cpp
+
diff --git a/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp
new file mode 100644
index 000000000..6e33a0412
--- /dev/null
+++ b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp
@@ -0,0 +1,489 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <QtTest/QtTest>
+#include <QDebug>
+#include <QStringList>
+
+#include <qmediaserviceprovider.h>
+#include <qmediaserviceproviderplugin.h>
+#include <private/qmediapluginloader_p.h>
+#include <qmediaobject.h>
+#include <qmediaservice.h>
+#include <qmediaplayer.h>
+#include <qaudiocapturesource.h>
+
+QT_USE_NAMESPACE
+class MockMediaService : public QMediaService
+{
+ Q_OBJECT
+public:
+ MockMediaService(const QString& name, QObject *parent = 0) : QMediaService(parent)
+ { setObjectName(name); }
+ ~MockMediaService() {}
+
+ QMediaControl* requestControl(const char *) {return 0;}
+ void releaseControl(QMediaControl *) {}
+};
+
+class MockServicePlugin1 : public QMediaServiceProviderPlugin,
+ public QMediaServiceSupportedFormatsInterface,
+ public QMediaServiceSupportedDevicesInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceSupportedFormatsInterface)
+ Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
+public:
+ QStringList keys() const
+ {
+ return QStringList() <<
+ QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER);
+ }
+
+ QMediaService* create(QString const& key)
+ {
+ if (keys().contains(key))
+ return new MockMediaService("MockServicePlugin1");
+ else
+ return 0;
+ }
+
+ void release(QMediaService *service)
+ {
+ delete service;
+ }
+
+ QtMultimediaKit::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const
+ {
+ if (codecs.contains(QLatin1String("mpeg4")))
+ return QtMultimediaKit::NotSupported;
+
+ if (mimeType == "audio/ogg") {
+ return QtMultimediaKit::ProbablySupported;
+ }
+
+ return QtMultimediaKit::MaybeSupported;
+ }
+
+ QStringList supportedMimeTypes() const
+ {
+ return QStringList("audio/ogg");
+ }
+
+ QList<QByteArray> devices(const QByteArray &service) const
+ {
+ QList<QByteArray> res;
+ return res;
+ }
+
+ QString deviceDescription(const QByteArray &service, const QByteArray &device)
+ {
+ if (devices(service).contains(device))
+ return QString(device)+" description";
+ else
+ return QString();
+ }
+};
+
+class MockServicePlugin2 : public QMediaServiceProviderPlugin,
+ public QMediaServiceSupportedFormatsInterface,
+ public QMediaServiceFeaturesInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceSupportedFormatsInterface)
+ Q_INTERFACES(QMediaServiceFeaturesInterface)
+public:
+ QStringList keys() const
+ {
+ return QStringList() << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)
+ << QLatin1String(Q_MEDIASERVICE_RADIO);
+ }
+
+ QMediaService* create(QString const& key)
+ {
+ if (keys().contains(key))
+ return new MockMediaService("MockServicePlugin2");
+ else
+ return 0;
+ }
+
+ void release(QMediaService *service)
+ {
+ delete service;
+ }
+
+ QtMultimediaKit::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const
+ {
+ Q_UNUSED(codecs);
+
+ if (mimeType == "audio/wav")
+ return QtMultimediaKit::PreferredService;
+
+ return QtMultimediaKit::NotSupported;
+ }
+
+ QStringList supportedMimeTypes() const
+ {
+ return QStringList("audio/wav");
+ }
+
+ QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const
+ {
+ if (service == QByteArray(Q_MEDIASERVICE_MEDIAPLAYER))
+ return QMediaServiceProviderHint::LowLatencyPlayback;
+ else
+ return 0;
+ }
+};
+
+
+class MockServicePlugin3 : public QMediaServiceProviderPlugin,
+ public QMediaServiceSupportedDevicesInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
+public:
+ QStringList keys() const
+ {
+ return QStringList() <<
+ QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER) <<
+ QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE);
+ }
+
+ QMediaService* create(QString const& key)
+ {
+ if (keys().contains(key))
+ return new MockMediaService("MockServicePlugin3");
+ else
+ return 0;
+ }
+
+ void release(QMediaService *service)
+ {
+ delete service;
+ }
+
+ QList<QByteArray> devices(const QByteArray &service) const
+ {
+ QList<QByteArray> res;
+ if (service == QByteArray(Q_MEDIASERVICE_AUDIOSOURCE))
+ res << "audiosource1" << "audiosource2";
+
+ return res;
+ }
+
+ QString deviceDescription(const QByteArray &service, const QByteArray &device)
+ {
+ if (devices(service).contains(device))
+ return QString(device)+" description";
+ else
+ return QString();
+ }
+};
+
+class MockServicePlugin4 : public QMediaServiceProviderPlugin,
+ public QMediaServiceSupportedFormatsInterface,
+ public QMediaServiceFeaturesInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QMediaServiceSupportedFormatsInterface)
+ Q_INTERFACES(QMediaServiceFeaturesInterface)
+public:
+ QStringList keys() const
+ {
+ return QStringList() << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER);
+ }
+
+ QMediaService* create(QString const& key)
+ {
+ if (keys().contains(key))
+ return new MockMediaService("MockServicePlugin4");
+ else
+ return 0;
+ }
+
+ void release(QMediaService *service)
+ {
+ delete service;
+ }
+
+ QtMultimediaKit::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const
+ {
+ if (codecs.contains(QLatin1String("jpeg2000")))
+ return QtMultimediaKit::NotSupported;
+
+ if (supportedMimeTypes().contains(mimeType))
+ return QtMultimediaKit::ProbablySupported;
+
+ return QtMultimediaKit::MaybeSupported;
+ }
+
+ QStringList supportedMimeTypes() const
+ {
+ return QStringList() << "video/mp4" << "video/quicktime";
+ }
+
+ QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const
+ {
+ if (service == QByteArray(Q_MEDIASERVICE_MEDIAPLAYER))
+ return QMediaServiceProviderHint::StreamPlayback;
+ else
+ return 0;
+ }
+};
+
+
+
+class MockMediaServiceProvider : public QMediaServiceProvider
+{
+ QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &)
+ {
+ Q_UNUSED(type);
+ return 0;
+ }
+
+ void releaseService(QMediaService *service)
+ {
+ Q_UNUSED(service);
+ }
+};
+
+
+class tst_QMediaServiceProvider : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+
+private slots:
+ void testDefaultProviderAvailable();
+ void testObtainService();
+ void testHasSupport();
+ void testSupportedMimeTypes();
+ void testProviderHints();
+
+private:
+ QObjectList plugins;
+};
+
+void tst_QMediaServiceProvider::initTestCase()
+{
+ plugins << new MockServicePlugin1;
+ plugins << new MockServicePlugin2;
+ plugins << new MockServicePlugin3;
+ plugins << new MockServicePlugin4;
+
+ QMediaPluginLoader::setStaticPlugins(QLatin1String("mediaservice"), plugins);
+}
+
+void tst_QMediaServiceProvider::testDefaultProviderAvailable()
+{
+ // Must always be a default provider available
+ QVERIFY(QMediaServiceProvider::defaultServiceProvider() != 0);
+}
+
+void tst_QMediaServiceProvider::testObtainService()
+{
+ QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider();
+
+ if (provider == 0)
+ QSKIP("No default provider", SkipSingle);
+
+ QMediaService *service = 0;
+
+ // Player
+ service = provider->requestService(Q_MEDIASERVICE_MEDIAPLAYER);
+ QVERIFY(service != 0);
+ provider->releaseService(service);
+}
+
+void tst_QMediaServiceProvider::testHasSupport()
+{
+ MockMediaServiceProvider mockProvider;
+ QCOMPARE(mockProvider.hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "video/ogv", QStringList()),
+ QtMultimediaKit::MaybeSupported);
+
+ QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider();
+
+ if (provider == 0)
+ QSKIP("No default provider", SkipSingle);
+
+ QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "video/ogv", QStringList()),
+ QtMultimediaKit::MaybeSupported);
+
+ QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "audio/ogg", QStringList()),
+ QtMultimediaKit::ProbablySupported);
+
+ //while the service returns PreferredService, provider should return ProbablySupported
+ QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "audio/wav", QStringList()),
+ QtMultimediaKit::ProbablySupported);
+
+ //even while all the plugins with "hasSupport" returned NotSupported,
+ //MockServicePlugin3 has no "hasSupport" interface, so MaybeSupported
+ QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "video/avi",
+ QStringList() << "mpeg4"),
+ QtMultimediaKit::MaybeSupported);
+
+ QCOMPARE(provider->hasSupport(QByteArray("non existing service"), "video/ogv", QStringList()),
+ QtMultimediaKit::NotSupported);
+
+ QCOMPARE(QMediaPlayer::hasSupport("video/ogv"), QtMultimediaKit::MaybeSupported);
+ QCOMPARE(QMediaPlayer::hasSupport("audio/ogg"), QtMultimediaKit::ProbablySupported);
+ QCOMPARE(QMediaPlayer::hasSupport("audio/wav"), QtMultimediaKit::ProbablySupported);
+
+ //test low latency flag support
+ QCOMPARE(QMediaPlayer::hasSupport("audio/wav", QStringList(), QMediaPlayer::LowLatency),
+ QtMultimediaKit::ProbablySupported);
+ //plugin1 probably supports audio/ogg, it checked because it doesn't provide features iface
+ QCOMPARE(QMediaPlayer::hasSupport("audio/ogg", QStringList(), QMediaPlayer::LowLatency),
+ QtMultimediaKit::ProbablySupported);
+ //Plugin4 is not checked here, sine it's known not support low latency
+ QCOMPARE(QMediaPlayer::hasSupport("video/quicktime", QStringList(), QMediaPlayer::LowLatency),
+ QtMultimediaKit::MaybeSupported);
+
+ //test streaming flag support
+ QCOMPARE(QMediaPlayer::hasSupport("video/quicktime", QStringList(), QMediaPlayer::StreamPlayback),
+ QtMultimediaKit::ProbablySupported);
+ //Plugin2 is not checked here, sine it's known not support streaming
+ QCOMPARE(QMediaPlayer::hasSupport("audio/wav", QStringList(), QMediaPlayer::StreamPlayback),
+ QtMultimediaKit::MaybeSupported);
+
+ //ensure the correct media player plugin is chosen for mime type
+ QMediaPlayer simplePlayer(0, QMediaPlayer::LowLatency);
+ QCOMPARE(simplePlayer.service()->objectName(), QLatin1String("MockServicePlugin2"));
+
+ QMediaPlayer mediaPlayer;
+ QVERIFY(mediaPlayer.service()->objectName() != QLatin1String("MockServicePlugin2"));
+
+ QMediaPlayer streamPlayer(0, QMediaPlayer::StreamPlayback);
+ QCOMPARE(streamPlayer.service()->objectName(), QLatin1String("MockServicePlugin4"));
+}
+
+void tst_QMediaServiceProvider::testSupportedMimeTypes()
+{
+ QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider();
+
+ if (provider == 0)
+ QSKIP("No default provider", SkipSingle);
+
+ QVERIFY(provider->supportedMimeTypes(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER)).contains("audio/ogg"));
+ QVERIFY(!provider->supportedMimeTypes(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER)).contains("audio/mp3"));
+}
+
+void tst_QMediaServiceProvider::testProviderHints()
+{
+ {
+ QMediaServiceProviderHint hint;
+ QVERIFY(hint.isNull());
+ QCOMPARE(hint.type(), QMediaServiceProviderHint::Null);
+ QVERIFY(hint.device().isEmpty());
+ QVERIFY(hint.mimeType().isEmpty());
+ QVERIFY(hint.codecs().isEmpty());
+ QCOMPARE(hint.features(), 0);
+ }
+
+ {
+ QByteArray deviceName(QByteArray("testDevice"));
+ QMediaServiceProviderHint hint(deviceName);
+ QVERIFY(!hint.isNull());
+ QCOMPARE(hint.type(), QMediaServiceProviderHint::Device);
+ QCOMPARE(hint.device(), deviceName);
+ QVERIFY(hint.mimeType().isEmpty());
+ QVERIFY(hint.codecs().isEmpty());
+ QCOMPARE(hint.features(), 0);
+ }
+
+ {
+ QMediaServiceProviderHint hint(QMediaServiceProviderHint::LowLatencyPlayback);
+ QVERIFY(!hint.isNull());
+ QCOMPARE(hint.type(), QMediaServiceProviderHint::SupportedFeatures);
+ QVERIFY(hint.device().isEmpty());
+ QVERIFY(hint.mimeType().isEmpty());
+ QVERIFY(hint.codecs().isEmpty());
+ QCOMPARE(hint.features(), QMediaServiceProviderHint::LowLatencyPlayback);
+ }
+
+ {
+ QString mimeType(QLatin1String("video/ogg"));
+ QStringList codecs;
+ codecs << "theora" << "vorbis";
+
+ QMediaServiceProviderHint hint(mimeType,codecs);
+ QVERIFY(!hint.isNull());
+ QCOMPARE(hint.type(), QMediaServiceProviderHint::ContentType);
+ QVERIFY(hint.device().isEmpty());
+ QCOMPARE(hint.mimeType(), mimeType);
+ QCOMPARE(hint.codecs(), codecs);
+
+ QMediaServiceProviderHint hint2(hint);
+
+ QVERIFY(!hint2.isNull());
+ QCOMPARE(hint2.type(), QMediaServiceProviderHint::ContentType);
+ QVERIFY(hint2.device().isEmpty());
+ QCOMPARE(hint2.mimeType(), mimeType);
+ QCOMPARE(hint2.codecs(), codecs);
+
+ QMediaServiceProviderHint hint3;
+ QVERIFY(hint3.isNull());
+ hint3 = hint;
+ QVERIFY(!hint3.isNull());
+ QCOMPARE(hint3.type(), QMediaServiceProviderHint::ContentType);
+ QVERIFY(hint3.device().isEmpty());
+ QCOMPARE(hint3.mimeType(), mimeType);
+ QCOMPARE(hint3.codecs(), codecs);
+
+ QCOMPARE(hint, hint2);
+ QCOMPARE(hint3, hint2);
+
+ QMediaServiceProviderHint hint4(mimeType,codecs);
+ QCOMPARE(hint, hint4);
+
+ QMediaServiceProviderHint hint5(mimeType,QStringList());
+ QVERIFY(hint != hint5);
+ }
+}
+
+QTEST_MAIN(tst_QMediaServiceProvider)
+
+#include "tst_qmediaserviceprovider.moc"
diff --git a/tests/auto/qmediatimerange/qmediatimerange.pro b/tests/auto/qmediatimerange/qmediatimerange.pro
new file mode 100644
index 000000000..004bf373d
--- /dev/null
+++ b/tests/auto/qmediatimerange/qmediatimerange.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qmediatimerange
+# CONFIG += testcase
+
+SOURCES += tst_qmediatimerange.cpp
+
diff --git a/tests/auto/qmediatimerange/tst_qmediatimerange.cpp b/tests/auto/qmediatimerange/tst_qmediatimerange.cpp
new file mode 100644
index 000000000..2dfdd1be5
--- /dev/null
+++ b/tests/auto/qmediatimerange/tst_qmediatimerange.cpp
@@ -0,0 +1,739 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <QtTest/QtTest>
+#include <QtCore/qdebug.h>
+
+#include <qmediatimerange.h>
+
+QT_USE_NAMESPACE
+
+class tst_QMediaTimeRange: public QObject
+{
+ Q_OBJECT
+
+public slots:
+
+private slots:
+ void testCtor();
+ void testGetters();
+ void testAssignment();
+ void testNormalize();
+ void testTranslated();
+ void testEarliestLatest();
+ void testContains();
+ void testAddInterval();
+ void testAddTimeRange();
+ void testRemoveInterval();
+ void testRemoveTimeRange();
+ void testClear();
+ void testComparisons();
+ void testArithmetic();
+};
+
+void tst_QMediaTimeRange::testCtor()
+{
+ // Default Ctor
+ QMediaTimeRange a;
+ QVERIFY(a.isEmpty());
+
+ // (qint, qint) Ctor
+ QMediaTimeRange b(10, 20);
+
+ QVERIFY(!b.isEmpty());
+ QVERIFY(b.isContinuous());
+ QVERIFY(b.earliestTime() == 10);
+ QVERIFY(b.latestTime() == 20);
+
+ // Interval Ctor
+ QMediaTimeRange c(QMediaTimeInterval(30, 40));
+
+ QVERIFY(!c.isEmpty());
+ QVERIFY(c.isContinuous());
+ QVERIFY(c.earliestTime() == 30);
+ QVERIFY(c.latestTime() == 40);
+
+ // Abnormal Interval Ctor
+ QMediaTimeRange d(QMediaTimeInterval(20, 10));
+
+ QVERIFY(d.isEmpty());
+
+ // Copy Ctor
+ QMediaTimeRange e(b);
+
+ QVERIFY(!e.isEmpty());
+ QVERIFY(e.isContinuous());
+ QVERIFY(e.earliestTime() == 10);
+ QVERIFY(e.latestTime() == 20);
+}
+
+void tst_QMediaTimeRange::testGetters()
+{
+ QMediaTimeRange x;
+
+ // isEmpty
+ QVERIFY(x.isEmpty());
+
+ x.addInterval(10, 20);
+
+ // isEmpty + isContinuous
+ QVERIFY(!x.isEmpty());
+ QVERIFY(x.isContinuous());
+
+ x.addInterval(30, 40);
+
+ // isEmpty + isContinuous + intervals + start + end
+ QVERIFY(!x.isEmpty());
+ QVERIFY(!x.isContinuous());
+ QVERIFY(x.intervals().count() == 2);
+ QVERIFY(x.intervals()[0].start() == 10);
+ QVERIFY(x.intervals()[0].end() == 20);
+ QVERIFY(x.intervals()[1].start() == 30);
+ QVERIFY(x.intervals()[1].end() == 40);
+}
+
+void tst_QMediaTimeRange::testAssignment()
+{
+ QMediaTimeRange x;
+
+ // Range Assignment
+ x = QMediaTimeRange(10, 20);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(x.isContinuous());
+ QVERIFY(x.earliestTime() == 10);
+ QVERIFY(x.latestTime() == 20);
+
+ // Interval Assignment
+ x = QMediaTimeInterval(30, 40);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(x.isContinuous());
+ QVERIFY(x.earliestTime() == 30);
+ QVERIFY(x.latestTime() == 40);
+
+ // Shared Data Check
+ QMediaTimeRange y;
+
+ y = x;
+ y.addInterval(10, 20);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(x.isContinuous());
+ QVERIFY(x.earliestTime() == 30);
+ QVERIFY(x.latestTime() == 40);
+}
+
+void tst_QMediaTimeRange::testNormalize()
+{
+ QMediaTimeInterval x(20, 10);
+
+ QVERIFY(!x.isNormal());
+
+ x = x.normalized();
+
+ QVERIFY(x.isNormal());
+ QVERIFY(x.start() == 10);
+ QVERIFY(x.end() == 20);
+}
+
+void tst_QMediaTimeRange::testTranslated()
+{
+ QMediaTimeInterval x(10, 20);
+ x = x.translated(10);
+
+ QVERIFY(x.start() == 20);
+ QVERIFY(x.end() == 30);
+}
+
+void tst_QMediaTimeRange::testEarliestLatest()
+{
+ // Test over a single interval
+ QMediaTimeRange x(30, 40);
+
+ QVERIFY(x.earliestTime() == 30);
+ QVERIFY(x.latestTime() == 40);
+
+ // Test over multiple intervals
+ x.addInterval(50, 60);
+
+ QVERIFY(x.earliestTime() == 30);
+ QVERIFY(x.latestTime() == 60);
+}
+
+void tst_QMediaTimeRange::testContains()
+{
+ // Test over a single interval
+ QMediaTimeRange x(10, 20);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(x.isContinuous());
+ QVERIFY(x.contains(15));
+ QVERIFY(x.contains(10));
+ QVERIFY(x.contains(20));
+ QVERIFY(!x.contains(25));
+
+ // Test over multiple intervals
+ x.addInterval(40, 50);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(!x.isContinuous());
+ QVERIFY(x.contains(15));
+ QVERIFY(x.contains(45));
+ QVERIFY(!x.contains(30));
+
+ // Test over a concrete interval
+ QMediaTimeInterval y(10, 20);
+ QVERIFY(y.contains(15));
+ QVERIFY(y.contains(10));
+ QVERIFY(y.contains(20));
+ QVERIFY(!y.contains(25));
+}
+
+void tst_QMediaTimeRange::testAddInterval()
+{
+ // All intervals Overlap
+ QMediaTimeRange x;
+ x.addInterval(10, 40);
+ x.addInterval(30, 50);
+ x.addInterval(20, 60);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(x.isContinuous());
+ QVERIFY(x.earliestTime() == 10);
+ QVERIFY(x.latestTime() == 60);
+
+ // 1 adjacent interval, 1 encompassed interval
+ x = QMediaTimeRange();
+ x.addInterval(10, 40);
+ x.addInterval(20, 30);
+ x.addInterval(41, 50);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(x.isContinuous());
+ QVERIFY(x.earliestTime() == 10);
+ QVERIFY(x.latestTime() == 50);
+
+ // 1 overlapping interval, 1 disjoint interval
+ x = QMediaTimeRange();
+ x.addInterval(10, 30);
+ x.addInterval(20, 40);
+ x.addInterval(50, 60);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(!x.isContinuous());
+ QVERIFY(x.intervals().count() == 2);
+ QVERIFY(x.intervals()[0].start() == 10);
+ QVERIFY(x.intervals()[0].end() == 40);
+ QVERIFY(x.intervals()[1].start() == 50);
+ QVERIFY(x.intervals()[1].end() == 60);
+
+ // Identical Add
+ x = QMediaTimeRange();
+ x.addInterval(10, 20);
+ x.addInterval(10, 20);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(x.isContinuous());
+ QVERIFY(x.earliestTime() == 10);
+ QVERIFY(x.latestTime() == 20);
+
+ // Multi-Merge
+ x = QMediaTimeRange();
+ x.addInterval(10, 20);
+ x.addInterval(30, 40);
+ x.addInterval(50, 60);
+ x.addInterval(15, 55);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(x.isContinuous());
+ QVERIFY(x.earliestTime() == 10);
+ QVERIFY(x.latestTime() == 60);
+
+ // Interval Parameter - All intervals Overlap
+ x = QMediaTimeRange();
+ x.addInterval(QMediaTimeInterval(10, 40));
+ x.addInterval(QMediaTimeInterval(30, 50));
+ x.addInterval(QMediaTimeInterval(20, 60));
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(x.isContinuous());
+ QVERIFY(x.earliestTime() == 10);
+ QVERIFY(x.latestTime() == 60);
+
+ // Interval Parameter - Abnormal Interval
+ x = QMediaTimeRange();
+ x.addInterval(QMediaTimeInterval(20, 10));
+
+ QVERIFY(x.isEmpty());
+}
+
+void tst_QMediaTimeRange::testAddTimeRange()
+{
+ // Add Time Range uses Add Interval internally,
+ // so in this test the focus is on combinations of number
+ // of intervals added, rather than the different types of
+ // merges which can occur.
+ QMediaTimeRange a, b;
+
+ // Add Single into Single
+ a = QMediaTimeRange(10, 30);
+ b = QMediaTimeRange(20, 40);
+
+ b.addTimeRange(a);
+
+ QVERIFY(!b.isEmpty());
+ QVERIFY(b.isContinuous());
+ QVERIFY(b.earliestTime() == 10);
+ QVERIFY(b.latestTime() == 40);
+
+ // Add Multiple into Single
+ a = QMediaTimeRange();
+ a.addInterval(10, 30);
+ a.addInterval(40, 60);
+
+ b = QMediaTimeRange(20, 50);
+
+ b.addTimeRange(a);
+
+ QVERIFY(!b.isEmpty());
+ QVERIFY(b.isContinuous());
+ QVERIFY(b.earliestTime() == 10);
+ QVERIFY(b.latestTime() == 60);
+
+ // Add Single into Multiple
+ a = QMediaTimeRange(20, 50);
+
+ b = QMediaTimeRange();
+ b.addInterval(10, 30);
+ b.addInterval(40, 60);
+
+ b.addTimeRange(a);
+
+ QVERIFY(!b.isEmpty());
+ QVERIFY(b.isContinuous());
+ QVERIFY(b.earliestTime() == 10);
+ QVERIFY(b.latestTime() == 60);
+
+ // Add Multiple into Multiple
+ a = QMediaTimeRange();
+ a.addInterval(10, 30);
+ a.addInterval(40, 70);
+ a.addInterval(80, 100);
+
+ b = QMediaTimeRange();
+ b.addInterval(20, 50);
+ b.addInterval(60, 90);
+
+ b.addTimeRange(a);
+
+ QVERIFY(!b.isEmpty());
+ QVERIFY(b.isContinuous());
+ QVERIFY(b.earliestTime() == 10);
+ QVERIFY(b.latestTime() == 100);
+
+ // Add Nothing to Single
+ a = QMediaTimeRange();
+ b = QMediaTimeRange(10, 20);
+
+ b.addTimeRange(a);
+
+ QVERIFY(!b.isEmpty());
+ QVERIFY(b.isContinuous());
+ QVERIFY(b.earliestTime() == 10);
+ QVERIFY(b.latestTime() == 20);
+
+ // Add Single to Nothing
+ a = QMediaTimeRange(10, 20);
+ b = QMediaTimeRange();
+
+ b.addTimeRange(a);
+
+ QVERIFY(!b.isEmpty());
+ QVERIFY(b.isContinuous());
+ QVERIFY(b.earliestTime() == 10);
+ QVERIFY(b.latestTime() == 20);
+
+ // Add Nothing to Nothing
+ a = QMediaTimeRange();
+ b = QMediaTimeRange();
+
+ b.addTimeRange(a);
+
+ QVERIFY(b.isEmpty());
+}
+
+void tst_QMediaTimeRange::testRemoveInterval()
+{
+ // Removing an interval, causing a split
+ QMediaTimeRange x;
+ x.addInterval(10, 50);
+ x.removeInterval(20, 40);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(!x.isContinuous());
+ QVERIFY(x.intervals().count() == 2);
+ QVERIFY(x.intervals()[0].start() == 10);
+ QVERIFY(x.intervals()[0].end() == 19);
+ QVERIFY(x.intervals()[1].start() == 41);
+ QVERIFY(x.intervals()[1].end() == 50);
+
+ // Removing an interval, causing a deletion
+ x = QMediaTimeRange();
+ x.addInterval(20, 30);
+ x.removeInterval(10, 40);
+
+ QVERIFY(x.isEmpty());
+
+ // Removing an interval, causing a tail trim
+ x = QMediaTimeRange();
+ x.addInterval(20, 40);
+ x.removeInterval(30, 50);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(x.isContinuous());
+ QVERIFY(x.earliestTime() == 20);
+ QVERIFY(x.latestTime() == 29);
+
+ // Removing an interval, causing a head trim
+ x = QMediaTimeRange();
+ x.addInterval(20, 40);
+ x.removeInterval(10, 30);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(x.isContinuous());
+ QVERIFY(x.earliestTime() == 31);
+ QVERIFY(x.latestTime() == 40);
+
+ // Identical Remove
+ x = QMediaTimeRange();
+ x.addInterval(10, 20);
+ x.removeInterval(10, 20);
+
+ QVERIFY(x.isEmpty());
+
+ // Multi-Trim
+ x = QMediaTimeRange();
+ x.addInterval(10, 20);
+ x.addInterval(30, 40);
+ x.removeInterval(15, 35);
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(!x.isContinuous());
+ QVERIFY(x.intervals().count() == 2);
+ QVERIFY(x.intervals()[0].start() == 10);
+ QVERIFY(x.intervals()[0].end() == 14);
+ QVERIFY(x.intervals()[1].start() == 36);
+ QVERIFY(x.intervals()[1].end() == 40);
+
+ // Multi-Delete
+ x = QMediaTimeRange();
+ x.addInterval(10, 20);
+ x.addInterval(30, 40);
+ x.addInterval(50, 60);
+ x.removeInterval(10, 60);
+
+ QVERIFY(x.isEmpty());
+
+ // Interval Parameter - Removing an interval, causing a split
+ x = QMediaTimeRange();
+ x.addInterval(10, 50);
+ x.removeInterval(QMediaTimeInterval(20, 40));
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(!x.isContinuous());
+ QVERIFY(x.intervals().count() == 2);
+ QVERIFY(x.intervals()[0].start() == 10);
+ QVERIFY(x.intervals()[0].end() == 19);
+ QVERIFY(x.intervals()[1].start() == 41);
+ QVERIFY(x.intervals()[1].end() == 50);
+
+ // Interval Parameter - Abnormal Interval
+ x = QMediaTimeRange();
+ x.addInterval(10, 40);
+ x.removeInterval(QMediaTimeInterval(30, 20));
+
+ QVERIFY(!x.isEmpty());
+ QVERIFY(x.isContinuous());
+ QVERIFY(x.earliestTime() == 10);
+ QVERIFY(x.latestTime() == 40);
+}
+
+void tst_QMediaTimeRange::testRemoveTimeRange()
+{
+ // Remove Time Range uses Remove Interval internally,
+ // so in this test the focus is on combinations of number
+ // of intervals removed, rather than the different types of
+ // deletions which can occur.
+ QMediaTimeRange a, b;
+
+ // Remove Single from Single
+ a = QMediaTimeRange(10, 30);
+ b = QMediaTimeRange(20, 40);
+
+ b.removeTimeRange(a);
+
+ QVERIFY(!b.isEmpty());
+ QVERIFY(b.isContinuous());
+ QVERIFY(b.earliestTime() == 31);
+ QVERIFY(b.latestTime() == 40);
+
+ // Remove Multiple from Single
+ a = QMediaTimeRange();
+ a.addInterval(10, 30);
+ a.addInterval(40, 60);
+
+ b = QMediaTimeRange(20, 50);
+
+ b.removeTimeRange(a);
+
+ QVERIFY(!b.isEmpty());
+ QVERIFY(b.isContinuous());
+ QVERIFY(b.earliestTime() == 31);
+ QVERIFY(b.latestTime() == 39);
+
+ // Remove Single from Multiple
+ a = QMediaTimeRange(20, 50);
+
+ b = QMediaTimeRange();
+ b.addInterval(10, 30);
+ b.addInterval(40, 60);
+
+ b.removeTimeRange(a);
+
+ QVERIFY(!b.isEmpty());
+ QVERIFY(!b.isContinuous());
+ QVERIFY(b.intervals().count() == 2);
+ QVERIFY(b.intervals()[0].start() == 10);
+ QVERIFY(b.intervals()[0].end() == 19);
+ QVERIFY(b.intervals()[1].start() == 51);
+ QVERIFY(b.intervals()[1].end() == 60);
+
+ // Remove Multiple from Multiple
+ a = QMediaTimeRange();
+ a.addInterval(20, 50);
+ a.addInterval(50, 90);
+
+
+ b = QMediaTimeRange();
+ b.addInterval(10, 30);
+ b.addInterval(40, 70);
+ b.addInterval(80, 100);
+
+ b.removeTimeRange(a);
+
+ QVERIFY(!b.isEmpty());
+ QVERIFY(!b.isContinuous());
+ QVERIFY(b.intervals().count() == 2);
+ QVERIFY(b.intervals()[0].start() == 10);
+ QVERIFY(b.intervals()[0].end() == 19);
+ QVERIFY(b.intervals()[1].start() == 91);
+ QVERIFY(b.intervals()[1].end() == 100);
+
+ // Remove Nothing from Single
+ a = QMediaTimeRange();
+ b = QMediaTimeRange(10, 20);
+
+ b.removeTimeRange(a);
+
+ QVERIFY(!b.isEmpty());
+ QVERIFY(b.isContinuous());
+ QVERIFY(b.earliestTime() == 10);
+ QVERIFY(b.latestTime() == 20);
+
+ // Remove Single from Nothing
+ a = QMediaTimeRange(10, 20);
+ b = QMediaTimeRange();
+
+ b.removeTimeRange(a);
+
+ QVERIFY(b.isEmpty());
+
+ // Remove Nothing from Nothing
+ a = QMediaTimeRange();
+ b = QMediaTimeRange();
+
+ b.removeTimeRange(a);
+
+ QVERIFY(b.isEmpty());
+}
+
+void tst_QMediaTimeRange::testClear()
+{
+ QMediaTimeRange x;
+
+ // Clear Nothing
+ x.clear();
+
+ QVERIFY(x.isEmpty());
+
+ // Clear Single
+ x = QMediaTimeRange(10, 20);
+ x.clear();
+
+ QVERIFY(x.isEmpty());
+
+ // Clear Multiple
+ x = QMediaTimeRange();
+ x.addInterval(10, 20);
+ x.addInterval(30, 40);
+ x.clear();
+
+ QVERIFY(x.isEmpty());
+}
+
+void tst_QMediaTimeRange::testComparisons()
+{
+ // Interval equality
+ QVERIFY(QMediaTimeInterval(10, 20) == QMediaTimeInterval(10, 20));
+ QVERIFY(QMediaTimeInterval(10, 20) != QMediaTimeInterval(10, 30));
+ QVERIFY(!(QMediaTimeInterval(10, 20) != QMediaTimeInterval(10, 20)));
+ QVERIFY(!(QMediaTimeInterval(10, 20) == QMediaTimeInterval(10, 30)));
+
+ // Time range equality - Single Interval
+ QMediaTimeRange a(10, 20), b(20, 30), c(10, 20);
+
+ QVERIFY(a == c);
+ QVERIFY(!(a == b));
+ QVERIFY(a != b);
+ QVERIFY(!(a != c));
+
+ // Time Range Equality - Multiple Intervals
+ QMediaTimeRange x, y, z;
+
+ x.addInterval(10, 20);
+ x.addInterval(30, 40);
+ x.addInterval(50, 60);
+
+ y.addInterval(10, 20);
+ y.addInterval(35, 45);
+ y.addInterval(50, 60);
+
+ z.addInterval(10, 20);
+ z.addInterval(30, 40);
+ z.addInterval(50, 60);
+
+ QVERIFY(x == z);
+ QVERIFY(!(x == y));
+ QVERIFY(x != y);
+ QVERIFY(!(x != z));
+}
+
+void tst_QMediaTimeRange::testArithmetic()
+{
+ QMediaTimeRange a(10, 20), b(20, 30);
+
+ // Test +=
+ a += b;
+
+ QVERIFY(a.isContinuous());
+ QVERIFY(a.earliestTime() == 10);
+ QVERIFY(a.latestTime() == 30);
+
+ // Test -=
+ a -= b;
+
+ QVERIFY(a.isContinuous());
+ QVERIFY(a.earliestTime() == 10);
+ QVERIFY(a.latestTime() == 19);
+
+ // Test += and -= on intervals
+ a -= QMediaTimeInterval(10, 20);
+ a += QMediaTimeInterval(40, 50);
+
+ QVERIFY(a.isContinuous());
+ QVERIFY(a.earliestTime() == 40);
+ QVERIFY(a.latestTime() == 50);
+
+ // Test Interval + Interval
+ a = QMediaTimeInterval(10, 20) + QMediaTimeInterval(20, 30);
+ QVERIFY(a.isContinuous());
+ QVERIFY(a.earliestTime() == 10);
+ QVERIFY(a.latestTime() == 30);
+
+ // Test Range + Interval
+ a = a + QMediaTimeInterval(30, 40);
+ QVERIFY(a.isContinuous());
+ QVERIFY(a.earliestTime() == 10);
+ QVERIFY(a.latestTime() == 40);
+
+ // Test Interval + Range
+ a = QMediaTimeInterval(40, 50) + a;
+ QVERIFY(a.isContinuous());
+ QVERIFY(a.earliestTime() == 10);
+ QVERIFY(a.latestTime() == 50);
+
+ // Test Range + Range
+ a = a + QMediaTimeRange(50, 60);
+ QVERIFY(a.isContinuous());
+ QVERIFY(a.earliestTime() == 10);
+ QVERIFY(a.latestTime() == 60);
+
+ // Test Range - Interval
+ a = a - QMediaTimeInterval(50, 60);
+ QVERIFY(a.isContinuous());
+ QVERIFY(a.earliestTime() == 10);
+ QVERIFY(a.latestTime() == 49);
+
+ // Test Range - Range
+ a = a - QMediaTimeRange(40, 50);
+ QVERIFY(a.isContinuous());
+ QVERIFY(a.earliestTime() == 10);
+ QVERIFY(a.latestTime() == 39);
+
+ // Test Interval - Range
+ b = QMediaTimeInterval(0, 20) - a;
+ QVERIFY(b.isContinuous());
+ QVERIFY(b.earliestTime() == 0);
+ QVERIFY(b.latestTime() == 9);
+
+ // Test Interval - Interval
+ a = QMediaTimeInterval(10, 20) - QMediaTimeInterval(15, 30);
+ QVERIFY(a.isContinuous());
+ QVERIFY(a.earliestTime() == 10);
+ QVERIFY(a.latestTime() == 14);
+}
+
+QTEST_MAIN(tst_QMediaTimeRange)
+
+#include "tst_qmediatimerange.moc"
diff --git a/tests/auto/qpaintervideosurface/qpaintervideosurface.pro b/tests/auto/qpaintervideosurface/qpaintervideosurface.pro
new file mode 100644
index 000000000..a6c686d6d
--- /dev/null
+++ b/tests/auto/qpaintervideosurface/qpaintervideosurface.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qpaintervideosurface
+# CONFIG += testcase
+
+contains(QT_CONFIG, opengl): QT += opengl
+
+SOURCES += tst_qpaintervideosurface.cpp
+
diff --git a/tests/auto/qpaintervideosurface/tst_qpaintervideosurface.cpp b/tests/auto/qpaintervideosurface/tst_qpaintervideosurface.cpp
new file mode 100644
index 000000000..6c220c3db
--- /dev/null
+++ b/tests/auto/qpaintervideosurface/tst_qpaintervideosurface.cpp
@@ -0,0 +1,1249 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <private/qpaintervideosurface_p.h>
+#include <QtTest/QtTest>
+
+#include <QtGui/qapplication.h>
+#include <qvideosurfaceformat.h>
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+#include <QtOpenGL/qgl.h>
+#include <QtOpenGL/qglframebufferobject.h>
+#endif
+
+QT_USE_NAMESPACE
+class tst_QPainterVideoSurface : public QObject
+{
+ Q_OBJECT
+private slots:
+ void cleanup() {}
+ void cleanupTestCase() {}
+
+ void colors();
+
+ void supportedFormat_data();
+ void supportedFormat();
+
+ void present_data();
+ void present();
+ void presentOpaqueFrame();
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+
+ void shaderType();
+
+ void shaderTypeStarted_data();
+ void shaderTypeStarted();
+
+ void shaderSupportedFormat_data();
+ void shaderSupportedFormat();
+
+ void shaderPresent_data();
+ void shaderPresent();
+ void shaderPresentOpaqueFrame_data();
+ void shaderPresentOpaqueFrame();
+ void shaderPresentGLFrame_data();
+ void shaderPresentGLFrame();
+#endif
+};
+
+Q_DECLARE_METATYPE(const uchar *)
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+Q_DECLARE_METATYPE(QPainterVideoSurface::ShaderType);
+
+class QtTestGLVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ QtTestGLVideoBuffer()
+ : QAbstractVideoBuffer(GLTextureHandle)
+ , m_textureId(0)
+ {
+ glGenTextures(1, &m_textureId);
+ }
+
+ ~QtTestGLVideoBuffer()
+ {
+ glDeleteTextures(1, &m_textureId);
+ }
+
+ GLuint textureId() const { return m_textureId; }
+
+ QVariant handle() const { return m_textureId; }
+
+ uchar *map(MapMode, int *, int *) { return 0; }
+ void unmap() {}
+ MapMode mapMode() const { return NotMapped; }
+
+private:
+ GLuint m_textureId;
+};
+
+#endif
+
+class QtTestOpaqueVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ QtTestOpaqueVideoBuffer()
+ : QAbstractVideoBuffer(UserHandle)
+ {}
+
+ uchar *map(MapMode, int *, int *) { return 0; }
+ void unmap() {}
+ MapMode mapMode() const { return NotMapped; }
+};
+
+void tst_QPainterVideoSurface::colors()
+{
+ QPainterVideoSurface surface;
+
+ QCOMPARE(surface.brightness(), 0);
+ QCOMPARE(surface.contrast(), 0);
+ QCOMPARE(surface.hue(), 0);
+ QCOMPARE(surface.saturation(), 0);
+
+ surface.setBrightness(56);
+ QCOMPARE(surface.brightness(), 56);
+
+ surface.setContrast(43);
+ QCOMPARE(surface.contrast(), 43);
+
+ surface.setHue(-84);
+ QCOMPARE(surface.hue(), -84);
+
+ surface.setSaturation(100);
+ QCOMPARE(surface.saturation(), 100);
+}
+
+static const uchar rgb32ImageData[] =
+{
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00
+};
+
+static const uchar argb32ImageData[] =
+{
+ 0x00, 0xff, 0x00, 0x00, 0xcc, 0x00, 0xff, 0xcc,
+ 0x77, 0x00, 0x00, 0x77, 0x00, 0xff, 0xff, 0x00
+};
+
+static const uchar rgb24ImageData[] =
+{
+ 0x00, 0xff, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00,
+ 0xcc, 0x00, 0xcc, 0x77, 0xff, 0x77, 0x00, 0x00
+};
+
+static const uchar rgb565ImageData[] =
+{
+ 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00
+};
+
+static const uchar yuvPlanarImageData[] =
+{
+ 0x00, 0x00, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00,
+ 0x00, 0x0f, 0xff, 0x0f, 0x0f, 0xff, 0x0f, 0x00,
+ 0x00, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0x00,
+ 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff,
+ 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff,
+ 0x0f, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0x0f,
+ 0x00, 0x0f, 0xff, 0x0f, 0x0f, 0xff, 0x0f, 0x00,
+ 0x00, 0x00, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00,
+ 0x00, 0x0f, 0x0f, 0x00,
+ 0x0f, 0x00, 0x00, 0x0f,
+ 0x0f, 0x00, 0x00, 0x0f,
+ 0x00, 0x0f, 0x0f, 0x00,
+ 0x00, 0x0f, 0x0f, 0x00,
+ 0x0f, 0x00, 0x00, 0x0f,
+ 0x0f, 0x00, 0x00, 0x0f,
+ 0x00, 0x0f, 0x0f, 0x00,
+};
+
+void tst_QPainterVideoSurface::supportedFormat_data()
+{
+ QTest::addColumn<QAbstractVideoBuffer::HandleType>("handleType");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormat");
+ QTest::addColumn<QSize>("frameSize");
+ QTest::addColumn<bool>("supportedPixelFormat");
+ QTest::addColumn<bool>("supportedFormat");
+
+ QTest::newRow("rgb32 640x480")
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_RGB32
+ << QSize(640, 480)
+ << true
+ << true;
+ QTest::newRow("rgb32 -640x480")
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_RGB32
+ << QSize(-640, 480)
+ << true
+ << false;
+ QTest::newRow("rgb24 1024x768")
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_RGB24
+ << QSize(1024, 768)
+#ifndef QT_OPENGL_ES
+ << true
+ << true;
+#else
+ << false
+ << false;
+#endif
+ QTest::newRow("rgb24 -1024x-768")
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_RGB24
+ << QSize(-1024, -768)
+#ifndef QT_OPENGL_ES
+ << true
+#else
+ << false
+#endif
+ << false;
+ QTest::newRow("rgb565 0x0")
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_RGB565
+ << QSize(0, 0)
+ << true
+ << false;
+ QTest::newRow("YUV420P 640x480")
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_YUV420P
+ << QSize(640, 480)
+ << false
+ << false;
+ QTest::newRow("YUV420P 640x-480")
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_YUV420P
+ << QSize(640, -480)
+ << false
+ << false;
+ QTest::newRow("Y8 640x480")
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_Y8
+ << QSize(640, 480)
+ << false
+ << false;
+ QTest::newRow("Texture: rgb32 640x480")
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_RGB32
+ << QSize(640, 480)
+ << false
+ << false;
+ QTest::newRow("Texture: rgb32 -640x480")
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_RGB32
+ << QSize(-640, 480)
+ << false
+ << false;
+ QTest::newRow("rgb565 32x32")
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_RGB565
+ << QSize(32, 32)
+ << true
+ << true;
+ QTest::newRow("rgb565 0x0")
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_RGB565
+ << QSize(0, 0)
+ << true
+ << false;
+ QTest::newRow("argb32 256x256")
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_ARGB32
+ << QSize(256, 256)
+ << true
+ << true;
+ QTest::newRow("Texture: rgb24 1024x768")
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_RGB24
+ << QSize(1024, 768)
+ << false
+ << false;
+ QTest::newRow("Texture: rgb24 -1024x-768")
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_RGB24
+ << QSize(-1024, -768)
+ << false
+ << false;
+ QTest::newRow("Texture: YUV420P 640x480")
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_YUV420P
+ << QSize(640, 480)
+ << false
+ << false;
+ QTest::newRow("Texture: YUV420P 640x-480")
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_YUV420P
+ << QSize(640, -480)
+ << false
+ << false;
+ QTest::newRow("User Buffer: rgb32 256x256")
+ << QAbstractVideoBuffer::UserHandle
+ << QVideoFrame::Format_RGB32
+ << QSize(256, 256)
+ << false
+ << false;
+#if !defined(Q_OS_MAC)
+ QTest::newRow("Pixmap: rgb32 640x480")
+ << QAbstractVideoBuffer::QPixmapHandle
+ << QVideoFrame::Format_RGB32
+ << QSize(640, 480)
+ << true
+ << true;
+ QTest::newRow("Pixmap: YUV420P 640x480")
+ << QAbstractVideoBuffer::QPixmapHandle
+ << QVideoFrame::Format_YUV420P
+ << QSize(640, 480)
+ << false
+ << true;
+#endif
+}
+
+void tst_QPainterVideoSurface::supportedFormat()
+{
+ QFETCH(QAbstractVideoBuffer::HandleType, handleType);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormat);
+ QFETCH(QSize, frameSize);
+ QFETCH(bool, supportedPixelFormat);
+ QFETCH(bool, supportedFormat);
+
+ QPainterVideoSurface surface;
+
+ const QList<QVideoFrame::PixelFormat> pixelFormats = surface.supportedPixelFormats(handleType);
+
+ QCOMPARE(pixelFormats.contains(pixelFormat), QBool(supportedPixelFormat));
+
+ QVideoSurfaceFormat format(frameSize, pixelFormat, handleType);
+
+ QCOMPARE(surface.isFormatSupported(format), supportedFormat);
+ QCOMPARE(surface.start(format), supportedFormat);
+}
+
+void tst_QPainterVideoSurface::present_data()
+{
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormatA");
+ QTest::addColumn<QSize>("frameSizeA");
+ QTest::addColumn<const uchar *>("frameDataA");
+ QTest::addColumn<int>("bytesA");
+ QTest::addColumn<int>("bytesPerLineA");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormatB");
+ QTest::addColumn<QSize>("frameSizeB");
+ QTest::addColumn<const uchar *>("frameDataB");
+ QTest::addColumn<int>("bytesB");
+ QTest::addColumn<int>("bytesPerLineB");
+
+ QTest::newRow("rgb32 -> argb32")
+ << QVideoFrame::Format_RGB32
+ << QSize(2, 2)
+ << static_cast<const uchar *>(rgb32ImageData)
+ << int(sizeof(rgb32ImageData))
+ << 8
+ << QVideoFrame::Format_ARGB32
+ << QSize(2, 2)
+ << static_cast<const uchar *>(argb32ImageData)
+ << int(sizeof(argb32ImageData))
+ << 8;
+
+#ifndef QT_OPENGL_ES
+ QTest::newRow("rgb32 -> rgb24")
+ << QVideoFrame::Format_RGB32
+ << QSize(2, 2)
+ << static_cast<const uchar *>(rgb32ImageData)
+ << int(sizeof(rgb32ImageData))
+ << 8
+ << QVideoFrame::Format_RGB24
+ << QSize(2, 2)
+ << static_cast<const uchar *>(rgb24ImageData)
+ << int(sizeof(rgb24ImageData))
+ << 8;
+#endif
+
+ QTest::newRow("rgb32 -> rgb565")
+ << QVideoFrame::Format_RGB32
+ << QSize(2, 2)
+ << static_cast<const uchar *>(rgb32ImageData)
+ << int(sizeof(rgb32ImageData))
+ << 8
+ << QVideoFrame::Format_RGB565
+ << QSize(2, 2)
+ << static_cast<const uchar *>(rgb565ImageData)
+ << int(sizeof(rgb565ImageData))
+ << 4;
+
+#ifndef QT_OPENGL_ES
+ QTest::newRow("rgb24 -> rgb565")
+ << QVideoFrame::Format_RGB24
+ << QSize(2, 2)
+ << static_cast<const uchar *>(rgb24ImageData)
+ << int(sizeof(rgb24ImageData))
+ << 8
+ << QVideoFrame::Format_RGB565
+ << QSize(2, 2)
+ << static_cast<const uchar *>(rgb565ImageData)
+ << int(sizeof(rgb565ImageData))
+ << 4;
+#endif
+}
+
+void tst_QPainterVideoSurface::present()
+{
+ QFETCH(QVideoFrame::PixelFormat, pixelFormatA);
+ QFETCH(QSize, frameSizeA);
+ QFETCH(const uchar *, frameDataA);
+ QFETCH(int, bytesA);
+ QFETCH(int, bytesPerLineA);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormatB);
+ QFETCH(QSize, frameSizeB);
+ QFETCH(const uchar *, frameDataB);
+ QFETCH(int, bytesB);
+ QFETCH(int, bytesPerLineB);
+
+ QPainterVideoSurface surface;
+
+ QImage image(320, 240, QImage::Format_RGB32);
+
+ QSignalSpy frameSpy(&surface, SIGNAL(frameChanged()));
+
+ const QList<QVideoFrame::PixelFormat> pixelFormats = surface.supportedPixelFormats();
+
+ { // Test painting before started.
+ QPainter painter(&image);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+
+ QVideoSurfaceFormat formatA(frameSizeA, pixelFormatA);
+
+ QVERIFY(surface.start(formatA));
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), true);
+
+ { // Test painting before receiving a frame.
+ QPainter painter(&image);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+ QCOMPARE(surface.error(), QAbstractVideoSurface::NoError);
+
+ QVideoFrame frameA(bytesA, frameSizeA, bytesPerLineA, pixelFormatA);
+
+ frameA.map(QAbstractVideoBuffer::WriteOnly);
+ memcpy(frameA.bits(), frameDataA, frameA.mappedBytes());
+ frameA.unmap();
+
+ QVERIFY(surface.present(frameA));
+ QCOMPARE(surface.isReady(), false);
+ QCOMPARE(frameSpy.count(), 1);
+
+ {
+ QPainter painter(&image);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), false);
+
+ { // Test repainting before receiving another frame.
+ QPainter painter(&image);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), false);
+
+ // Not ready.
+ QVERIFY(!surface.present(frameA));
+ QCOMPARE(frameSpy.count(), 1);
+
+ surface.setReady(true);
+ QCOMPARE(surface.isReady(), true);
+ QVERIFY(surface.present(frameA));
+ QCOMPARE(frameSpy.count(), 2);
+
+ // Try switching to a different format after starting.
+ QVideoSurfaceFormat formatB(frameSizeB, pixelFormatB);
+
+ QVERIFY(surface.start(formatB));
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), true);
+
+ QVideoFrame frameB(bytesB, frameSizeB, bytesPerLineB, pixelFormatB);
+
+ frameB.map(QAbstractVideoBuffer::WriteOnly);
+ memcpy(frameB.bits(), frameDataB, frameB.mappedBytes());
+ frameB.unmap();
+
+ QVERIFY(surface.present(frameB));
+ QCOMPARE(surface.isReady(), false);
+ QCOMPARE(frameSpy.count(), 3);
+
+ {
+ QPainter painter(&image);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+ QVERIFY(surface.isActive());
+
+ surface.stop();
+
+ QCOMPARE(surface.isActive(), false);
+ QCOMPARE(surface.isReady(), false);
+
+ // Try presenting a frame while stopped.
+ QVERIFY(!surface.present(frameB));
+ QCOMPARE(surface.isReady(), false);
+ QCOMPARE(surface.error(), QAbstractVideoSurface::StoppedError);
+
+ // Try presenting a frame with a different format.
+ QVERIFY(surface.start(formatB));
+ QVERIFY(!surface.present(frameA));
+ QCOMPARE(surface.isActive(), false);
+ QCOMPARE(surface.isReady(), false);
+ QCOMPARE(surface.error(), QAbstractVideoSurface::IncorrectFormatError);
+}
+
+void tst_QPainterVideoSurface::presentOpaqueFrame()
+{
+ QPainterVideoSurface surface;
+
+ QImage image(320, 240, QImage::Format_RGB32);
+
+ QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32);
+
+ QVERIFY(surface.start(format));
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), true);
+
+ QVideoFrame frame(new QtTestOpaqueVideoBuffer, QSize(64, 64), QVideoFrame::Format_RGB32);
+
+ if (surface.present(frame)) {
+ QPainter painter(&image);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+
+ QCOMPARE(surface.isActive(), false);
+ QCOMPARE(surface.isReady(), false);
+ QCOMPARE(surface.error(), QAbstractVideoSurface::IncorrectFormatError);
+}
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+
+void tst_QPainterVideoSurface::shaderType()
+{
+ QPainterVideoSurface surface;
+ QGLWidget widget;
+ widget.makeCurrent();
+
+ QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders);
+ QCOMPARE(surface.supportedShaderTypes(), QPainterVideoSurface::NoShaders);
+
+ surface.setGLContext(const_cast<QGLContext *>(widget.context()));
+ QCOMPARE(surface.glContext(), widget.context());
+
+ {
+ QSignalSpy spy(&surface, SIGNAL(supportedFormatsChanged()));
+
+ surface.setShaderType(QPainterVideoSurface::NoShaders);
+ QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders);
+ QCOMPARE(spy.count(), 0);
+ }
+
+#ifndef QT_OPENGL_ES
+ if (surface.supportedShaderTypes() & QPainterVideoSurface::FragmentProgramShader) {
+ QSignalSpy spy(&surface, SIGNAL(supportedFormatsChanged()));
+
+ surface.setShaderType(QPainterVideoSurface::FragmentProgramShader);
+ QCOMPARE(surface.shaderType(), QPainterVideoSurface::FragmentProgramShader);
+ QCOMPARE(spy.count(), 1);
+
+ surface.setShaderType(QPainterVideoSurface::FragmentProgramShader);
+ QCOMPARE(surface.shaderType(), QPainterVideoSurface::FragmentProgramShader);
+ QCOMPARE(spy.count(), 1);
+ }
+#endif
+
+ if (surface.supportedShaderTypes() & QPainterVideoSurface::GlslShader) {
+ QSignalSpy spy(&surface, SIGNAL(supportedFormatsChanged()));
+
+ surface.setShaderType(QPainterVideoSurface::GlslShader);
+ QCOMPARE(surface.shaderType(), QPainterVideoSurface::GlslShader);
+ QCOMPARE(spy.count(), 1);
+
+ surface.setShaderType(QPainterVideoSurface::GlslShader);
+ QCOMPARE(surface.shaderType(), QPainterVideoSurface::GlslShader);
+ QCOMPARE(spy.count(), 1);
+ }
+
+ {
+ QSignalSpy spy(&surface, SIGNAL(supportedFormatsChanged()));
+
+ surface.setGLContext(const_cast<QGLContext *>(widget.context()));
+ QCOMPARE(surface.glContext(), widget.context());
+ QCOMPARE(spy.count(), 0);
+ }
+
+ surface.setGLContext(0);
+ QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders);
+ QCOMPARE(surface.supportedShaderTypes(), QPainterVideoSurface::NoShaders);
+
+ {
+ QSignalSpy spy(&surface, SIGNAL(supportedFormatsChanged()));
+
+ surface.setShaderType(QPainterVideoSurface::NoShaders);
+ QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders);
+ QCOMPARE(spy.count(), 0);
+
+#ifndef QT_OPENGL_ES
+ surface.setShaderType(QPainterVideoSurface::FragmentProgramShader);
+ QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders);
+ QCOMPARE(spy.count(), 0);
+#endif
+
+ surface.setShaderType(QPainterVideoSurface::GlslShader);
+ QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders);
+ QCOMPARE(spy.count(), 0);
+ }
+}
+
+void tst_QPainterVideoSurface::shaderTypeStarted_data()
+{
+ QTest::addColumn<QPainterVideoSurface::ShaderType>("shaderType");
+
+#ifndef QT_OPENGL_ES
+ QTest::newRow("ARBfp")
+ << QPainterVideoSurface::FragmentProgramShader;
+#endif
+ QTest::newRow("GLSL")
+ << QPainterVideoSurface::GlslShader;
+}
+
+void tst_QPainterVideoSurface::shaderTypeStarted()
+{
+ QFETCH(QPainterVideoSurface::ShaderType, shaderType);
+
+ QGLWidget widget;
+ widget.makeCurrent();
+
+ QPainterVideoSurface surface;
+
+ surface.setGLContext(const_cast<QGLContext *>(widget.context()));
+
+ if (!(surface.supportedShaderTypes() & shaderType))
+ QSKIP("Shader type unsupported on this platform", SkipSingle);
+
+ surface.setShaderType(shaderType);
+ QCOMPARE(surface.shaderType(), shaderType);
+
+ QVERIFY(surface.start(QVideoSurfaceFormat(QSize(640, 480), QVideoFrame::Format_RGB32)));
+ {
+ QSignalSpy spy(&surface, SIGNAL(activeChanged(bool)));
+
+ surface.setShaderType(QPainterVideoSurface::NoShaders);
+ QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders);
+ QCOMPARE(surface.isActive(), false);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.last().value(0).toBool(), false);
+ }
+
+ QVERIFY(surface.start(QVideoSurfaceFormat(QSize(640, 480), QVideoFrame::Format_RGB32)));
+ {
+ QSignalSpy spy(&surface, SIGNAL(activeChanged(bool)));
+
+ surface.setShaderType(QPainterVideoSurface::NoShaders);
+ QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders);
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(spy.count(), 0);
+
+ surface.setShaderType(shaderType);
+ QCOMPARE(surface.shaderType(), shaderType);
+ QCOMPARE(surface.isActive(), false);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.last().value(0).toBool(), false);
+ }
+
+ QVERIFY(surface.start(QVideoSurfaceFormat(QSize(640, 480), QVideoFrame::Format_RGB32)));
+ {
+ QSignalSpy spy(&surface, SIGNAL(activeChanged(bool)));
+
+ surface.setShaderType(shaderType);
+ QCOMPARE(surface.shaderType(), shaderType);
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(spy.count(), 0);
+
+ surface.setGLContext(0);
+ QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders);
+ QCOMPARE(surface.isActive(), false);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.last().value(0).toBool(), false);
+ }
+}
+
+void tst_QPainterVideoSurface::shaderSupportedFormat_data()
+{
+ QTest::addColumn<QPainterVideoSurface::ShaderType>("shaderType");
+ QTest::addColumn<QAbstractVideoBuffer::HandleType>("handleType");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormat");
+ QTest::addColumn<QSize>("frameSize");
+ QTest::addColumn<bool>("supportedPixelFormat");
+ QTest::addColumn<bool>("supportedFormat");
+
+ QList<QPair<QPainterVideoSurface::ShaderType, QByteArray> > types;
+
+
+#ifndef QT_OPENGL_ES
+ types << qMakePair(QPainterVideoSurface::FragmentProgramShader, QByteArray("ARBfp: "));
+#endif
+ types << qMakePair(QPainterVideoSurface::GlslShader, QByteArray("GLSL: "));
+
+ QPair<QPainterVideoSurface::ShaderType, QByteArray> type;
+ foreach (type, types) {
+ QTest::newRow((type.second + "rgb32 640x480").constData())
+ << type.first
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_RGB32
+ << QSize(640, 480)
+ << true
+ << true;
+ QTest::newRow((type.second + "rgb32 -640x480").constData())
+ << type.first
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_RGB32
+ << QSize(-640, 480)
+ << true
+ << false;
+ QTest::newRow((type.second + "rgb565 32x32").constData())
+ << type.first
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_RGB565
+ << QSize(32, 32)
+ << true
+ << true;
+ QTest::newRow((type.second + "rgb565 0x0").constData())
+ << type.first
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_RGB565
+ << QSize(0, 0)
+ << true
+ << false;
+ QTest::newRow((type.second + "argb32 256x256").constData())
+ << type.first
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_ARGB32
+ << QSize(256, 256)
+ << true
+ << true;
+ QTest::newRow((type.second + "rgb24 1024x768").constData())
+ << type.first
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_RGB24
+ << QSize(1024, 768)
+#ifndef QT_OPENGL_ES
+ << true
+ << true;
+#else
+ << false
+ << false;
+#endif
+ QTest::newRow((type.second + "rgb24 -1024x-768").constData())
+ << type.first
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_RGB24
+ << QSize(-1024, -768)
+#ifndef QT_OPENGL_ES
+ << true
+#else
+ << false
+#endif
+ << false;
+#ifndef Q_WS_MAC
+ QTest::newRow((type.second + "YUV420P 640x480").constData())
+ << type.first
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_YUV420P
+ << QSize(640, 480)
+ << true
+ << true;
+ QTest::newRow((type.second + "YUV420P 640x-480").constData())
+ << type.first
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_YUV420P
+ << QSize(640, -480)
+ << true
+ << false;
+#endif
+ QTest::newRow((type.second + "Y8 640x480").constData())
+ << type.first
+ << QAbstractVideoBuffer::NoHandle
+ << QVideoFrame::Format_Y8
+ << QSize(640, 480)
+ << false
+ << false;
+ QTest::newRow((type.second + "Texture: rgb32 640x480").constData())
+ << type.first
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_RGB32
+ << QSize(640, 480)
+ << true
+ << true;
+ QTest::newRow((type.second + "Texture: rgb32 -640x480").constData())
+ << type.first
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_RGB32
+ << QSize(-640, 480)
+ << true
+ << false;
+#ifndef Q_WS_MAC
+ QTest::newRow((type.second + "Texture: rgb565 32x32").constData())
+ << type.first
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_RGB565
+ << QSize(32, 32)
+ << false
+ << false;
+ QTest::newRow((type.second + "Texture: rgb565 0x0").constData())
+ << type.first
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_RGB565
+ << QSize(0, 0)
+ << false
+ << false;
+#endif
+ QTest::newRow((type.second + "Texture argb32 256x256").constData())
+ << type.first
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_ARGB32
+ << QSize(256, 256)
+ << true
+ << true;
+#ifndef Q_WS_MAC
+ QTest::newRow((type.second + "Texture: rgb24 1024x768").constData())
+ << type.first
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_RGB24
+ << QSize(1024, 768)
+ << false
+ << false;
+ QTest::newRow((type.second + "Texture: rgb24 -1024x-768").constData())
+ << type.first
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_RGB24
+ << QSize(-1024, -768)
+ << false
+ << false;
+ QTest::newRow((type.second + "Texture: YUV420P 640x480").constData())
+ << type.first
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_YUV420P
+ << QSize(640, 480)
+ << false
+ << false;
+ QTest::newRow((type.second + "Texture: YUV420P 640x-480").constData())
+ << type.first
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QVideoFrame::Format_YUV420P
+ << QSize(640, -480)
+ << false
+ << false;
+#endif
+ QTest::newRow(type.second + "User Buffer: rgb32 256x256")
+ << type.first
+ << QAbstractVideoBuffer::UserHandle
+ << QVideoFrame::Format_RGB32
+ << QSize(256, 256)
+ << false
+ << false;
+ }
+}
+
+void tst_QPainterVideoSurface::shaderSupportedFormat()
+{
+ QFETCH(QPainterVideoSurface::ShaderType, shaderType);
+ QFETCH(QAbstractVideoBuffer::HandleType, handleType);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormat);
+ QFETCH(QSize, frameSize);
+ QFETCH(bool, supportedPixelFormat);
+ QFETCH(bool, supportedFormat);
+
+ QGLWidget widget;
+ widget.makeCurrent();
+
+ QPainterVideoSurface surface;
+ surface.setGLContext(const_cast<QGLContext *>(widget.context()));
+
+
+ if (!(surface.supportedShaderTypes() & shaderType))
+ QSKIP("Shader type not supported on this platform", SkipSingle);
+
+ surface.setShaderType(shaderType);
+ if (surface.shaderType() != shaderType)
+ QSKIP("Shader type couldn't be set", SkipSingle);
+
+ const QList<QVideoFrame::PixelFormat> pixelFormats = surface.supportedPixelFormats(handleType);
+
+ QCOMPARE(pixelFormats.contains(pixelFormat), QBool(supportedPixelFormat));
+
+ QVideoSurfaceFormat format(frameSize, pixelFormat, handleType);
+
+ QCOMPARE(surface.isFormatSupported(format), supportedFormat);
+ QCOMPARE(surface.start(format), supportedFormat);
+}
+
+void tst_QPainterVideoSurface::shaderPresent_data()
+{
+ QTest::addColumn<QPainterVideoSurface::ShaderType>("shaderType");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormatA");
+ QTest::addColumn<QSize>("frameSizeA");
+ QTest::addColumn<const uchar *>("frameDataA");
+ QTest::addColumn<int>("bytesA");
+ QTest::addColumn<int>("bytesPerLineA");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormatB");
+ QTest::addColumn<QSize>("frameSizeB");
+ QTest::addColumn<const uchar *>("frameDataB");
+ QTest::addColumn<int>("bytesB");
+ QTest::addColumn<int>("bytesPerLineB");
+
+ QList<QPair<QPainterVideoSurface::ShaderType, QByteArray> > types;
+#ifndef QT_OPENGL_ES
+ types << qMakePair(QPainterVideoSurface::FragmentProgramShader, QByteArray("ARBfp: "));
+#endif
+ types << qMakePair(QPainterVideoSurface::GlslShader, QByteArray("GLSL: "));
+
+ QPair<QPainterVideoSurface::ShaderType, QByteArray> type;
+ foreach (type, types) {
+ QTest::newRow((type.second + "rgb32 -> argb32").constData())
+ << type.first
+ << QVideoFrame::Format_RGB32
+ << QSize(2, 2)
+ << static_cast<const uchar *>(rgb32ImageData)
+ << int(sizeof(rgb32ImageData))
+ << 8
+ << QVideoFrame::Format_ARGB32
+ << QSize(2, 2)
+ << static_cast<const uchar *>(argb32ImageData)
+ << int(sizeof(argb32ImageData))
+ << 8;
+
+ QTest::newRow((type.second + "rgb32 -> rgb565").constData())
+ << type.first
+ << QVideoFrame::Format_RGB32
+ << QSize(2, 2)
+ << static_cast<const uchar *>(rgb32ImageData)
+ << int(sizeof(rgb32ImageData))
+ << 8
+ << QVideoFrame::Format_RGB565
+ << QSize(2, 2)
+ << static_cast<const uchar *>(rgb565ImageData)
+ << int(sizeof(rgb565ImageData))
+ << 4;
+#ifndef Q_WS_MAC
+ QTest::newRow((type.second + "rgb32 -> yuv420p").constData())
+ << type.first
+ << QVideoFrame::Format_RGB32
+ << QSize(2, 2)
+ << static_cast<const uchar *>(rgb32ImageData)
+ << int(sizeof(rgb32ImageData))
+ << 8
+ << QVideoFrame::Format_YUV420P
+ << QSize(8, 8)
+ << static_cast<const uchar *>(yuvPlanarImageData)
+ << int(sizeof(yuvPlanarImageData))
+ << 8;
+
+ QTest::newRow((type.second + "yv12 -> rgb32").constData())
+ << type.first
+ << QVideoFrame::Format_YV12
+ << QSize(8, 8)
+ << static_cast<const uchar *>(yuvPlanarImageData)
+ << int(sizeof(yuvPlanarImageData))
+ << 8
+ << QVideoFrame::Format_RGB32
+ << QSize(2, 2)
+ << static_cast<const uchar *>(rgb32ImageData)
+ << int(sizeof(rgb32ImageData))
+ << 8;
+#endif
+ }
+}
+
+void tst_QPainterVideoSurface::shaderPresent()
+{
+ QFETCH(QPainterVideoSurface::ShaderType, shaderType);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormatA);
+ QFETCH(QSize, frameSizeA);
+ QFETCH(const uchar *, frameDataA);
+ QFETCH(int, bytesA);
+ QFETCH(int, bytesPerLineA);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormatB);
+ QFETCH(QSize, frameSizeB);
+ QFETCH(const uchar *, frameDataB);
+ QFETCH(int, bytesB);
+ QFETCH(int, bytesPerLineB);
+
+ QGLWidget widget;
+ widget.makeCurrent();
+
+ QPainterVideoSurface surface;
+ surface.setGLContext(const_cast<QGLContext *>(widget.context()));
+
+ if (!(surface.supportedShaderTypes() & shaderType))
+ QSKIP("Shader type unsupported on this platform", SkipSingle);
+
+ surface.setShaderType(shaderType);
+ if (surface.shaderType() != shaderType)
+ QSKIP("Shader type couldn't be set", SkipSingle);
+
+ QSignalSpy frameSpy(&surface, SIGNAL(frameChanged()));
+
+ { // Test painting before starting the surface.
+ QPainter painter(&widget);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+ QCOMPARE(surface.error(), QAbstractVideoSurface::NoError);
+
+ QVideoSurfaceFormat formatA(frameSizeA, pixelFormatA);
+
+ QVERIFY(surface.start(formatA));
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), true);
+
+ // Test painting before receiving a frame.
+ {
+ QPainter painter(&widget);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), true);
+
+ QVideoFrame frameA(bytesA, frameSizeA, bytesPerLineA, pixelFormatA);
+
+ frameA.map(QAbstractVideoBuffer::WriteOnly);
+ memcpy(frameA.bits(), frameDataA, frameA.mappedBytes());
+ frameA.unmap();
+
+ QVERIFY(surface.present(frameA));
+ QCOMPARE(surface.isReady(), false);
+ QCOMPARE(frameSpy.count(), 1);
+
+ {
+ QPainter painter(&widget);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), false);
+
+ { // Test repainting before receiving another frame.
+ QPainter painter(&widget);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), false);
+
+ // Not ready.
+ QVERIFY(!surface.present(frameA));
+ QCOMPARE(frameSpy.count(), 1);
+
+ surface.setReady(true);
+ QCOMPARE(surface.isReady(), true);
+ QVERIFY(surface.present(frameA));
+ QCOMPARE(frameSpy.count(), 2);
+
+ // Try switching to a different format after starting.
+ QVideoSurfaceFormat formatB(frameSizeB, pixelFormatB);
+
+ QVERIFY(surface.start(formatB));
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), true);
+
+ QVideoFrame frameB(bytesB, frameSizeB, bytesPerLineB, pixelFormatB);
+
+ frameB.map(QAbstractVideoBuffer::WriteOnly);
+ memcpy(frameB.bits(), frameDataB, frameB.mappedBytes());
+ frameB.unmap();
+
+ QVERIFY(surface.present(frameB));
+ QCOMPARE(surface.isReady(), false);
+ QCOMPARE(frameSpy.count(), 3);
+
+ {
+ QPainter painter(&widget);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+ QCOMPARE(surface.isActive(), true);
+
+ surface.stop();
+ QCOMPARE(surface.isActive(), false);
+ QCOMPARE(surface.isReady(), false);
+
+ // Try presenting a frame while stopped.
+ QVERIFY(!surface.present(frameB));
+ QCOMPARE(surface.isReady(), false);
+ QCOMPARE(surface.error(), QAbstractVideoSurface::StoppedError);
+
+ // Try stopping while already stopped.
+ surface.stop();
+ QCOMPARE(surface.isActive(), false);
+ QCOMPARE(surface.isReady(), false);
+
+ // Try presenting a frame with a different format.
+ QVERIFY(surface.start(formatB));
+ QVERIFY(!surface.present(frameA));
+ QCOMPARE(surface.isActive(), false);
+ QCOMPARE(surface.isReady(), false);
+ QCOMPARE(surface.error(), QAbstractVideoSurface::IncorrectFormatError);
+}
+
+void tst_QPainterVideoSurface::shaderPresentOpaqueFrame_data()
+{
+ QTest::addColumn<QPainterVideoSurface::ShaderType>("shaderType");
+
+#ifndef QT_OPENGL_ES
+ QTest::newRow("ARBfp")
+ << QPainterVideoSurface::FragmentProgramShader;
+#endif
+ QTest::newRow("GLSL")
+ << QPainterVideoSurface::GlslShader;
+}
+
+void tst_QPainterVideoSurface::shaderPresentOpaqueFrame()
+{
+ QFETCH(QPainterVideoSurface::ShaderType, shaderType);
+
+ QGLWidget widget;
+ widget.makeCurrent();
+
+ QPainterVideoSurface surface;
+ surface.setGLContext(const_cast<QGLContext *>(widget.context()));
+
+ if (!(surface.supportedShaderTypes() & shaderType))
+ QSKIP("Shader type unsupported on this platform", SkipSingle);
+
+ surface.setShaderType(shaderType);
+ if (surface.shaderType() != shaderType)
+ QSKIP("Shader type couldn't be set", SkipSingle);
+
+ QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32);
+
+ QVERIFY(surface.start(format));
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), true);
+
+ QVideoFrame frame(new QtTestOpaqueVideoBuffer, QSize(64, 64), QVideoFrame::Format_RGB32);
+
+ if (surface.present(frame)) {
+ QPainter painter(&widget);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+
+ QCOMPARE(surface.isActive(), false);
+ QCOMPARE(surface.isReady(), false);
+ QCOMPARE(surface.error(), QAbstractVideoSurface::IncorrectFormatError);
+}
+
+void tst_QPainterVideoSurface::shaderPresentGLFrame_data()
+{
+ QTest::addColumn<QPainterVideoSurface::ShaderType>("shaderType");
+
+#ifndef QT_OPENGL_ES
+ QTest::newRow("ARBfp")
+ << QPainterVideoSurface::FragmentProgramShader;
+#endif
+ QTest::newRow("GLSL")
+ << QPainterVideoSurface::GlslShader;
+}
+
+void tst_QPainterVideoSurface::shaderPresentGLFrame()
+{
+ QFETCH(QPainterVideoSurface::ShaderType, shaderType);
+
+ QGLWidget widget;
+ widget.makeCurrent();
+
+ QPainterVideoSurface surface;
+ surface.setGLContext(const_cast<QGLContext *>(widget.context()));
+
+ if (!(surface.supportedShaderTypes() & shaderType))
+ QSKIP("Shader type unsupported on this platform", SkipSingle);
+
+ surface.setShaderType(shaderType);
+ if (surface.shaderType() != shaderType)
+ QSKIP("Shader type couldn't be set", SkipSingle);
+
+ QVideoSurfaceFormat format(
+ QSize(2, 2), QVideoFrame::Format_RGB32, QAbstractVideoBuffer::GLTextureHandle);
+
+ QVERIFY(surface.start(format));
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), true);
+
+ QtTestGLVideoBuffer *buffer = new QtTestGLVideoBuffer;
+
+ glBindTexture(GL_TEXTURE_2D, buffer->textureId());
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb32ImageData);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ QVideoFrame frame(buffer, QSize(2, 2), QVideoFrame::Format_RGB32);
+
+ QVERIFY(surface.present(frame));
+
+ {
+ QPainter painter(&widget);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), false);
+
+ {
+ QPainter painter(&widget);
+ surface.paint(&painter, QRect(0, 0, 320, 240));
+ }
+
+ QCOMPARE(surface.isActive(), true);
+ QCOMPARE(surface.isReady(), false);
+}
+
+#endif
+
+QTEST_MAIN(tst_QPainterVideoSurface)
+
+#include "tst_qpaintervideosurface.moc"
diff --git a/tests/auto/qradiotuner/main.cpp b/tests/auto/qradiotuner/main.cpp
new file mode 100755
index 000000000..f161c8fd6
--- /dev/null
+++ b/tests/auto/qradiotuner/main.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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.h>
+#include <QtTest/QtTest>
+
+#include "tst_qradiotuner.h"
+
+#ifdef Q_OS_SYMBIAN
+#include "tst_qradiotuner_xa.h"
+#include "tst_qradiotuner_s60.h"
+#endif
+
+int main(int argc, char**argv)
+{
+ QApplication app(argc,argv);
+ int ret;
+ tst_QRadioTuner test_api;
+ ret = QTest::qExec(&test_api, argc, argv);
+#ifdef Q_OS_SYMBIAN
+ char *new_argv[3];
+ QString str = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_xa.log";
+ QByteArray bytes = str.toAscii();
+ char arg1[] = "-o";
+ new_argv[0] = argv[0];
+ new_argv[1] = arg1;
+ new_argv[2] = bytes.data();
+ tst_QXARadio_xa test_xa;
+ ret = QTest::qExec(&test_xa, 3, new_argv);
+ char *new_argv1[3];
+ QString str1 = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_s60.log";
+ QByteArray bytes1 = str1.toAscii();
+ char arg2[] = "-o";
+ new_argv1[0] = argv[0];
+ new_argv1[1] = arg2;
+ new_argv1[2] = bytes1.data();
+ tst_QRadioTuner_s60 test_s60;
+ ret = QTest::qExec(&test_s60, 3, new_argv1);
+
+#endif
+ return ret;
+}
diff --git a/tests/auto/qradiotuner/qradiotuner.pro b/tests/auto/qradiotuner/qradiotuner.pro
new file mode 100644
index 000000000..b80043801
--- /dev/null
+++ b/tests/auto/qradiotuner/qradiotuner.pro
@@ -0,0 +1,19 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qradiotuner
+# CONFIG += testcase
+
+symbian {
+ HEADERS += tst_qradiotuner_xa.h
+ SOURCES += tst_qradiotuner_xa.cpp
+ TARGET.CAPABILITY = ALL -TCB
+ HEADERS += tst_qradiotuner_s60.h
+ SOURCES += tst_qradiotuner_s60.cpp
+
+}
+
+HEADERS += tst_qradiotuner.h
+SOURCES += main.cpp tst_qradiotuner.cpp
+
diff --git a/tests/auto/qradiotuner/tst_qradiotuner.cpp b/tests/auto/qradiotuner/tst_qradiotuner.cpp
new file mode 100644
index 000000000..647cd7775
--- /dev/null
+++ b/tests/auto/qradiotuner/tst_qradiotuner.cpp
@@ -0,0 +1,275 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include "tst_qradiotuner.h"
+
+QT_USE_NAMESPACE
+
+void tst_QRadioTuner::initTestCase()
+{
+ qRegisterMetaType<QRadioTuner::State>("QRadioTuner::State");
+ qRegisterMetaType<QRadioTuner::Band>("QRadioTuner::Band");
+
+ mock = new MockControl(this);
+ service = new MockService(this, mock);
+ provider = new MockProvider(service);
+ radio = new QRadioTuner(0,provider);
+ QVERIFY(radio->service() != 0);
+
+ QSignalSpy stateSpy(radio, SIGNAL(stateChanged(QRadioTuner::State)));
+
+ QCOMPARE(radio->state(), QRadioTuner::StoppedState);
+ radio->start();
+ QCOMPARE(radio->state(), QRadioTuner::ActiveState);
+
+ QCOMPARE(stateSpy.count(), 1);
+ QCOMPARE(stateSpy.first()[0].value<QRadioTuner::State>(), QRadioTuner::ActiveState);
+}
+
+void tst_QRadioTuner::cleanupTestCase()
+{
+ QVERIFY(radio->error() == QRadioTuner::NoError);
+ QVERIFY(radio->errorString().isEmpty());
+
+ QSignalSpy stateSpy(radio, SIGNAL(stateChanged(QRadioTuner::State)));
+
+ radio->stop();
+ QCOMPARE(radio->state(), QRadioTuner::StoppedState);
+ QCOMPARE(stateSpy.count(), 1);
+
+ QCOMPARE(stateSpy.first()[0].value<QRadioTuner::State>(), QRadioTuner::StoppedState);
+
+ delete radio;
+ delete service;
+ delete provider;
+}
+
+void tst_QRadioTuner::testNullService()
+{
+ const QPair<int, int> nullRange(0, 0);
+
+ MockProvider provider(0);
+ QRadioTuner radio(0, &provider);
+
+ radio.start();
+ QCOMPARE(radio.error(), QRadioTuner::ResourceError);
+ QCOMPARE(radio.errorString(), QString());
+ QCOMPARE(radio.band(), QRadioTuner::FM);
+ QCOMPARE(radio.isBandSupported(QRadioTuner::AM), false);
+ QCOMPARE(radio.isBandSupported(QRadioTuner::FM), false);
+ QCOMPARE(radio.frequency(), 0);
+ QCOMPARE(radio.frequencyStep(QRadioTuner::AM), 0);
+ QCOMPARE(radio.frequencyStep(QRadioTuner::FM), 0);
+ QCOMPARE(radio.frequencyRange(QRadioTuner::AM), nullRange);
+ QCOMPARE(radio.frequencyRange(QRadioTuner::FM), nullRange);
+ QCOMPARE(radio.isStereo(), false);
+ QCOMPARE(radio.stereoMode(), QRadioTuner::Auto);
+ QCOMPARE(radio.signalStrength(), 0);
+ QCOMPARE(radio.volume(), 0);
+ QCOMPARE(radio.isMuted(), false);
+ QCOMPARE(radio.isSearching(), false);
+ radio.stop();
+}
+
+void tst_QRadioTuner::testNullControl()
+{
+ const QPair<int, int> nullRange(0, 0);
+
+ MockService service(0, 0);
+ MockProvider provider(&service);
+ QRadioTuner radio(0, &provider);
+
+ radio.start();
+
+ QCOMPARE(radio.error(), QRadioTuner::ResourceError);
+ QCOMPARE(radio.errorString(), QString());
+
+ QCOMPARE(radio.band(), QRadioTuner::FM);
+ QCOMPARE(radio.isBandSupported(QRadioTuner::AM), false);
+ QCOMPARE(radio.isBandSupported(QRadioTuner::FM), false);
+ QCOMPARE(radio.frequency(), 0);
+ QCOMPARE(radio.frequencyStep(QRadioTuner::AM), 0);
+ QCOMPARE(radio.frequencyStep(QRadioTuner::FM), 0);
+ QCOMPARE(radio.frequencyRange(QRadioTuner::AM), nullRange);
+ QCOMPARE(radio.frequencyRange(QRadioTuner::FM), nullRange);
+ {
+ QSignalSpy bandSpy(&radio, SIGNAL(bandChanged(QRadioTuner::Band)));
+ QSignalSpy frequencySpy(&radio, SIGNAL(frequencyChanged(int)));
+
+ radio.setFrequency(107500);
+ QCOMPARE(radio.band(), QRadioTuner::FM);
+ QCOMPARE(radio.frequency(), 0);
+ QCOMPARE(bandSpy.count(), 0);
+ QCOMPARE(frequencySpy.count(), 0);
+
+ radio.setBand(QRadioTuner::AM);
+ QCOMPARE(radio.band(), QRadioTuner::FM);
+ QCOMPARE(radio.frequency(), 0);
+ QCOMPARE(bandSpy.count(), 0);
+ QCOMPARE(frequencySpy.count(), 0);
+ }
+ QCOMPARE(radio.isStereo(), false);
+ QCOMPARE(radio.stereoMode(), QRadioTuner::Auto);
+
+ radio.setStereoMode(QRadioTuner::ForceStereo);
+ QCOMPARE(radio.stereoMode(), QRadioTuner::Auto);
+
+ QCOMPARE(radio.signalStrength(), 0);
+
+ QCOMPARE(radio.volume(), 0);
+ QCOMPARE(radio.isMuted(), false);
+ {
+ QSignalSpy volumeSpy(&radio, SIGNAL(volumeChanged(int)));
+ QSignalSpy muteSpy(&radio, SIGNAL(mutedChanged(bool)));
+
+ radio.setVolume(76);
+ QCOMPARE(radio.volume(), 0);
+ QCOMPARE(volumeSpy.count(), 0);
+
+ radio.setMuted(true);
+ QCOMPARE(radio.isMuted(), false);
+ QCOMPARE(muteSpy.count(), 0);
+ }
+ QCOMPARE(radio.isSearching(), false);
+ {
+ QSignalSpy spy(&radio, SIGNAL(searchingChanged(bool)));
+
+ radio.searchBackward();
+ QCOMPARE(radio.isSearching(), false);
+ QCOMPARE(spy.count(), 0);
+
+ radio.searchForward();
+ QCOMPARE(radio.isSearching(), false);
+ QCOMPARE(spy.count(), 0);
+
+ radio.cancelSearch();
+ QCOMPARE(radio.isSearching(), false);
+ QCOMPARE(spy.count(), 0);
+ }
+
+ radio.stop();
+}
+
+void tst_QRadioTuner::testBand()
+{
+ QVERIFY(radio->isBandSupported(QRadioTuner::FM));
+ QVERIFY(!radio->isBandSupported(QRadioTuner::SW));
+
+ if(radio->isBandSupported(QRadioTuner::AM)) {
+ QSignalSpy readSignal(radio, SIGNAL(bandChanged(QRadioTuner::Band)));
+ radio->setBand(QRadioTuner::AM);
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(radio->band() == QRadioTuner::AM);
+ QVERIFY(readSignal.count() == 1);
+ }
+}
+
+void tst_QRadioTuner::testFrequency()
+{
+ QSignalSpy readSignal(radio, SIGNAL(frequencyChanged(int)));
+ radio->setFrequency(104500000);
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(radio->frequency() == 104500000);
+ QVERIFY(readSignal.count() == 1);
+
+ QVERIFY(radio->frequencyStep(QRadioTuner::FM) == 1);
+ QPair<int,int> test = radio->frequencyRange(QRadioTuner::FM);
+ QVERIFY(test.first == 1);
+ QVERIFY(test.second == 2);
+}
+
+void tst_QRadioTuner::testMute()
+{
+ QSignalSpy readSignal(radio, SIGNAL(mutedChanged(bool)));
+ radio->setMuted(true);
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(radio->isMuted());
+ QVERIFY(readSignal.count() == 1);
+}
+
+void tst_QRadioTuner::testSearch()
+{
+ QSignalSpy readSignal(radio, SIGNAL(searchingChanged(bool)));
+ QVERIFY(!radio->isSearching());
+
+ radio->searchForward();
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(radio->isSearching());
+ QVERIFY(readSignal.count() == 1);
+
+ radio->cancelSearch();
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(!radio->isSearching());
+ QVERIFY(readSignal.count() == 2);
+
+ radio->searchBackward();
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(radio->isSearching());
+ QVERIFY(readSignal.count() == 3);
+
+ radio->cancelSearch();
+ QVERIFY(!radio->isSearching());
+}
+
+void tst_QRadioTuner::testVolume()
+{
+ QVERIFY(radio->volume() == 100);
+ QSignalSpy readSignal(radio, SIGNAL(volumeChanged(int)));
+ radio->setVolume(50);
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(radio->volume() == 50);
+ QVERIFY(readSignal.count() == 1);
+}
+
+void tst_QRadioTuner::testSignal()
+{
+ QVERIFY(radio->signalStrength() == 0);
+ // There is no set of this only a get, do nothing else.
+}
+
+void tst_QRadioTuner::testStereo()
+{
+ QVERIFY(radio->isStereo());
+ radio->setStereoMode(QRadioTuner::ForceMono);
+ QVERIFY(radio->stereoMode() == QRadioTuner::ForceMono);
+}
diff --git a/tests/auto/qradiotuner/tst_qradiotuner.h b/tests/auto/qradiotuner/tst_qradiotuner.h
new file mode 100644
index 000000000..970036c08
--- /dev/null
+++ b/tests/auto/qradiotuner/tst_qradiotuner.h
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** 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 TST_QRADIOTUNER_H
+#define TST_QRADIOTUNER_H
+
+#include <QtTest/QtTest>
+#include <QDebug>
+#include <QTimer>
+
+#include <qmediaobject.h>
+#include <qmediacontrol.h>
+#include <qmediaservice.h>
+#include <qradiotunercontrol.h>
+#include <qradiotuner.h>
+
+QT_USE_NAMESPACE
+class MockControl : public QRadioTunerControl
+{
+ Q_OBJECT
+
+public:
+ MockControl(QObject *parent):
+ QRadioTunerControl(parent),
+ m_active(false),
+ m_searching(false),m_muted(false),m_stereo(true),
+ m_volume(100),m_signal(0),m_frequency(0),
+ m_band(QRadioTuner::FM) {}
+
+ QRadioTuner::State state() const
+ {
+ return m_active ? QRadioTuner::ActiveState : QRadioTuner::StoppedState;
+ }
+ bool isAvailable() const
+ {
+ return true;
+ }
+ QtMultimediaKit::AvailabilityError availabilityError() const
+ {
+ return QtMultimediaKit::NoError;
+ }
+
+ QRadioTuner::Band band() const
+ {
+ return m_band;
+ }
+
+ void setBand(QRadioTuner::Band b)
+ {
+ m_band = b;
+ emit bandChanged(m_band);
+ }
+
+ bool isBandSupported(QRadioTuner::Band b) const
+ {
+ if(b == QRadioTuner::FM || b == QRadioTuner::AM) return true;
+
+ return false;
+ }
+
+ int frequency() const
+ {
+ return m_frequency;
+ }
+
+ QPair<int,int> frequencyRange(QRadioTuner::Band) const
+ {
+ return qMakePair<int,int>(1,2);
+ }
+
+ int frequencyStep(QRadioTuner::Band) const
+ {
+ return 1;
+ }
+
+ void setFrequency(int frequency)
+ {
+ m_frequency = frequency;
+ emit frequencyChanged(m_frequency);
+ }
+
+ bool isStereo() const
+ {
+ return m_stereo;
+ }
+
+ void setStereo(bool stereo)
+ {
+ emit stereoStatusChanged(m_stereo = stereo);
+ }
+
+
+ QRadioTuner::StereoMode stereoMode() const
+ {
+ return m_stereoMode;
+ }
+
+ void setStereoMode(QRadioTuner::StereoMode mode)
+ {
+ m_stereoMode = mode;
+ }
+
+ QRadioTuner::Error error() const
+ {
+ return QRadioTuner::NoError;
+ }
+
+ QString errorString() const
+ {
+ return QString();
+ }
+
+ int signalStrength() const
+ {
+ return m_signal;
+ }
+
+ int volume() const
+ {
+ return m_volume;
+ }
+
+ void setVolume(int volume)
+ {
+ m_volume = volume;
+ emit volumeChanged(m_volume);
+ }
+
+ bool isMuted() const
+ {
+ return m_muted;
+ }
+
+ void setMuted(bool muted)
+ {
+ m_muted = muted;
+ emit mutedChanged(m_muted);
+ }
+
+ bool isSearching() const
+ {
+ return m_searching;
+ }
+
+ void searchForward()
+ {
+ m_searching = true;
+ emit searchingChanged(m_searching);
+ }
+
+ void searchBackward()
+ {
+ m_searching = true;
+ emit searchingChanged(m_searching);
+ }
+
+ void cancelSearch()
+ {
+ m_searching = false;
+ emit searchingChanged(m_searching);
+ }
+
+ void start()
+ {
+ if (!m_active) {
+ m_active = true;
+ emit stateChanged(state());
+ }
+ }
+
+ void stop()
+ {
+ if (m_active) {
+ m_active = false;
+ emit stateChanged(state());
+ }
+ }
+
+public:
+ bool m_active;
+ bool m_searching;
+ bool m_muted;
+ bool m_stereo;
+ int m_volume;
+ int m_signal;
+ int m_frequency;
+ QRadioTuner::StereoMode m_stereoMode;
+ QRadioTuner::Band m_band;
+};
+
+class MockService : public QMediaService
+{
+ Q_OBJECT
+public:
+ MockService(QObject *parent, QMediaControl *control):
+ QMediaService(parent),
+ mockControl(control) {}
+
+ QMediaControl* requestControl(const char *)
+ {
+ return mockControl;
+ }
+
+ void releaseControl(QMediaControl*) {}
+
+ QMediaControl *mockControl;
+};
+
+class MockProvider : public QMediaServiceProvider
+{
+public:
+ MockProvider(MockService *service):mockService(service) {}
+ QMediaService *requestService(const QByteArray &, const QMediaServiceProviderHint &)
+ {
+ return mockService;
+ }
+
+ void releaseService(QMediaService *) {}
+
+ MockService *mockService;
+};
+
+class tst_QRadioTuner: public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void testNullService();
+ void testNullControl();
+ void testBand();
+ void testFrequency();
+ void testMute();
+ void testSearch();
+ void testVolume();
+ void testSignal();
+ void testStereo();
+
+private:
+ MockControl *mock;
+ MockService *service;
+ MockProvider *provider;
+ QRadioTuner *radio;
+};
+#endif
diff --git a/tests/auto/qradiotuner/tst_qradiotuner_s60.cpp b/tests/auto/qradiotuner/tst_qradiotuner_s60.cpp
new file mode 100644
index 000000000..3c3de22da
--- /dev/null
+++ b/tests/auto/qradiotuner/tst_qradiotuner_s60.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include "tst_qradiotuner_s60.h"
+
+#define QTRY_COMPARE_S60(a,e) \
+ for (int _i = 0; _i < 5000; _i += 100) { \
+ if ((a) == (e)) break; \
+ QTest::qWait(100); \
+ }
+
+void tst_QRadioTuner_s60::initTestCase()
+{
+ qRegisterMetaType<QRadioTuner::State>("QRadioTuner::State");
+ qRegisterMetaType<QRadioTuner::Band>("QRadioTuner::Band");
+
+ radio = new QRadioTuner(0);
+ QVERIFY(radio->service() != 0);
+
+ QSignalSpy stateSpy(radio, SIGNAL(stateChanged(QRadioTuner::State)));
+
+ QCOMPARE(radio->state(), QRadioTuner::StoppedState);
+ radio->start();
+ //QCOMPARE(radio->state(), QRadioTuner::ActiveState);
+ QTRY_COMPARE_S60(radio->state(), QRadioTuner::ActiveState);
+
+ QCOMPARE(stateSpy.count(), 1);
+ QCOMPARE(stateSpy.first()[0].value<QRadioTuner::State>(), QRadioTuner::ActiveState);
+}
+
+void tst_QRadioTuner_s60::cleanupTestCase()
+{
+ QVERIFY(radio->error() == QRadioTuner::NoError);
+ QVERIFY(radio->errorString().isEmpty());
+
+ QSignalSpy stateSpy(radio, SIGNAL(stateChanged(QRadioTuner::State)));
+
+ radio->stop();
+ QTRY_COMPARE_S60(radio->state(), QRadioTuner::StoppedState);
+ QCOMPARE(stateSpy.count(), 1);
+
+ QCOMPARE(stateSpy.first()[0].value<QRadioTuner::State>(), QRadioTuner::StoppedState);
+
+ delete radio;
+}
+
+void tst_QRadioTuner_s60::testBand()
+{
+ QVERIFY(radio->isBandSupported(QRadioTuner::FM));
+ QVERIFY(!radio->isBandSupported(QRadioTuner::SW));
+
+ if(radio->isBandSupported(QRadioTuner::AM)) {
+ QSignalSpy readSignal(radio, SIGNAL(bandChanged(QRadioTuner::Band)));
+ radio->setBand(QRadioTuner::AM);
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(radio->band() == QRadioTuner::AM);
+ QVERIFY(readSignal.count() == 1);
+ }
+}
+
+void tst_QRadioTuner_s60::testFrequency()
+{
+ QSignalSpy readSignal(radio, SIGNAL(frequencyChanged(int)));
+ radio->setFrequency(104500000);
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(radio->frequency() == 104500000);
+ QVERIFY(readSignal.count() == 1);
+
+ // frequencyStep for FM radio is 100kHz (100000Hz)
+ QVERIFY(radio->frequencyStep(QRadioTuner::FM) == 100000);
+ QPair<int,int> test = radio->frequencyRange(QRadioTuner::FM);
+ // frequency range for FM radio is 87,5MHz - 108MHz
+ QVERIFY(test.first == 87500000);
+ QVERIFY(test.second == 108000000);
+}
+
+void tst_QRadioTuner_s60::testMute()
+{
+ QSignalSpy readSignal(radio, SIGNAL(mutedChanged(bool)));
+ radio->setMuted(true);
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(radio->isMuted());
+ QVERIFY(readSignal.count() == 1);
+}
+
+void tst_QRadioTuner_s60::testSearch()
+{
+ QSignalSpy readSignal(radio, SIGNAL(searchingChanged(bool)));
+ QVERIFY(!radio->isSearching());
+
+ radio->searchForward();
+ QVERIFY(radio->isSearching());
+ QVERIFY(readSignal.count() == 1);
+
+ radio->cancelSearch();
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(!radio->isSearching());
+ QVERIFY(readSignal.count() == 2);
+
+ radio->searchBackward();
+ QVERIFY(radio->isSearching());
+ QVERIFY(readSignal.count() == 3);
+
+ radio->cancelSearch();
+ QVERIFY(!radio->isSearching());
+}
+
+void tst_QRadioTuner_s60::testVolume()
+{
+ QVERIFY(radio->volume() == 50);
+ QSignalSpy readSignal(radio, SIGNAL(volumeChanged(int)));
+ radio->setVolume(70);
+ QTestEventLoop::instance().enterLoop(1);
+ QTRY_COMPARE_S60(radio->volume() , 70);
+ QTRY_COMPARE_S60(readSignal.count() ,1);
+}
+
+void tst_QRadioTuner_s60::testSignal()
+{
+ int signalStrength = radio->signalStrength();
+ QVERIFY(signalStrength == signalStrength);
+ // There is no set of this only a get, do nothing else.
+}
+
+void tst_QRadioTuner_s60::testStereo()
+{
+ QVERIFY(radio->isStereo());
+ radio->setStereoMode(QRadioTuner::ForceMono);
+ QVERIFY(radio->stereoMode() == QRadioTuner::ForceMono);
+}
diff --git a/tests/auto/qradiotuner/tst_qradiotuner_s60.h b/tests/auto/qradiotuner/tst_qradiotuner_s60.h
new file mode 100644
index 000000000..2767fcb59
--- /dev/null
+++ b/tests/auto/qradiotuner/tst_qradiotuner_s60.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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 TST_QRADIOTUNER_S60_H
+#define TST_QRADIOTUNER_S60_H
+
+#include <QtTest/QtTest>
+#include <QDebug>
+#include <QTimer>
+
+#include <qmediaobject.h>
+#include <qmediacontrol.h>
+#include <qmediaservice.h>
+#include <qradiotunercontrol.h>
+#include <qradiotuner.h>
+
+#include <QMessageBox>
+
+QT_USE_NAMESPACE
+
+class tst_QRadioTuner_s60: public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void testBand();
+ void testFrequency();
+ void testMute();
+ void testSearch();
+ void testVolume();
+ void testSignal();
+ void testStereo();
+
+private:
+ QRadioTuner *radio;
+};
+
+#endif
diff --git a/tests/auto/qradiotuner/tst_qradiotuner_xa.cpp b/tests/auto/qradiotuner/tst_qradiotuner_xa.cpp
new file mode 100644
index 000000000..dec65f839
--- /dev/null
+++ b/tests/auto/qradiotuner/tst_qradiotuner_xa.cpp
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** 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 "tst_qradiotuner_xa.h"
+
+QT_USE_NAMESPACE
+
+#define QTEST_MAIN_S60(TestObject) \
+ int main(int argc, char *argv[]) { \
+ char *new_argv[3]; \
+ QApplication app(argc, argv); \
+ \
+ QString str = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + ".log"; \
+ QByteArray bytes = str.toAscii(); \
+ \
+ char arg1[] = "-o"; \
+ \
+ new_argv[0] = argv[0]; \
+ new_argv[1] = arg1; \
+ new_argv[2] = bytes.data(); \
+ \
+ TestObject tc; \
+ return QTest::qExec(&tc, 3, new_argv); \
+ }
+
+#define QTRY_COMPARE(a,e) \
+ for (int _i = 0; _i < 5000; _i += 100) { \
+ if ((a) == (e)) break; \
+ QTest::qWait(100); \
+ } \
+// QCOMPARE(a, e)
+
+void tst_QXARadio_xa::initTestCase()
+{
+ qRegisterMetaType<QRadioTuner::State>("QRadioTuner::State");
+ radio = new QRadioTuner(0);
+// QVERIFY(radio->service() != 0);
+// QSignalSpy stateSpy(radio, SIGNAL(stateChanged(QRadioTuner::State)));
+ radio->start();
+// QTRY_COMPARE(stateSpy.count(), 1); // wait for callbacks to complete in symbian API
+// QCOMPARE(radio->state(), QRadioTuner::ActiveState);
+
+}
+
+void tst_QXARadio_xa::cleanupTestCase()
+{
+ QVERIFY(radio->service() != 0);
+}
+
+void tst_QXARadio_xa::testBand()
+{
+ qRegisterMetaType<QRadioTuner::Band>("QRadioTuner::Band");
+
+ QVERIFY(radio->isBandSupported(QRadioTuner::FM));
+ QVERIFY(!radio->isBandSupported(QRadioTuner::SW));
+ radio->setBand(QRadioTuner::FM);
+ QVERIFY(radio->band() == QRadioTuner::FM);
+ if(radio->isBandSupported(QRadioTuner::AM)) {
+ QSignalSpy readSignal(radio, SIGNAL(bandChanged(QRadioTuner::Band)));
+ radio->setBand(QRadioTuner::AM);
+ QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QVERIFY(radio->band() == QRadioTuner::AM);
+ }
+}
+
+void tst_QXARadio_xa::testFrequency()
+{
+ QSignalSpy readSignal(radio, SIGNAL(frequencyChanged(int)));
+ radio->setFrequency(90900000);
+ QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QVERIFY(radio->frequency() == 90900000);
+ // frequencyStep for FM radio is 100kHz (100000Hz)
+ QVERIFY(radio->frequencyStep(QRadioTuner::FM) == 100000);
+ QPair<int,int> test = radio->frequencyRange(QRadioTuner::FM);
+ // frequency range for FM radio is 87,5MHz - 108MHz
+ QVERIFY(test.first == 87500000);
+ QVERIFY(test.second == 108000000);
+}
+
+void tst_QXARadio_xa::testMute()
+{
+ QSignalSpy readSignal(radio, SIGNAL(mutedChanged(bool)));
+ radio->setMuted(true);
+ QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QVERIFY(radio->isMuted());
+ QVERIFY(readSignal.count() == 1);
+}
+
+void tst_QXARadio_xa::testSearch()
+{
+ QSignalSpy readSignal(radio, SIGNAL(searchingChanged(bool)));
+ QVERIFY(!radio->isSearching());
+
+ radio->searchForward();
+ // Note: DON'T wait for callback to complete in symbian API
+ QVERIFY(radio->isSearching());
+
+ radio->cancelSearch();
+ QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QVERIFY(!radio->isSearching());
+
+ radio->searchBackward();
+ // Note: DON'T wait for callbacks to complete in symbian API
+ QVERIFY(radio->isSearching());
+
+ radio->cancelSearch();
+ QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QVERIFY(!radio->isSearching());
+}
+
+void tst_QXARadio_xa::testVolume()
+{
+ QSignalSpy readSignal(radio, SIGNAL(volumeChanged(int)));
+ radio->setVolume(50);
+ QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QVERIFY(radio->volume() == 50);
+}
+
+void tst_QXARadio_xa::testSignal()
+{
+ QVERIFY(radio->signalStrength() != 0);
+ // There is no set of this only a get, do nothing else.
+}
+
+void tst_QXARadio_xa::testStereo()
+{
+ // Default = Auto. Testing transition from auto to mono:
+ QVERIFY(radio->isStereo());
+ QSignalSpy readSignal(radio, SIGNAL(stereoStatusChanged(bool)));
+ radio->setStereoMode(QRadioTuner::ForceMono);
+ QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QVERIFY(radio->stereoMode() == QRadioTuner::ForceMono);
+// QVERIFY(readSignal.count() == 1);
+
+ // testing transition from mono to stereo:
+ radio->setStereoMode(QRadioTuner::ForceStereo);
+ QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QVERIFY(radio->stereoMode() == QRadioTuner::ForceStereo);
+// QVERIFY(readSignal.count() == 1);
+
+ // testing transition from stereo to auto:
+ radio->setStereoMode(QRadioTuner::Auto);
+ QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QVERIFY(radio->stereoMode() == QRadioTuner::Auto);
+ // QVERIFY(readSignal.count() == 1);
+
+ // testing transition from auto to stereo:
+ radio->setStereoMode(QRadioTuner::ForceStereo);
+ QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QVERIFY(radio->stereoMode() == QRadioTuner::ForceStereo);
+ // QVERIFY(readSignal.count() == 1);
+
+ // testing transition from stereo to mono:
+ radio->setStereoMode(QRadioTuner::ForceMono);
+ QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QVERIFY(radio->stereoMode() == QRadioTuner::ForceMono);
+ // QVERIFY(readSignal.count() == 1);
+
+ // testing transition from mono to auto:
+ radio->setStereoMode(QRadioTuner::Auto);
+ QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API
+ QVERIFY(radio->stereoMode() == QRadioTuner::Auto);
+// QVERIFY(readSignal.count() == 1);
+
+}
+
+void tst_QXARadio_xa::testAvailability()
+{
+ QVERIFY(radio->isAvailable());
+ QVERIFY(radio->availabilityError() == QtMultimediaKit::NoError);
+}
+
+void tst_QXARadio_xa::testStopRadio()
+{
+ QVERIFY(radio->service() != 0);
+ QVERIFY(radio->error() == QRadioTuner::NoError);
+ QVERIFY(radio->errorString().isEmpty());
+
+ QSignalSpy stateSpy(radio, SIGNAL(stateChanged(QRadioTuner::State)));
+
+ radio->stop();
+ QTRY_COMPARE(stateSpy.count(), 1); // wait for callbacks to complete in symbian API
+ QCOMPARE(radio->state(), QRadioTuner::StoppedState);
+
+// delete radio;
+}
diff --git a/tests/auto/qradiotuner/tst_qradiotuner_xa.h b/tests/auto/qradiotuner/tst_qradiotuner_xa.h
new file mode 100644
index 000000000..6cb7c7802
--- /dev/null
+++ b/tests/auto/qradiotuner/tst_qradiotuner_xa.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 TST_QRADIOTUNER_XA_H
+#define TST_QRADIOTUNER_XA_H
+
+#include <QtTest/QtTest>
+#include <QDebug>
+#include <QTimer>
+#include <qmediaobject.h>
+#include <qmediacontrol.h>
+#include <qmediaservice.h>
+#include <qradiotunercontrol.h>
+#include <qradiotuner.h>
+#include <qtmedianamespace.h>
+
+#include <QMessageBox>
+
+QT_USE_NAMESPACE
+
+class tst_QXARadio_xa: public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void testBand();
+ void testFrequency();
+ void testMute();
+ void testSearch();
+ void testVolume();
+ void testSignal();
+ void testStereo();
+ void testAvailability();
+ void testStopRadio();
+
+private:
+ QRadioTuner *radio;
+};
+
+#endif // TST_QRADIOTUNER_XA_H
diff --git a/tests/auto/qvideoframe/qvideoframe.pro b/tests/auto/qvideoframe/qvideoframe.pro
new file mode 100644
index 000000000..03af898c8
--- /dev/null
+++ b/tests/auto/qvideoframe/qvideoframe.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += core multimediakit-private
+
+# TARGET = tst_qvideoframe
+# CONFIG += testcase
+
+SOURCES += tst_qvideoframe.cpp
+
diff --git a/tests/auto/qvideoframe/tst_qvideoframe.cpp b/tests/auto/qvideoframe/tst_qvideoframe.cpp
new file mode 100644
index 000000000..58640b71a
--- /dev/null
+++ b/tests/auto/qvideoframe/tst_qvideoframe.cpp
@@ -0,0 +1,793 @@
+/****************************************************************************
+**
+** 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 test suite 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <QtTest/QtTest>
+
+#include <qvideoframe.h>
+#include <QtGui/QImage>
+#include <QtCore/QPointer>
+
+class tst_QVideoFrame : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QVideoFrame();
+ ~tst_QVideoFrame();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void create_data();
+ void create();
+ void createInvalid_data();
+ void createInvalid();
+ void createFromBuffer_data();
+ void createFromBuffer();
+ void createFromImage_data();
+ void createFromImage();
+ void createFromIncompatibleImage();
+ void createNull();
+ void destructor();
+ void copy_data();
+ void copy();
+ void assign_data();
+ void assign();
+ void map_data();
+ void map();
+ void mapImage_data();
+ void mapImage();
+ void imageDetach();
+ void formatConversion_data();
+ void formatConversion();
+};
+
+Q_DECLARE_METATYPE(QImage::Format)
+Q_DECLARE_METATYPE(QVideoFrame)
+
+class QtTestVideoBuffer : public QObject, public QAbstractVideoBuffer
+{
+ Q_OBJECT
+public:
+ QtTestVideoBuffer()
+ : QAbstractVideoBuffer(NoHandle) {}
+ explicit QtTestVideoBuffer(QAbstractVideoBuffer::HandleType type)
+ : QAbstractVideoBuffer(type) {}
+
+ MapMode mapMode() const { return NotMapped; }
+
+ uchar *map(MapMode, int *, int *) { return 0; }
+ void unmap() {}
+};
+
+tst_QVideoFrame::tst_QVideoFrame()
+{
+}
+
+tst_QVideoFrame::~tst_QVideoFrame()
+{
+}
+
+void tst_QVideoFrame::initTestCase()
+{
+}
+
+void tst_QVideoFrame::cleanupTestCase()
+{
+}
+
+void tst_QVideoFrame::init()
+{
+}
+
+void tst_QVideoFrame::cleanup()
+{
+}
+
+void tst_QVideoFrame::create_data()
+{
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormat");
+ QTest::addColumn<int>("bytes");
+ QTest::addColumn<int>("bytesPerLine");
+
+ QTest::newRow("64x64 ARGB32")
+ << QSize(64, 64)
+ << QVideoFrame::Format_ARGB32
+ << 16384
+ << 256;
+ QTest::newRow("32x256 YUV420P")
+ << QSize(32, 256)
+ << QVideoFrame::Format_YUV420P
+ << 13288
+ << 32;
+}
+
+void tst_QVideoFrame::create()
+{
+ QFETCH(QSize, size);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormat);
+ QFETCH(int, bytes);
+ QFETCH(int, bytesPerLine);
+
+ QVideoFrame frame(bytes, size, bytesPerLine, pixelFormat);
+
+ QVERIFY(frame.isValid());
+ QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle);
+ QCOMPARE(frame.pixelFormat(), pixelFormat);
+ QCOMPARE(frame.size(), size);
+ QCOMPARE(frame.width(), size.width());
+ QCOMPARE(frame.height(), size.height());
+ QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame);
+ QCOMPARE(frame.startTime(), qint64(-1));
+ QCOMPARE(frame.endTime(), qint64(-1));
+}
+
+void tst_QVideoFrame::createInvalid_data()
+{
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormat");
+ QTest::addColumn<int>("bytes");
+ QTest::addColumn<int>("bytesPerLine");
+
+ QTest::newRow("64x64 ARGB32 0 size")
+ << QSize(64, 64)
+ << QVideoFrame::Format_ARGB32
+ << 0
+ << 45;
+ QTest::newRow("32x256 YUV420P negative size")
+ << QSize(32, 256)
+ << QVideoFrame::Format_YUV420P
+ << -13288
+ << 32;
+}
+
+void tst_QVideoFrame::createInvalid()
+{
+ QFETCH(QSize, size);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormat);
+ QFETCH(int, bytes);
+ QFETCH(int, bytesPerLine);
+
+ QVideoFrame frame(bytes, size, bytesPerLine, pixelFormat);
+
+ QVERIFY(!frame.isValid());
+ QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle);
+ QCOMPARE(frame.pixelFormat(), pixelFormat);
+ QCOMPARE(frame.size(), size);
+ QCOMPARE(frame.width(), size.width());
+ QCOMPARE(frame.height(), size.height());
+ QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame);
+ QCOMPARE(frame.startTime(), qint64(-1));
+ QCOMPARE(frame.endTime(), qint64(-1));
+}
+
+void tst_QVideoFrame::createFromBuffer_data()
+{
+ QTest::addColumn<QAbstractVideoBuffer::HandleType>("handleType");
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormat");
+
+ QTest::newRow("64x64 ARGB32 no handle")
+ << QAbstractVideoBuffer::NoHandle
+ << QSize(64, 64)
+ << QVideoFrame::Format_ARGB32;
+ QTest::newRow("64x64 ARGB32 gl handle")
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QSize(64, 64)
+ << QVideoFrame::Format_ARGB32;
+ QTest::newRow("64x64 ARGB32 user handle")
+ << QAbstractVideoBuffer::UserHandle
+ << QSize(64, 64)
+ << QVideoFrame::Format_ARGB32;
+}
+
+void tst_QVideoFrame::createFromBuffer()
+{
+ QFETCH(QAbstractVideoBuffer::HandleType, handleType);
+ QFETCH(QSize, size);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormat);
+
+ QVideoFrame frame(new QtTestVideoBuffer(handleType), size, pixelFormat);
+
+ QVERIFY(frame.isValid());
+ QCOMPARE(frame.handleType(), handleType);
+ QCOMPARE(frame.pixelFormat(), pixelFormat);
+ QCOMPARE(frame.size(), size);
+ QCOMPARE(frame.width(), size.width());
+ QCOMPARE(frame.height(), size.height());
+ QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame);
+ QCOMPARE(frame.startTime(), qint64(-1));
+ QCOMPARE(frame.endTime(), qint64(-1));
+}
+
+void tst_QVideoFrame::createFromImage_data()
+{
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QImage::Format>("imageFormat");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormat");
+
+ QTest::newRow("64x64 RGB32")
+ << QSize(64, 64)
+ << QImage::Format_RGB32
+ << QVideoFrame::Format_RGB32;
+ QTest::newRow("12x45 RGB16")
+ << QSize(12, 45)
+ << QImage::Format_RGB16
+ << QVideoFrame::Format_RGB565;
+ QTest::newRow("19x46 ARGB32_Premultiplied")
+ << QSize(19, 46)
+ << QImage::Format_ARGB32_Premultiplied
+ << QVideoFrame::Format_ARGB32_Premultiplied;
+}
+
+void tst_QVideoFrame::createFromImage()
+{
+ QFETCH(QSize, size);
+ QFETCH(QImage::Format, imageFormat);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormat);
+
+ const QImage image(size.width(), size.height(), imageFormat);
+
+ QVideoFrame frame(image);
+
+ QVERIFY(frame.isValid());
+ QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle);
+ QCOMPARE(frame.pixelFormat(), pixelFormat);
+ QCOMPARE(frame.size(), size);
+ QCOMPARE(frame.width(), size.width());
+ QCOMPARE(frame.height(), size.height());
+ QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame);
+ QCOMPARE(frame.startTime(), qint64(-1));
+ QCOMPARE(frame.endTime(), qint64(-1));
+}
+
+void tst_QVideoFrame::createFromIncompatibleImage()
+{
+ const QImage image(64, 64, QImage::Format_Mono);
+
+ QVideoFrame frame(image);
+
+ QVERIFY(!frame.isValid());
+ QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle);
+ QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_Invalid);
+ QCOMPARE(frame.size(), QSize(64, 64));
+ QCOMPARE(frame.width(), 64);
+ QCOMPARE(frame.height(), 64);
+ QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame);
+ QCOMPARE(frame.startTime(), qint64(-1));
+ QCOMPARE(frame.endTime(), qint64(-1));
+}
+
+void tst_QVideoFrame::createNull()
+{
+ QVideoFrame frame;
+
+ QVERIFY(!frame.isValid());
+ QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle);
+ QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_Invalid);
+ QCOMPARE(frame.size(), QSize());
+ QCOMPARE(frame.width(), -1);
+ QCOMPARE(frame.height(), -1);
+ QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame);
+ QCOMPARE(frame.startTime(), qint64(-1));
+ QCOMPARE(frame.endTime(), qint64(-1));
+}
+
+void tst_QVideoFrame::destructor()
+{
+ QPointer<QtTestVideoBuffer> buffer = new QtTestVideoBuffer;
+
+ {
+ QVideoFrame frame(buffer, QSize(4, 1), QVideoFrame::Format_ARGB32);
+ }
+
+ QVERIFY(buffer.isNull());
+}
+
+void tst_QVideoFrame::copy_data()
+{
+ QTest::addColumn<QAbstractVideoBuffer::HandleType>("handleType");
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormat");
+ QTest::addColumn<QVideoFrame::FieldType>("fieldType");
+ QTest::addColumn<qint64>("startTime");
+ QTest::addColumn<qint64>("endTime");
+
+ QTest::newRow("64x64 ARGB32")
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QSize(64, 64)
+ << QVideoFrame::Format_ARGB32
+ << QVideoFrame::TopField
+ << qint64(63641740)
+ << qint64(63641954);
+ QTest::newRow("32x256 YUV420P")
+ << QAbstractVideoBuffer::UserHandle
+ << QSize(32, 256)
+ << QVideoFrame::Format_YUV420P
+ << QVideoFrame::InterlacedFrame
+ << qint64(12345)
+ << qint64(12389);
+}
+
+void tst_QVideoFrame::copy()
+{
+ QFETCH(QAbstractVideoBuffer::HandleType, handleType);
+ QFETCH(QSize, size);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormat);
+ QFETCH(QVideoFrame::FieldType, fieldType);
+ QFETCH(qint64, startTime);
+ QFETCH(qint64, endTime);
+
+ QPointer<QtTestVideoBuffer> buffer = new QtTestVideoBuffer(handleType);
+
+ {
+ QVideoFrame frame(buffer, size, pixelFormat);
+ frame.setFieldType(QVideoFrame::FieldType(fieldType));
+ frame.setStartTime(startTime);
+ frame.setEndTime(endTime);
+
+ QVERIFY(frame.isValid());
+ QCOMPARE(frame.handleType(), handleType);
+ QCOMPARE(frame.pixelFormat(), pixelFormat);
+ QCOMPARE(frame.size(), size);
+ QCOMPARE(frame.width(), size.width());
+ QCOMPARE(frame.height(), size.height());
+ QCOMPARE(frame.fieldType(), fieldType);
+ QCOMPARE(frame.startTime(), startTime);
+ QCOMPARE(frame.endTime(), endTime);
+
+ {
+ QVideoFrame otherFrame(frame);
+
+ QVERIFY(!buffer.isNull());
+
+ QVERIFY(otherFrame.isValid());
+ QCOMPARE(otherFrame.handleType(), handleType);
+ QCOMPARE(otherFrame.pixelFormat(), pixelFormat);
+ QCOMPARE(otherFrame.size(), size);
+ QCOMPARE(otherFrame.width(), size.width());
+ QCOMPARE(otherFrame.height(), size.height());
+ QCOMPARE(otherFrame.fieldType(), fieldType);
+ QCOMPARE(otherFrame.startTime(), startTime);
+ QCOMPARE(otherFrame.endTime(), endTime);
+
+ otherFrame.setEndTime(-1);
+
+ QVERIFY(!buffer.isNull());
+
+ QVERIFY(otherFrame.isValid());
+ QCOMPARE(otherFrame.handleType(), handleType);
+ QCOMPARE(otherFrame.pixelFormat(), pixelFormat);
+ QCOMPARE(otherFrame.size(), size);
+ QCOMPARE(otherFrame.width(), size.width());
+ QCOMPARE(otherFrame.height(), size.height());
+ QCOMPARE(otherFrame.fieldType(), fieldType);
+ QCOMPARE(otherFrame.startTime(), startTime);
+ QCOMPARE(otherFrame.endTime(), qint64(-1));
+ }
+
+ QVERIFY(!buffer.isNull());
+
+ QVERIFY(frame.isValid());
+ QCOMPARE(frame.handleType(), handleType);
+ QCOMPARE(frame.pixelFormat(), pixelFormat);
+ QCOMPARE(frame.size(), size);
+ QCOMPARE(frame.width(), size.width());
+ QCOMPARE(frame.height(), size.height());
+ QCOMPARE(frame.fieldType(), fieldType);
+ QCOMPARE(frame.startTime(), startTime);
+ QCOMPARE(frame.endTime(), qint64(-1)); // Explicitly shared.
+ }
+
+ QVERIFY(buffer.isNull());
+}
+
+void tst_QVideoFrame::assign_data()
+{
+ QTest::addColumn<QAbstractVideoBuffer::HandleType>("handleType");
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormat");
+ QTest::addColumn<QVideoFrame::FieldType>("fieldType");
+ QTest::addColumn<qint64>("startTime");
+ QTest::addColumn<qint64>("endTime");
+
+ QTest::newRow("64x64 ARGB32")
+ << QAbstractVideoBuffer::GLTextureHandle
+ << QSize(64, 64)
+ << QVideoFrame::Format_ARGB32
+ << QVideoFrame::TopField
+ << qint64(63641740)
+ << qint64(63641954);
+ QTest::newRow("32x256 YUV420P")
+ << QAbstractVideoBuffer::UserHandle
+ << QSize(32, 256)
+ << QVideoFrame::Format_YUV420P
+ << QVideoFrame::InterlacedFrame
+ << qint64(12345)
+ << qint64(12389);
+}
+
+void tst_QVideoFrame::assign()
+{
+ QFETCH(QAbstractVideoBuffer::HandleType, handleType);
+ QFETCH(QSize, size);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormat);
+ QFETCH(QVideoFrame::FieldType, fieldType);
+ QFETCH(qint64, startTime);
+ QFETCH(qint64, endTime);
+
+ QPointer<QtTestVideoBuffer> buffer = new QtTestVideoBuffer(handleType);
+
+ QVideoFrame frame;
+ {
+ QVideoFrame otherFrame(buffer, size, pixelFormat);
+ otherFrame.setFieldType(fieldType);
+ otherFrame.setStartTime(startTime);
+ otherFrame.setEndTime(endTime);
+
+ frame = otherFrame;
+
+ QVERIFY(!buffer.isNull());
+
+ QVERIFY(otherFrame.isValid());
+ QCOMPARE(otherFrame.handleType(), handleType);
+ QCOMPARE(otherFrame.pixelFormat(), pixelFormat);
+ QCOMPARE(otherFrame.size(), size);
+ QCOMPARE(otherFrame.width(), size.width());
+ QCOMPARE(otherFrame.height(), size.height());
+ QCOMPARE(otherFrame.fieldType(), fieldType);
+ QCOMPARE(otherFrame.startTime(), startTime);
+ QCOMPARE(otherFrame.endTime(), endTime);
+
+ otherFrame.setStartTime(-1);
+
+ QVERIFY(!buffer.isNull());
+
+ QVERIFY(otherFrame.isValid());
+ QCOMPARE(otherFrame.handleType(), handleType);
+ QCOMPARE(otherFrame.pixelFormat(), pixelFormat);
+ QCOMPARE(otherFrame.size(), size);
+ QCOMPARE(otherFrame.width(), size.width());
+ QCOMPARE(otherFrame.height(), size.height());
+ QCOMPARE(otherFrame.fieldType(), fieldType);
+ QCOMPARE(otherFrame.startTime(), qint64(-1));
+ QCOMPARE(otherFrame.endTime(), endTime);
+ }
+
+ QVERIFY(!buffer.isNull());
+
+ QVERIFY(frame.isValid());
+ QCOMPARE(frame.handleType(), handleType);
+ QCOMPARE(frame.pixelFormat(), pixelFormat);
+ QCOMPARE(frame.size(), size);
+ QCOMPARE(frame.width(), size.width());
+ QCOMPARE(frame.height(), size.height());
+ QCOMPARE(frame.fieldType(), fieldType);
+ QCOMPARE(frame.startTime(), qint64(-1));
+ QCOMPARE(frame.endTime(), endTime);
+
+ frame = QVideoFrame();
+
+ QVERIFY(buffer.isNull());
+
+ QVERIFY(!frame.isValid());
+ QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle);
+ QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_Invalid);
+ QCOMPARE(frame.size(), QSize());
+ QCOMPARE(frame.width(), -1);
+ QCOMPARE(frame.height(), -1);
+ QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame);
+ QCOMPARE(frame.startTime(), qint64(-1));
+ QCOMPARE(frame.endTime(), qint64(-1));
+}
+
+void tst_QVideoFrame::map_data()
+{
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<int>("mappedBytes");
+ QTest::addColumn<int>("bytesPerLine");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormat");
+ QTest::addColumn<QAbstractVideoBuffer::MapMode>("mode");
+
+ QTest::newRow("read-only")
+ << QSize(64, 64)
+ << 16384
+ << 256
+ << QVideoFrame::Format_ARGB32
+ << QAbstractVideoBuffer::ReadOnly;
+
+ QTest::newRow("write-only")
+ << QSize(64, 64)
+ << 16384
+ << 256
+ << QVideoFrame::Format_ARGB32
+ << QAbstractVideoBuffer::WriteOnly;
+
+ QTest::newRow("read-write")
+ << QSize(64, 64)
+ << 16384
+ << 256
+ << QVideoFrame::Format_ARGB32
+ << QAbstractVideoBuffer::ReadWrite;
+}
+
+void tst_QVideoFrame::map()
+{
+ QFETCH(QSize, size);
+ QFETCH(int, mappedBytes);
+ QFETCH(int, bytesPerLine);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormat);
+ QFETCH(QAbstractVideoBuffer::MapMode, mode);
+
+ QVideoFrame frame(mappedBytes, size, bytesPerLine, pixelFormat);
+
+ QVERIFY(!frame.bits());
+ QCOMPARE(frame.mappedBytes(), 0);
+ QCOMPARE(frame.bytesPerLine(), 0);
+ QCOMPARE(frame.mapMode(), QAbstractVideoBuffer::NotMapped);
+
+ QVERIFY(frame.map(mode));
+
+ QVERIFY(frame.bits());
+ QCOMPARE(frame.mappedBytes(), mappedBytes);
+ QCOMPARE(frame.bytesPerLine(), bytesPerLine);
+ QCOMPARE(frame.mapMode(), mode);
+
+ frame.unmap();
+
+ QVERIFY(!frame.bits());
+ QCOMPARE(frame.mappedBytes(), 0);
+ QCOMPARE(frame.bytesPerLine(), 0);
+ QCOMPARE(frame.mapMode(), QAbstractVideoBuffer::NotMapped);
+}
+
+void tst_QVideoFrame::mapImage_data()
+{
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QImage::Format>("format");
+ QTest::addColumn<QAbstractVideoBuffer::MapMode>("mode");
+
+ QTest::newRow("read-only")
+ << QSize(64, 64)
+ << QImage::Format_ARGB32
+ << QAbstractVideoBuffer::ReadOnly;
+
+ QTest::newRow("write-only")
+ << QSize(15, 106)
+ << QImage::Format_RGB32
+ << QAbstractVideoBuffer::WriteOnly;
+
+ QTest::newRow("read-write")
+ << QSize(23, 111)
+ << QImage::Format_RGB16
+ << QAbstractVideoBuffer::ReadWrite;
+}
+
+void tst_QVideoFrame::mapImage()
+{
+ QFETCH(QSize, size);
+ QFETCH(QImage::Format, format);
+ QFETCH(QAbstractVideoBuffer::MapMode, mode);
+
+ QImage image(size.width(), size.height(), format);
+
+ QVideoFrame frame(image);
+
+ QVERIFY(!frame.bits());
+ QCOMPARE(frame.mappedBytes(), 0);
+ QCOMPARE(frame.bytesPerLine(), 0);
+ QCOMPARE(frame.mapMode(), QAbstractVideoBuffer::NotMapped);
+
+ QVERIFY(frame.map(mode));
+
+ QVERIFY(frame.bits());
+ QCOMPARE(frame.mappedBytes(), image.numBytes());
+ QCOMPARE(frame.bytesPerLine(), image.bytesPerLine());
+ QCOMPARE(frame.mapMode(), mode);
+
+ frame.unmap();
+
+ QVERIFY(!frame.bits());
+ QCOMPARE(frame.mappedBytes(), 0);
+ QCOMPARE(frame.bytesPerLine(), 0);
+ QCOMPARE(frame.mapMode(), QAbstractVideoBuffer::NotMapped);
+}
+
+void tst_QVideoFrame::imageDetach()
+{
+ const uint red = qRgb(255, 0, 0);
+ const uint blue = qRgb(0, 0, 255);
+
+ QImage image(8, 8, QImage::Format_RGB32);
+
+ image.fill(red);
+ QCOMPARE(image.pixel(4, 4), red);
+
+ QVideoFrame frame(image);
+
+ QVERIFY(frame.map(QAbstractVideoBuffer::ReadWrite));
+
+ QImage frameImage(frame.bits(), 8, 8, frame.bytesPerLine(), QImage::Format_RGB32);
+
+ QCOMPARE(frameImage.pixel(4, 4), red);
+
+ frameImage.fill(blue);
+ QCOMPARE(frameImage.pixel(4, 4), blue);
+
+ // Original image has detached and is therefore unchanged.
+ QCOMPARE(image.pixel(4, 4), red);
+}
+
+void tst_QVideoFrame::formatConversion_data()
+{
+ QTest::addColumn<QImage::Format>("imageFormat");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormat");
+
+ QTest::newRow("QImage::Format_RGB32 | QVideoFrame::Format_RGB32")
+ << QImage::Format_RGB32
+ << QVideoFrame::Format_RGB32;
+ QTest::newRow("QImage::Format_ARGB32 | QVideoFrame::Format_ARGB32")
+ << QImage::Format_ARGB32
+ << QVideoFrame::Format_ARGB32;
+ QTest::newRow("QImage::Format_ARGB32_Premultiplied | QVideoFrame::Format_ARGB32_Premultiplied")
+ << QImage::Format_ARGB32_Premultiplied
+ << QVideoFrame::Format_ARGB32_Premultiplied;
+ QTest::newRow("QImage::Format_RGB16 | QVideoFrame::Format_RGB565")
+ << QImage::Format_RGB16
+ << QVideoFrame::Format_RGB565;
+ QTest::newRow("QImage::Format_ARGB8565_Premultiplied | QVideoFrame::Format_ARGB8565_Premultiplied")
+ << QImage::Format_ARGB8565_Premultiplied
+ << QVideoFrame::Format_ARGB8565_Premultiplied;
+ QTest::newRow("QImage::Format_RGB555 | QVideoFrame::Format_RGB555")
+ << QImage::Format_RGB555
+ << QVideoFrame::Format_RGB555;
+ QTest::newRow("QImage::Format_RGB888 | QVideoFrame::Format_RGB24")
+ << QImage::Format_RGB888
+ << QVideoFrame::Format_RGB24;
+
+ QTest::newRow("QImage::Format_MonoLSB")
+ << QImage::Format_MonoLSB
+ << QVideoFrame::Format_Invalid;
+ QTest::newRow("QImage::Format_Indexed8")
+ << QImage::Format_Indexed8
+ << QVideoFrame::Format_Invalid;
+ QTest::newRow("QImage::Format_ARGB6666_Premultiplied")
+ << QImage::Format_ARGB6666_Premultiplied
+ << QVideoFrame::Format_Invalid;
+ QTest::newRow("QImage::Format_ARGB8555_Premultiplied")
+ << QImage::Format_ARGB8555_Premultiplied
+ << QVideoFrame::Format_Invalid;
+ QTest::newRow("QImage::Format_RGB666")
+ << QImage::Format_RGB666
+ << QVideoFrame::Format_Invalid;
+ QTest::newRow("QImage::Format_RGB444")
+ << QImage::Format_RGB444
+ << QVideoFrame::Format_Invalid;
+ QTest::newRow("QImage::Format_ARGB4444_Premultiplied")
+ << QImage::Format_ARGB4444_Premultiplied
+ << QVideoFrame::Format_Invalid;
+
+ QTest::newRow("QVideoFrame::Format_BGRA32")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_BGRA32;
+ QTest::newRow("QVideoFrame::Format_BGRA32_Premultiplied")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_BGRA32_Premultiplied;
+ QTest::newRow("QVideoFrame::Format_BGR32")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_BGR32;
+ QTest::newRow("QVideoFrame::Format_BGR24")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_BGR24;
+ QTest::newRow("QVideoFrame::Format_BGR565")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_BGR565;
+ QTest::newRow("QVideoFrame::Format_BGR555")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_BGR555;
+ QTest::newRow("QVideoFrame::Format_BGRA5658_Premultiplied")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_BGRA5658_Premultiplied;
+ QTest::newRow("QVideoFrame::Format_AYUV444")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_AYUV444;
+ QTest::newRow("QVideoFrame::Format_AYUV444_Premultiplied")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_AYUV444_Premultiplied;
+ QTest::newRow("QVideoFrame::Format_YUV444")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_YUV420P;
+ QTest::newRow("QVideoFrame::Format_YV12")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_YV12;
+ QTest::newRow("QVideoFrame::Format_UYVY")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_UYVY;
+ QTest::newRow("QVideoFrame::Format_YUYV")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_YUYV;
+ QTest::newRow("QVideoFrame::Format_NV12")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_NV12;
+ QTest::newRow("QVideoFrame::Format_NV21")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_NV21;
+ QTest::newRow("QVideoFrame::Format_IMC1")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_IMC1;
+ QTest::newRow("QVideoFrame::Format_IMC2")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_IMC2;
+ QTest::newRow("QVideoFrame::Format_IMC3")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_IMC3;
+ QTest::newRow("QVideoFrame::Format_IMC4")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_IMC4;
+ QTest::newRow("QVideoFrame::Format_Y8")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_Y8;
+ QTest::newRow("QVideoFrame::Format_Y16")
+ << QImage::Format_Invalid
+ << QVideoFrame::Format_Y16;
+}
+
+void tst_QVideoFrame::formatConversion()
+{
+ QFETCH(QImage::Format, imageFormat);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormat);
+
+ QCOMPARE(QVideoFrame::pixelFormatFromImageFormat(imageFormat) == pixelFormat,
+ imageFormat != QImage::Format_Invalid);
+
+ QCOMPARE(QVideoFrame::imageFormatFromPixelFormat(pixelFormat) == imageFormat,
+ pixelFormat != QVideoFrame::Format_Invalid);
+}
+
+QTEST_MAIN(tst_QVideoFrame)
+
+#include "tst_qvideoframe.moc"
diff --git a/tests/auto/qvideosurfaceformat/qvideosurfaceformat.pro b/tests/auto/qvideosurfaceformat/qvideosurfaceformat.pro
new file mode 100644
index 000000000..472d2cf9c
--- /dev/null
+++ b/tests/auto/qvideosurfaceformat/qvideosurfaceformat.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += core multimediakit-private
+
+# TARGET = tst_qvideosurfaceformat
+# CONFIG += testcase
+
+SOURCES += tst_qvideosurfaceformat.cpp
+
diff --git a/tests/auto/qvideosurfaceformat/tst_qvideosurfaceformat.cpp b/tests/auto/qvideosurfaceformat/tst_qvideosurfaceformat.cpp
new file mode 100644
index 000000000..6a751ff20
--- /dev/null
+++ b/tests/auto/qvideosurfaceformat/tst_qvideosurfaceformat.cpp
@@ -0,0 +1,738 @@
+/****************************************************************************
+**
+** 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 test suite 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <QtTest/QtTest>
+
+#include <qvideosurfaceformat.h>
+
+class tst_QVideoSurfaceFormat : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QVideoSurfaceFormat();
+ ~tst_QVideoSurfaceFormat();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void constructNull();
+ void construct_data();
+ void construct();
+ void frameSize_data();
+ void frameSize();
+ void viewport_data();
+ void viewport();
+ void scanLineDirection_data();
+ void scanLineDirection();
+ void frameRate_data();
+ void frameRate();
+ void yCbCrColorSpace_data();
+ void yCbCrColorSpace();
+ void pixelAspectRatio_data();
+ void pixelAspectRatio();
+ void sizeHint_data();
+ void sizeHint();
+ void staticPropertyNames();
+ void dynamicProperty();
+ void compare();
+ void copy();
+ void assign();
+};
+
+tst_QVideoSurfaceFormat::tst_QVideoSurfaceFormat()
+{
+}
+
+tst_QVideoSurfaceFormat::~tst_QVideoSurfaceFormat()
+{
+}
+
+void tst_QVideoSurfaceFormat::initTestCase()
+{
+}
+
+void tst_QVideoSurfaceFormat::cleanupTestCase()
+{
+}
+
+void tst_QVideoSurfaceFormat::init()
+{
+}
+
+void tst_QVideoSurfaceFormat::cleanup()
+{
+}
+
+void tst_QVideoSurfaceFormat::constructNull()
+{
+ QVideoSurfaceFormat format;
+
+ QVERIFY(!format.isValid());
+ QCOMPARE(format.handleType(), QAbstractVideoBuffer::NoHandle);
+ QCOMPARE(format.pixelFormat(), QVideoFrame::Format_Invalid);
+ QCOMPARE(format.frameSize(), QSize());
+ QCOMPARE(format.frameWidth(), -1);
+ QCOMPARE(format.frameHeight(), -1);
+ QCOMPARE(format.viewport(), QRect());
+ QCOMPARE(format.scanLineDirection(), QVideoSurfaceFormat::TopToBottom);
+ QCOMPARE(format.frameRate(), 0.0);
+ QCOMPARE(format.pixelAspectRatio(), QSize(1, 1));
+ QCOMPARE(format.yCbCrColorSpace(), QVideoSurfaceFormat::YCbCr_Undefined);
+}
+
+void tst_QVideoSurfaceFormat::construct_data()
+{
+ QTest::addColumn<QSize>("frameSize");
+ QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormat");
+ QTest::addColumn<QAbstractVideoBuffer::HandleType>("handleType");
+ QTest::addColumn<bool>("valid");
+
+ QTest::newRow("32x32 rgb32 no handle")
+ << QSize(32, 32)
+ << QVideoFrame::Format_RGB32
+ << QAbstractVideoBuffer::NoHandle
+ << true;
+
+ QTest::newRow("1024x768 YUV444 GL texture")
+ << QSize(32, 32)
+ << QVideoFrame::Format_YUV444
+ << QAbstractVideoBuffer::GLTextureHandle
+ << true;
+
+ QTest::newRow("32x32 invalid no handle")
+ << QSize(32, 32)
+ << QVideoFrame::Format_Invalid
+ << QAbstractVideoBuffer::NoHandle
+ << false;
+
+ QTest::newRow("invalid size, rgb32 no handle")
+ << QSize()
+ << QVideoFrame::Format_RGB32
+ << QAbstractVideoBuffer::NoHandle
+ << false;
+
+ QTest::newRow("0x0 rgb32 no handle")
+ << QSize(0,0)
+ << QVideoFrame::Format_RGB32
+ << QAbstractVideoBuffer::NoHandle
+ << true;
+}
+
+void tst_QVideoSurfaceFormat::construct()
+{
+ QFETCH(QSize, frameSize);
+ QFETCH(QVideoFrame::PixelFormat, pixelFormat);
+ QFETCH(QAbstractVideoBuffer::HandleType, handleType);
+ QFETCH(bool, valid);
+
+ QRect viewport(QPoint(0, 0), frameSize);
+
+ QVideoSurfaceFormat format(frameSize, pixelFormat, handleType);
+
+ QCOMPARE(format.handleType(), handleType);
+ QCOMPARE(format.pixelFormat(), pixelFormat);
+ QCOMPARE(format.frameSize(), frameSize);
+ QCOMPARE(format.frameWidth(), frameSize.width());
+ QCOMPARE(format.frameHeight(), frameSize.height());
+ QCOMPARE(format.isValid(), valid);
+ QCOMPARE(format.viewport(), viewport);
+ QCOMPARE(format.scanLineDirection(), QVideoSurfaceFormat::TopToBottom);
+ QCOMPARE(format.frameRate(), 0.0);
+ QCOMPARE(format.pixelAspectRatio(), QSize(1, 1));
+ QCOMPARE(format.yCbCrColorSpace(), QVideoSurfaceFormat::YCbCr_Undefined);
+}
+
+void tst_QVideoSurfaceFormat::frameSize_data()
+{
+ QTest::addColumn<QSize>("initialSize");
+ QTest::addColumn<QSize>("newSize");
+
+ QTest::newRow("grow")
+ << QSize(64, 64)
+ << QSize(1024, 1024);
+ QTest::newRow("shrink")
+ << QSize(1024, 1024)
+ << QSize(64, 64);
+ QTest::newRow("unchanged")
+ << QSize(512, 512)
+ << QSize(512, 512);
+}
+
+void tst_QVideoSurfaceFormat::frameSize()
+{
+ QFETCH(QSize, initialSize);
+ QFETCH(QSize, newSize);
+
+ QVideoSurfaceFormat format(initialSize, QVideoFrame::Format_RGB32);
+
+ format.setFrameSize(newSize);
+
+ QCOMPARE(format.frameSize(), newSize);
+ QCOMPARE(format.property("frameSize").toSize(), newSize);
+ QCOMPARE(format.frameWidth(), newSize.width());
+ QCOMPARE(format.property("frameWidth").toInt(), newSize.width());
+ QCOMPARE(format.frameHeight(), newSize.height());
+ QCOMPARE(format.property("frameHeight").toInt(), newSize.height());
+}
+
+void tst_QVideoSurfaceFormat::viewport_data()
+{
+ QTest::addColumn<QSize>("initialSize");
+ QTest::addColumn<QRect>("viewport");
+ QTest::addColumn<QSize>("newSize");
+ QTest::addColumn<QRect>("expectedViewport");
+
+ QTest::newRow("grow reset")
+ << QSize(64, 64)
+ << QRect(8, 8, 48, 48)
+ << QSize(1024, 1024)
+ << QRect(0, 0, 1024, 1024);
+ QTest::newRow("shrink reset")
+ << QSize(1024, 1024)
+ << QRect(8, 8, 1008, 1008)
+ << QSize(64, 64)
+ << QRect(0, 0, 64, 64);
+ QTest::newRow("unchanged reset")
+ << QSize(512, 512)
+ << QRect(8, 8, 496, 496)
+ << QSize(512, 512)
+ << QRect(0, 0, 512, 512);
+}
+
+void tst_QVideoSurfaceFormat::viewport()
+{
+ QFETCH(QSize, initialSize);
+ QFETCH(QRect, viewport);
+ QFETCH(QSize, newSize);
+ QFETCH(QRect, expectedViewport);
+
+ {
+ QRect initialViewport(QPoint(0, 0), initialSize);
+
+ QVideoSurfaceFormat format(initialSize, QVideoFrame::Format_RGB32);
+
+ format.setViewport(viewport);
+
+ QCOMPARE(format.viewport(), viewport);
+ QCOMPARE(format.property("viewport").toRect(), viewport);
+
+ format.setFrameSize(newSize);
+
+ QCOMPARE(format.viewport(), expectedViewport);
+ QCOMPARE(format.property("viewport").toRect(), expectedViewport);
+ }
+ {
+ QVideoSurfaceFormat format(initialSize, QVideoFrame::Format_RGB32);
+
+ format.setProperty("viewport", viewport);
+
+ QCOMPARE(format.viewport(), viewport);
+ QCOMPARE(format.property("viewport").toRect(), viewport);
+ }
+}
+
+void tst_QVideoSurfaceFormat::scanLineDirection_data()
+{
+ QTest::addColumn<QVideoSurfaceFormat::Direction>("direction");
+
+ QTest::newRow("top to bottom")
+ << QVideoSurfaceFormat::TopToBottom;
+
+ QTest::newRow("bottom to top")
+ << QVideoSurfaceFormat::BottomToTop;
+}
+
+void tst_QVideoSurfaceFormat::scanLineDirection()
+{
+ QFETCH(QVideoSurfaceFormat::Direction, direction);
+
+ {
+ QVideoSurfaceFormat format(QSize(16, 16), QVideoFrame::Format_RGB32);
+
+ format.setScanLineDirection(direction);
+
+ QCOMPARE(format.scanLineDirection(), direction);
+ QCOMPARE(
+ qvariant_cast<QVideoSurfaceFormat::Direction>(format.property("scanLineDirection")),
+ direction);
+ }
+ {
+ QVideoSurfaceFormat format(QSize(16, 16), QVideoFrame::Format_RGB32);
+
+ format.setProperty("scanLineDirection", qVariantFromValue(direction));
+
+ QCOMPARE(format.scanLineDirection(), direction);
+ QCOMPARE(
+ qvariant_cast<QVideoSurfaceFormat::Direction>(format.property("scanLineDirection")),
+ direction);
+ }
+}
+
+void tst_QVideoSurfaceFormat::frameRate_data()
+{
+ QTest::addColumn<qreal>("frameRate");
+
+ QTest::newRow("null")
+ << qreal(0.0);
+ QTest::newRow("1/1")
+ << qreal(1.0);
+ QTest::newRow("24/1")
+ << qreal(24.0);
+ QTest::newRow("15/2")
+ << qreal(7.5);
+}
+
+void tst_QVideoSurfaceFormat::frameRate()
+{
+ QFETCH(qreal, frameRate);
+
+ {
+ QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32);
+
+ format.setFrameRate(frameRate);
+
+ QCOMPARE(format.frameRate(), frameRate);
+ QCOMPARE(qvariant_cast<qreal>(format.property("frameRate")), frameRate);
+ }
+ {
+ QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32);
+
+ format.setFrameRate(frameRate);
+ format.setProperty("frameRate", frameRate);
+
+ QCOMPARE(format.frameRate(), frameRate);
+ QCOMPARE(qvariant_cast<qreal>(format.property("frameRate")), frameRate);
+ }
+}
+
+void tst_QVideoSurfaceFormat::yCbCrColorSpace_data()
+{
+ QTest::addColumn<QVideoSurfaceFormat::YCbCrColorSpace>("colorspace");
+
+ QTest::newRow("undefined")
+ << QVideoSurfaceFormat::YCbCr_Undefined;
+ QTest::newRow("bt709")
+ << QVideoSurfaceFormat::YCbCr_BT709;
+ QTest::newRow("xvYCC601")
+ << QVideoSurfaceFormat::YCbCr_xvYCC601;
+ QTest::newRow("JPEG")
+ << QVideoSurfaceFormat::YCbCr_JPEG;
+}
+
+void tst_QVideoSurfaceFormat::yCbCrColorSpace()
+{
+ QFETCH(QVideoSurfaceFormat::YCbCrColorSpace, colorspace);
+
+ {
+ QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32);
+ format.setYCbCrColorSpace(colorspace);
+
+ QCOMPARE(format.yCbCrColorSpace(), colorspace);
+ QCOMPARE(qvariant_cast<QVideoSurfaceFormat::YCbCrColorSpace>(format.property("yCbCrColorSpace")),
+ colorspace);
+ }
+ {
+ QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32);
+ format.setProperty("yCbCrColorSpace", qVariantFromValue(colorspace));
+
+ QCOMPARE(format.yCbCrColorSpace(), colorspace);
+ QCOMPARE(qvariant_cast<QVideoSurfaceFormat::YCbCrColorSpace>(format.property("yCbCrColorSpace")),
+ colorspace);
+ }
+}
+
+void tst_QVideoSurfaceFormat::pixelAspectRatio_data()
+{
+ QTest::addColumn<QSize>("aspectRatio");
+
+ QTest::newRow("1:1")
+ << QSize(1, 1);
+ QTest::newRow("4:3")
+ << QSize(4, 3);
+ QTest::newRow("16:9")
+ << QSize(16, 9);
+}
+
+void tst_QVideoSurfaceFormat::pixelAspectRatio()
+{
+ QFETCH(QSize, aspectRatio);
+
+ {
+ QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32);
+ format.setPixelAspectRatio(aspectRatio);
+
+ QCOMPARE(format.pixelAspectRatio(), aspectRatio);
+ QCOMPARE(format.property("pixelAspectRatio").toSize(), aspectRatio);
+ }
+ {
+ QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32);
+ format.setPixelAspectRatio(aspectRatio.width(), aspectRatio.height());
+
+ QCOMPARE(format.pixelAspectRatio(), aspectRatio);
+ QCOMPARE(format.property("pixelAspectRatio").toSize(), aspectRatio);
+ }
+ {
+ QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32);
+ format.setProperty("pixelAspectRatio", aspectRatio);
+
+ QCOMPARE(format.pixelAspectRatio(), aspectRatio);
+ QCOMPARE(format.property("pixelAspectRatio").toSize(), aspectRatio);
+ }
+}
+
+void tst_QVideoSurfaceFormat::sizeHint_data()
+{
+ QTest::addColumn<QSize>("frameSize");
+ QTest::addColumn<QRect>("viewport");
+ QTest::addColumn<QSize>("aspectRatio");
+ QTest::addColumn<QSize>("sizeHint");
+
+ QTest::newRow("(0, 0, 1024x768), 1:1")
+ << QSize(1024, 768)
+ << QRect(0, 0, 1024, 768)
+ << QSize(1, 1)
+ << QSize(1024, 768);
+ QTest::newRow("0, 0, 1024x768), 4:3")
+ << QSize(1024, 768)
+ << QRect(0, 0, 1024, 768)
+ << QSize(4, 3)
+ << QSize(1365, 768);
+ QTest::newRow("(168, 84, 800x600), 1:1")
+ << QSize(1024, 768)
+ << QRect(168, 84, 800, 600)
+ << QSize(1, 1)
+ << QSize(800, 600);
+ QTest::newRow("(168, 84, 800x600), 4:3")
+ << QSize(1024, 768)
+ << QRect(168, 84, 800, 600)
+ << QSize(4, 3)
+ << QSize(1066, 600);
+}
+
+void tst_QVideoSurfaceFormat::sizeHint()
+{
+ QFETCH(QSize, frameSize);
+ QFETCH(QRect, viewport);
+ QFETCH(QSize, aspectRatio);
+ QFETCH(QSize, sizeHint);
+
+ QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_RGB32);
+ format.setViewport(viewport);
+ format.setPixelAspectRatio(aspectRatio);
+
+ QCOMPARE(format.sizeHint(), sizeHint);
+ QCOMPARE(format.property("sizeHint").toSize(), sizeHint);
+}
+
+void tst_QVideoSurfaceFormat::staticPropertyNames()
+{
+ QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32);
+
+ QList<QByteArray> propertyNames = format.propertyNames();
+
+ QVERIFY(propertyNames.contains("handleType"));
+ QVERIFY(propertyNames.contains("pixelFormat"));
+ QVERIFY(propertyNames.contains("frameSize"));
+ QVERIFY(propertyNames.contains("frameWidth"));
+ QVERIFY(propertyNames.contains("viewport"));
+ QVERIFY(propertyNames.contains("scanLineDirection"));
+ QVERIFY(propertyNames.contains("frameRate"));
+ QVERIFY(propertyNames.contains("pixelAspectRatio"));
+ QVERIFY(propertyNames.contains("yCbCrColorSpace"));
+ QVERIFY(propertyNames.contains("sizeHint"));
+ QCOMPARE(propertyNames.count(), 10);
+}
+
+void tst_QVideoSurfaceFormat::dynamicProperty()
+{
+ QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32);
+
+ QCOMPARE(format.property("integer"), QVariant());
+ QCOMPARE(format.property("size"), QVariant());
+ QCOMPARE(format.property("string"), QVariant());
+ QCOMPARE(format.property("null"), QVariant());
+
+ QList<QByteArray> propertyNames = format.propertyNames();
+
+ QCOMPARE(propertyNames.count(QByteArray("integer")), 0);
+ QCOMPARE(propertyNames.count(QByteArray("string")), 0);
+ QCOMPARE(propertyNames.count(QByteArray("size")), 0);
+ QCOMPARE(propertyNames.count(QByteArray("null")), 0);
+
+ format.setProperty("string", QString::fromLatin1("Hello"));
+ format.setProperty("integer", 198);
+ format.setProperty("size", QSize(43, 65));
+
+ QCOMPARE(format.property("integer").toInt(), 198);
+ QCOMPARE(format.property("size").toSize(), QSize(43, 65));
+ QCOMPARE(format.property("string").toString(), QString::fromLatin1("Hello"));
+
+ propertyNames = format.propertyNames();
+
+ QCOMPARE(propertyNames.count(QByteArray("integer")), 1);
+ QCOMPARE(propertyNames.count(QByteArray("string")), 1);
+ QCOMPARE(propertyNames.count(QByteArray("size")), 1);
+
+ format.setProperty("integer", 125423);
+ format.setProperty("size", QSize(1, 986));
+
+ QCOMPARE(format.property("integer").toInt(), 125423);
+ QCOMPARE(format.property("size").toSize(), QSize(1, 986));
+ QCOMPARE(format.property("string").toString(), QString::fromLatin1("Hello"));
+
+ propertyNames = format.propertyNames();
+
+ QCOMPARE(propertyNames.count(QByteArray("integer")), 1);
+ QCOMPARE(propertyNames.count(QByteArray("string")), 1);
+ QCOMPARE(propertyNames.count(QByteArray("size")), 1);
+
+ format.setProperty("string", QVariant());
+ format.setProperty("size", QVariant());
+ format.setProperty("null", QVariant());
+
+ QCOMPARE(format.property("integer").toInt(), 125423);
+ QCOMPARE(format.property("size"), QVariant());
+ QCOMPARE(format.property("string"), QVariant());
+ QCOMPARE(format.property("null"), QVariant());
+
+ propertyNames = format.propertyNames();
+
+ QCOMPARE(propertyNames.count(QByteArray("integer")), 1);
+ QCOMPARE(propertyNames.count(QByteArray("string")), 0);
+ QCOMPARE(propertyNames.count(QByteArray("size")), 0);
+ QCOMPARE(propertyNames.count(QByteArray("null")), 0);
+}
+
+void tst_QVideoSurfaceFormat::compare()
+{
+ QVideoSurfaceFormat format1(
+ QSize(16, 16), QVideoFrame::Format_RGB32, QAbstractVideoBuffer::GLTextureHandle);
+ QVideoSurfaceFormat format2(
+ QSize(16, 16), QVideoFrame::Format_RGB32, QAbstractVideoBuffer::GLTextureHandle);
+ QVideoSurfaceFormat format3(
+ QSize(32, 32), QVideoFrame::Format_YUV444, QAbstractVideoBuffer::GLTextureHandle);
+ QVideoSurfaceFormat format4(
+ QSize(16, 16), QVideoFrame::Format_RGB32, QAbstractVideoBuffer::UserHandle);
+
+ QCOMPARE(format1 == format2, true);
+ QCOMPARE(format1 != format2, false);
+ QCOMPARE(format1 == format3, false);
+ QCOMPARE(format1 != format3, true);
+ QCOMPARE(format1 == format4, false);
+ QCOMPARE(format1 != format4, true);
+
+ format2.setFrameSize(1024, 768);
+
+ // Not equal, frame size differs.
+ QCOMPARE(format1 == format2, false);
+ QCOMPARE(format1 != format2, true);
+
+ format1.setFrameSize(1024, 768);
+
+ // Equal.
+ QCOMPARE(format1 == format2, true);
+ QCOMPARE(format1 != format2, false);
+
+ format1.setViewport(QRect(0, 0, 800, 600));
+ format2.setViewport(QRect(112, 84, 800, 600));
+
+ // Not equal, viewports differ.
+ QCOMPARE(format1 == format2, false);
+ QCOMPARE(format1 != format2, true);
+
+ format1.setViewport(QRect(112, 84, 800, 600));
+
+ // Equal.
+ QCOMPARE(format1 == format2, true);
+ QCOMPARE(format1 != format2, false);
+
+ format2.setScanLineDirection(QVideoSurfaceFormat::BottomToTop);
+
+ // Not equal scan line direction differs.
+ QCOMPARE(format1 == format2, false);
+ QCOMPARE(format1 != format2, true);
+
+ format1.setScanLineDirection(QVideoSurfaceFormat::BottomToTop);
+
+ // Equal.
+ QCOMPARE(format1 == format2, true);
+ QCOMPARE(format1 != format2, false);
+
+ format1.setFrameRate(7.5);
+
+ // Not equal frame rate differs.
+ QCOMPARE(format1 == format2, false);
+ QCOMPARE(format1 != format2, true);
+
+ format2.setFrameRate(qreal(7.50001));
+
+ // Equal.
+ QCOMPARE(format1 == format2, true);
+ QCOMPARE(format1 != format2, false);
+
+ format2.setPixelAspectRatio(4, 3);
+
+ // Not equal pixel aspect ratio differs.
+ QCOMPARE(format1 == format2, false);
+ QCOMPARE(format1 != format2, true);
+
+ format1.setPixelAspectRatio(QSize(4, 3));
+
+ // Equal.
+ QCOMPARE(format1 == format2, true);
+ QCOMPARE(format1 != format2, false);
+
+ format2.setYCbCrColorSpace(QVideoSurfaceFormat::YCbCr_xvYCC601);
+
+ // Not equal yuv color space differs.
+ QCOMPARE(format1 == format2, false);
+ QCOMPARE(format1 != format2, true);
+
+ format1.setYCbCrColorSpace(QVideoSurfaceFormat::YCbCr_xvYCC601);
+
+ // Equal.
+ QCOMPARE(format1 == format2, true);
+ QCOMPARE(format1 != format2, false);
+
+ format1.setProperty("integer", 12);
+
+ // Not equal, property mismatch.
+ QCOMPARE(format1 == format2, false);
+ QCOMPARE(format1 != format2, true);
+
+ format2.setProperty("integer", 45);
+
+ // Not equal, integer differs.
+ QCOMPARE(format1 == format2, false);
+ QCOMPARE(format1 != format2, true);
+
+ format2.setProperty("integer", 12);
+
+ // Equal.
+ QCOMPARE(format1 == format2, true);
+ QCOMPARE(format1 != format2, false);
+
+ format1.setProperty("string", QString::fromLatin1("Hello"));
+ format2.setProperty("size", QSize(12, 54));
+
+ // Not equal, property mismatch.
+ QCOMPARE(format1 == format2, false);
+ QCOMPARE(format1 != format2, true);
+
+ format2.setProperty("string", QString::fromLatin1("Hello"));
+ format1.setProperty("size", QSize(12, 54));
+
+ // Equal.
+ QCOMPARE(format1 == format2, true);
+ QCOMPARE(format1 != format2, false);
+
+ format1.setProperty("string", QVariant());
+
+ // Not equal, property mismatch.
+ QCOMPARE(format1 == format2, false);
+ QCOMPARE(format1 != format2, true);
+}
+
+
+void tst_QVideoSurfaceFormat::copy()
+{
+ QVideoSurfaceFormat original(
+ QSize(1024, 768), QVideoFrame::Format_ARGB32, QAbstractVideoBuffer::GLTextureHandle);
+ original.setScanLineDirection(QVideoSurfaceFormat::BottomToTop);
+
+ QVideoSurfaceFormat copy(original);
+
+ QCOMPARE(copy.handleType(), QAbstractVideoBuffer::GLTextureHandle);
+ QCOMPARE(copy.pixelFormat(), QVideoFrame::Format_ARGB32);
+ QCOMPARE(copy.frameSize(), QSize(1024, 768));
+ QCOMPARE(copy.scanLineDirection(), QVideoSurfaceFormat::BottomToTop);
+
+ QCOMPARE(original == copy, true);
+ QCOMPARE(original != copy, false);
+
+ copy.setScanLineDirection(QVideoSurfaceFormat::TopToBottom);
+
+ QCOMPARE(copy.scanLineDirection(), QVideoSurfaceFormat::TopToBottom);
+
+ QCOMPARE(original.scanLineDirection(), QVideoSurfaceFormat::BottomToTop);
+
+ QCOMPARE(original == copy, false);
+ QCOMPARE(original != copy, true);
+}
+
+void tst_QVideoSurfaceFormat::assign()
+{
+ QVideoSurfaceFormat copy(
+ QSize(64, 64), QVideoFrame::Format_AYUV444, QAbstractVideoBuffer::UserHandle);
+
+ QVideoSurfaceFormat original(
+ QSize(1024, 768), QVideoFrame::Format_ARGB32, QAbstractVideoBuffer::GLTextureHandle);
+ original.setScanLineDirection(QVideoSurfaceFormat::BottomToTop);
+
+ copy = original;
+
+ QCOMPARE(copy.handleType(), QAbstractVideoBuffer::GLTextureHandle);
+ QCOMPARE(copy.pixelFormat(), QVideoFrame::Format_ARGB32);
+ QCOMPARE(copy.frameSize(), QSize(1024, 768));
+ QCOMPARE(copy.scanLineDirection(), QVideoSurfaceFormat::BottomToTop);
+
+ QCOMPARE(original == copy, true);
+ QCOMPARE(original != copy, false);
+
+ copy.setScanLineDirection(QVideoSurfaceFormat::TopToBottom);
+
+ QCOMPARE(copy.scanLineDirection(), QVideoSurfaceFormat::TopToBottom);
+
+ QCOMPARE(original.scanLineDirection(), QVideoSurfaceFormat::BottomToTop);
+
+ QCOMPARE(original == copy, false);
+ QCOMPARE(original != copy, true);
+}
+
+QTEST_MAIN(tst_QVideoSurfaceFormat)
+
+#include "tst_qvideosurfaceformat.moc"
diff --git a/tests/auto/qvideowidget/qvideowidget.pro b/tests/auto/qvideowidget/qvideowidget.pro
new file mode 100644
index 000000000..07fd03a02
--- /dev/null
+++ b/tests/auto/qvideowidget/qvideowidget.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+
+QT += multimediakit-private
+
+# TARGET = tst_qvideowidget
+# CONFIG += testcase
+
+SOURCES += tst_qvideowidget.cpp
+
+maemo*:CONFIG += insignificant_test
diff --git a/tests/auto/qvideowidget/tst_qvideowidget.cpp b/tests/auto/qvideowidget/tst_qvideowidget.cpp
new file mode 100644
index 000000000..3c5e1c6c6
--- /dev/null
+++ b/tests/auto/qvideowidget/tst_qvideowidget.cpp
@@ -0,0 +1,1567 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//TESTED_COMPONENT=src/multimedia
+
+#include <qmobilityglobal.h>
+#include <QtTest/QtTest>
+
+#include "qvideowidget.h"
+
+#include "qmediaobject.h"
+#include "qmediaservice.h"
+#include <private/qpaintervideosurface_p.h>
+#include "qvideowindowcontrol.h"
+#include "qvideowidgetcontrol.h"
+
+#include "qvideorenderercontrol.h"
+#include <qabstractvideosurface.h>
+#include <qvideosurfaceformat.h>
+
+#include <QtGui/qapplication.h>
+
+QT_USE_NAMESPACE
+class tst_QVideoWidget : public QObject
+{
+ Q_OBJECT
+private slots:
+ void nullObject();
+ void nullService();
+ void noOutputs();
+ void serviceDestroyed();
+ void objectDestroyed();
+ void setMediaObject();
+
+ void showWindowControl();
+ void fullScreenWindowControl();
+ void aspectRatioWindowControl();
+ void sizeHintWindowControl_data() { sizeHint_data(); }
+ void sizeHintWindowControl();
+ void brightnessWindowControl_data() { color_data(); }
+ void brightnessWindowControl();
+ void contrastWindowControl_data() { color_data(); }
+ void contrastWindowControl();
+ void hueWindowControl_data() { color_data(); }
+ void hueWindowControl();
+ void saturationWindowControl_data() { color_data(); }
+ void saturationWindowControl();
+
+ void showWidgetControl();
+ void fullScreenWidgetControl();
+ void aspectRatioWidgetControl();
+ void sizeHintWidgetControl_data() { sizeHint_data(); }
+ void sizeHintWidgetControl();
+ void brightnessWidgetControl_data() { color_data(); }
+ void brightnessWidgetControl();
+ void contrastWidgetControl_data() { color_data(); }
+ void contrastWidgetControl();
+ void hueWidgetControl_data() { color_data(); }
+ void hueWidgetControl();
+ void saturationWidgetControl_data() { color_data(); }
+ void saturationWidgetControl();
+
+ void showRendererControl();
+ void fullScreenRendererControl();
+ void aspectRatioRendererControl();
+ void sizeHintRendererControl_data();
+ void sizeHintRendererControl();
+ void brightnessRendererControl_data() { color_data(); }
+ void brightnessRendererControl();
+ void contrastRendererControl_data() { color_data(); }
+ void contrastRendererControl();
+ void hueRendererControl_data() { color_data(); }
+ void hueRendererControl();
+ void saturationRendererControl_data() { color_data(); }
+ void saturationRendererControl();
+
+ void paintRendererControl();
+
+private:
+ void sizeHint_data();
+ void color_data();
+};
+
+Q_DECLARE_METATYPE(Qt::AspectRatioMode)
+Q_DECLARE_METATYPE(const uchar *)
+
+class QtTestWindowControl : public QVideoWindowControl
+{
+public:
+ QtTestWindowControl()
+ : m_winId(0)
+ , m_repaintCount(0)
+ , m_brightness(0)
+ , m_contrast(0)
+ , m_saturation(0)
+ , m_aspectRatioMode(Qt::KeepAspectRatio)
+ , m_fullScreen(0)
+ {
+ }
+
+ WId winId() const { return m_winId; }
+ void setWinId(WId id) { m_winId = id; }
+
+ QRect displayRect() const { return m_displayRect; }
+ void setDisplayRect(const QRect &rect) { m_displayRect = rect; }
+
+ bool isFullScreen() const { return m_fullScreen; }
+ void setFullScreen(bool fullScreen) { emit fullScreenChanged(m_fullScreen = fullScreen); }
+
+ int repaintCount() const { return m_repaintCount; }
+ void setRepaintCount(int count) { m_repaintCount = count; }
+ void repaint() { ++m_repaintCount; }
+
+ QSize nativeSize() const { return m_nativeSize; }
+ void setNativeSize(const QSize &size) { m_nativeSize = size; emit nativeSizeChanged(); }
+
+ Qt::AspectRatioMode aspectRatioMode() const { return m_aspectRatioMode; }
+ void setAspectRatioMode(Qt::AspectRatioMode mode) { m_aspectRatioMode = mode; }
+
+ int brightness() const { return m_brightness; }
+ void setBrightness(int brightness) { emit brightnessChanged(m_brightness = brightness); }
+
+ int contrast() const { return m_contrast; }
+ void setContrast(int contrast) { emit contrastChanged(m_contrast = contrast); }
+
+ int hue() const { return m_hue; }
+ void setHue(int hue) { emit hueChanged(m_hue = hue); }
+
+ int saturation() const { return m_saturation; }
+ void setSaturation(int saturation) { emit saturationChanged(m_saturation = saturation); }
+
+private:
+ WId m_winId;
+ int m_repaintCount;
+ int m_brightness;
+ int m_contrast;
+ int m_hue;
+ int m_saturation;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QRect m_displayRect;
+ QSize m_nativeSize;
+ bool m_fullScreen;
+};
+
+class QtTestWidgetControl : public QVideoWidgetControl
+{
+public:
+ QtTestWidgetControl()
+ : m_brightness(1.0)
+ , m_contrast(1.0)
+ , m_hue(1.0)
+ , m_saturation(1.0)
+ , m_aspectRatioMode(Qt::KeepAspectRatio)
+ , m_fullScreen(false)
+ {
+ }
+
+ bool isFullScreen() const { return m_fullScreen; }
+ void setFullScreen(bool fullScreen) { emit fullScreenChanged(m_fullScreen = fullScreen); }
+
+ Qt::AspectRatioMode aspectRatioMode() const { return m_aspectRatioMode; }
+ void setAspectRatioMode(Qt::AspectRatioMode mode) { m_aspectRatioMode = mode; }
+
+ int brightness() const { return m_brightness; }
+ void setBrightness(int brightness) { emit brightnessChanged(m_brightness = brightness); }
+
+ int contrast() const { return m_contrast; }
+ void setContrast(int contrast) { emit contrastChanged(m_contrast = contrast); }
+
+ int hue() const { return m_hue; }
+ void setHue(int hue) { emit hueChanged(m_hue = hue); }
+
+ int saturation() const { return m_saturation; }
+ void setSaturation(int saturation) { emit saturationChanged(m_saturation = saturation); }
+
+ void setSizeHint(const QSize &size) { m_widget.setSizeHint(size); }
+
+ QWidget *videoWidget() { return &m_widget; }
+
+private:
+ class Widget : public QWidget
+ {
+ public:
+ QSize sizeHint() const { return m_sizeHint; }
+ void setSizeHint(const QSize &size) { m_sizeHint = size; updateGeometry(); }
+ private:
+ QSize m_sizeHint;
+ } m_widget;
+ int m_brightness;
+ int m_contrast;
+ int m_hue;
+ int m_saturation;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QSize m_sizeHint;
+ bool m_fullScreen;
+};
+
+class QtTestRendererControl : public QVideoRendererControl
+{
+public:
+ QtTestRendererControl()
+ : m_surface(0)
+ {
+ }
+
+ QAbstractVideoSurface *surface() const { return m_surface; }
+ void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; }
+
+private:
+ QAbstractVideoSurface *m_surface;
+};
+
+class QtTestVideoService : public QMediaService
+{
+ Q_OBJECT
+public:
+ QtTestVideoService(
+ QtTestWindowControl *window,
+ QtTestWidgetControl *widget,
+ QtTestRendererControl *renderer)
+ : QMediaService(0)
+ , windowRef(0)
+ , widgetRef(0)
+ , rendererRef(0)
+ , windowControl(window)
+ , widgetControl(widget)
+ , rendererControl(renderer)
+ {
+ }
+
+ ~QtTestVideoService()
+ {
+ delete windowControl;
+ delete widgetControl;
+ delete rendererControl;
+ }
+
+ QMediaControl *requestControl(const char *name)
+ {
+ if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
+ if (windowControl) {
+ windowRef += 1;
+
+ return windowControl;
+ }
+ } else if (qstrcmp(name, QVideoWidgetControl_iid) == 0) {
+ if (widgetControl) {
+ widgetRef += 1;
+
+ return widgetControl;
+ }
+ } else if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+ if (rendererControl) {
+ rendererRef += 1;
+
+ return rendererControl;
+ }
+ }
+ return 0;
+ }
+
+ void releaseControl(QMediaControl *control)
+ {
+ Q_ASSERT(control);
+
+ if (control == windowControl)
+ windowRef -= 1;
+ else if (control == widgetControl)
+ widgetRef -= 1;
+ else if (control == rendererControl)
+ rendererRef -= 1;
+ }
+
+ int windowRef;
+ int widgetRef;
+ int rendererRef;
+
+ QtTestWindowControl *windowControl;
+ QtTestWidgetControl *widgetControl;
+ QtTestRendererControl *rendererControl;
+};
+
+class QtTestVideoObject : public QMediaObject
+{
+ Q_OBJECT
+public:
+ QtTestVideoObject(
+ QtTestWindowControl *window,
+ QtTestWidgetControl *widget,
+ QtTestRendererControl *renderer):
+ QMediaObject(0, new QtTestVideoService(window, widget, renderer))
+ {
+ testService = qobject_cast<QtTestVideoService*>(service());
+ }
+
+ QtTestVideoObject(QtTestVideoService *service):
+ QMediaObject(0, service),
+ testService(service)
+ {
+ }
+
+ ~QtTestVideoObject()
+ {
+ delete testService;
+ }
+
+ QtTestVideoService *testService;
+};
+
+void tst_QVideoWidget::nullObject()
+{
+ QVideoWidget widget;
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ QVERIFY(widget.sizeHint().isEmpty());
+
+ widget.setFullScreen(true);
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.isFullScreen(), true);
+
+ widget.setAspectRatioMode(Qt::IgnoreAspectRatio);
+ QCOMPARE(widget.aspectRatioMode(), Qt::IgnoreAspectRatio);
+
+ {
+ QSignalSpy spy(&widget, SIGNAL(brightnessChanged(int)));
+
+ widget.setBrightness(100);
+ QCOMPARE(widget.brightness(), 100);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), 100);
+
+ widget.setBrightness(100);
+ QCOMPARE(widget.brightness(), 100);
+ QCOMPARE(spy.count(), 1);
+
+ widget.setBrightness(-120);
+ QCOMPARE(widget.brightness(), -100);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toInt(), -100);
+ } {
+ QSignalSpy spy(&widget, SIGNAL(contrastChanged(int)));
+
+ widget.setContrast(100);
+ QCOMPARE(widget.contrast(), 100);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), 100);
+
+ widget.setContrast(100);
+ QCOMPARE(widget.contrast(), 100);
+ QCOMPARE(spy.count(), 1);
+
+ widget.setContrast(-120);
+ QCOMPARE(widget.contrast(), -100);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toInt(), -100);
+ } {
+ QSignalSpy spy(&widget, SIGNAL(hueChanged(int)));
+
+ widget.setHue(100);
+ QCOMPARE(widget.hue(), 100);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), 100);
+
+ widget.setHue(100);
+ QCOMPARE(widget.hue(), 100);
+ QCOMPARE(spy.count(), 1);
+
+ widget.setHue(-120);
+ QCOMPARE(widget.hue(), -100);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toInt(), -100);
+ } {
+ QSignalSpy spy(&widget, SIGNAL(saturationChanged(int)));
+
+ widget.setSaturation(100);
+ QCOMPARE(widget.saturation(), 100);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), 100);
+
+ widget.setSaturation(100);
+ QCOMPARE(widget.saturation(), 100);
+ QCOMPARE(spy.count(), 1);
+
+ widget.setSaturation(-120);
+ QCOMPARE(widget.saturation(), -100);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toInt(), -100);
+ }
+}
+
+void tst_QVideoWidget::nullService()
+{
+ QtTestVideoObject object(0);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ QVERIFY(widget.sizeHint().isEmpty());
+
+ widget.setFullScreen(true);
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.isFullScreen(), true);
+
+ widget.setAspectRatioMode(Qt::IgnoreAspectRatio);
+ QCOMPARE(widget.aspectRatioMode(), Qt::IgnoreAspectRatio);
+
+ widget.setBrightness(100);
+ QCOMPARE(widget.brightness(), 100);
+
+ widget.setContrast(100);
+ QCOMPARE(widget.contrast(), 100);
+
+ widget.setHue(100);
+ QCOMPARE(widget.hue(), 100);
+
+ widget.setSaturation(100);
+ QCOMPARE(widget.saturation(), 100);
+}
+
+void tst_QVideoWidget::noOutputs()
+{
+ QtTestVideoObject object(0, 0, 0);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ QVERIFY(widget.sizeHint().isEmpty());
+
+ widget.setFullScreen(true);
+ QCOMPARE(widget.isFullScreen(), true);
+
+ widget.setBrightness(100);
+ QCOMPARE(widget.brightness(), 100);
+
+ widget.setContrast(100);
+ QCOMPARE(widget.contrast(), 100);
+
+ widget.setHue(100);
+ QCOMPARE(widget.hue(), 100);
+
+ widget.setSaturation(100);
+ QCOMPARE(widget.saturation(), 100);
+}
+
+void tst_QVideoWidget::serviceDestroyed()
+{
+ QtTestVideoObject object(new QtTestWindowControl, new QtTestWidgetControl, 0);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ widget.setBrightness(100);
+ widget.setContrast(100);
+ widget.setHue(100);
+ widget.setSaturation(100);
+
+ delete object.testService;
+ object.testService = 0;
+
+ QCOMPARE(widget.mediaObject(), static_cast<QMediaObject *>(&object));
+
+ QCOMPARE(widget.brightness(), 100);
+ QCOMPARE(widget.contrast(), 100);
+ QCOMPARE(widget.hue(), 100);
+ QCOMPARE(widget.saturation(), 100);
+
+ widget.setFullScreen(true);
+ QCOMPARE(widget.isFullScreen(), true);
+}
+
+void tst_QVideoWidget::objectDestroyed()
+{
+ QtTestVideoObject *object = new QtTestVideoObject(
+ new QtTestWindowControl,
+ new QtTestWidgetControl,
+ 0);
+
+ QVideoWidget widget;
+ object->bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ QCOMPARE(object->testService->windowRef, 0);
+ QCOMPARE(object->testService->widgetRef, 1);
+ QCOMPARE(object->testService->rendererRef, 0);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ widget.setBrightness(100);
+ widget.setContrast(100);
+ widget.setHue(100);
+ widget.setSaturation(100);
+
+ // Delete the media object without deleting the service.
+ QtTestVideoService *service = object->testService;
+ object->testService = 0;
+
+ delete object;
+ object = 0;
+
+ QCOMPARE(widget.mediaObject(), static_cast<QMediaObject *>(object));
+
+ QCOMPARE(widget.brightness(), 100);
+ QCOMPARE(widget.contrast(), 100);
+ QCOMPARE(widget.hue(), 100);
+ QCOMPARE(widget.saturation(), 100);
+
+ widget.setFullScreen(true);
+ QCOMPARE(widget.isFullScreen(), true);
+
+ delete service;
+}
+
+void tst_QVideoWidget::setMediaObject()
+{
+ QMediaObject *nullObject = 0;
+ QtTestVideoObject windowObject(new QtTestWindowControl, 0, 0);
+ QtTestVideoObject widgetObject(0, new QtTestWidgetControl, 0);
+ QtTestVideoObject rendererObject(0, 0, new QtTestRendererControl);
+
+ QVideoWidget widget;
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ QCOMPARE(widget.mediaObject(), nullObject);
+ QCOMPARE(windowObject.testService->windowRef, 0);
+ QCOMPARE(widgetObject.testService->widgetRef, 0);
+ QCOMPARE(rendererObject.testService->rendererRef, 0);
+
+ windowObject.bind(&widget);
+ QCOMPARE(widget.mediaObject(), static_cast<QMediaObject *>(&windowObject));
+ QCOMPARE(windowObject.testService->windowRef, 1);
+ QCOMPARE(widgetObject.testService->widgetRef, 0);
+ QCOMPARE(rendererObject.testService->rendererRef, 0);
+ QVERIFY(windowObject.testService->windowControl->winId() != 0);
+
+
+ widgetObject.bind(&widget);
+ QCOMPARE(widget.mediaObject(), static_cast<QMediaObject *>(&widgetObject));
+ QCOMPARE(windowObject.testService->windowRef, 0);
+ QCOMPARE(widgetObject.testService->widgetRef, 1);
+ QCOMPARE(rendererObject.testService->rendererRef, 0);
+
+ QCoreApplication::processEvents(QEventLoop::AllEvents);
+ QCOMPARE(widgetObject.testService->widgetControl->videoWidget()->isVisible(), true);
+
+ QCOMPARE(windowObject.testService->windowRef, 0);
+ QCOMPARE(widgetObject.testService->widgetRef, 1);
+ QCOMPARE(rendererObject.testService->rendererRef, 0);
+
+ rendererObject.bind(&widget);
+ QCOMPARE(widget.mediaObject(), static_cast<QMediaObject *>(&rendererObject));
+
+ QCOMPARE(windowObject.testService->windowRef, 0);
+ QCOMPARE(widgetObject.testService->widgetRef, 0);
+ QCOMPARE(rendererObject.testService->rendererRef, 1);
+ QVERIFY(rendererObject.testService->rendererControl->surface() != 0);
+
+ rendererObject.unbind(&widget);
+ QCOMPARE(widget.mediaObject(), nullObject);
+
+ QCOMPARE(windowObject.testService->windowRef, 0);
+ QCOMPARE(widgetObject.testService->widgetRef, 0);
+ QCOMPARE(rendererObject.testService->rendererRef, 0);
+}
+
+void tst_QVideoWidget::showWindowControl()
+{
+ QtTestVideoObject object(new QtTestWindowControl, 0, 0);
+ object.testService->windowControl->setNativeSize(QSize(240, 180));
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ QVERIFY(object.testService->windowControl->winId() != 0);
+ QVERIFY(object.testService->windowControl->repaintCount() > 0);
+
+ widget.resize(640, 480);
+ QCOMPARE(object.testService->windowControl->displayRect(), QRect(0, 0, 640, 480));
+
+ widget.move(10, 10);
+ QCOMPARE(object.testService->windowControl->displayRect(), QRect(0, 0, 640, 480));
+
+ widget.hide();
+}
+
+void tst_QVideoWidget::showWidgetControl()
+{
+ QtTestVideoObject object(0, new QtTestWidgetControl, 0);
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(object.testService->widgetControl->videoWidget()->isVisible(), true);
+
+ widget.resize(640, 480);
+
+ widget.move(10, 10);
+
+ widget.hide();
+
+ QCOMPARE(object.testService->widgetControl->videoWidget()->isVisible(), false);
+}
+
+void tst_QVideoWidget::showRendererControl()
+{
+ QtTestVideoObject object(0, 0, new QtTestRendererControl);
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ QVERIFY(object.testService->rendererControl->surface() != 0);
+
+ widget.resize(640, 480);
+
+ widget.move(10, 10);
+
+ widget.hide();
+}
+
+void tst_QVideoWidget::aspectRatioWindowControl()
+{
+ QtTestVideoObject object(new QtTestWindowControl, 0, 0);
+ object.testService->windowControl->setAspectRatioMode(Qt::IgnoreAspectRatio);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ // Test the aspect ratio defaults to keeping the aspect ratio.
+ QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio);
+
+ // Test the control has been informed of the aspect ratio change, post show.
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio);
+ QCOMPARE(object.testService->windowControl->aspectRatioMode(), Qt::KeepAspectRatio);
+
+ // Test an aspect ratio change is enforced immediately while visible.
+ widget.setAspectRatioMode(Qt::IgnoreAspectRatio);
+ QCOMPARE(widget.aspectRatioMode(), Qt::IgnoreAspectRatio);
+ QCOMPARE(object.testService->windowControl->aspectRatioMode(), Qt::IgnoreAspectRatio);
+
+ // Test an aspect ratio set while not visible is respected.
+ widget.hide();
+ widget.setAspectRatioMode(Qt::KeepAspectRatio);
+ QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio);
+ widget.show();
+ QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio);
+ QCOMPARE(object.testService->windowControl->aspectRatioMode(), Qt::KeepAspectRatio);
+}
+
+void tst_QVideoWidget::aspectRatioWidgetControl()
+{
+ QtTestVideoObject object(0, new QtTestWidgetControl, 0);
+ object.testService->widgetControl->setAspectRatioMode(Qt::IgnoreAspectRatio);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ // Test the aspect ratio defaults to keeping the aspect ratio.
+ QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio);
+
+ // Test the control has been informed of the aspect ratio change, post show.
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio);
+ QCOMPARE(object.testService->widgetControl->aspectRatioMode(), Qt::KeepAspectRatio);
+
+ // Test an aspect ratio change is enforced immediately while visible.
+ widget.setAspectRatioMode(Qt::IgnoreAspectRatio);
+ QCOMPARE(widget.aspectRatioMode(), Qt::IgnoreAspectRatio);
+ QCOMPARE(object.testService->widgetControl->aspectRatioMode(), Qt::IgnoreAspectRatio);
+
+ // Test an aspect ratio set while not visible is respected.
+ widget.hide();
+ widget.setAspectRatioMode(Qt::KeepAspectRatio);
+ QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio);
+ widget.show();
+ QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio);
+ QCOMPARE(object.testService->widgetControl->aspectRatioMode(), Qt::KeepAspectRatio);
+}
+
+void tst_QVideoWidget::aspectRatioRendererControl()
+{
+ QtTestVideoObject object(0, 0, new QtTestRendererControl);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ // Test the aspect ratio defaults to keeping the aspect ratio.
+ QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio);
+
+ // Test the control has been informed of the aspect ratio change, post show.
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio);
+
+ // Test an aspect ratio change is enforced immediately while visible.
+ widget.setAspectRatioMode(Qt::IgnoreAspectRatio);
+ QCOMPARE(widget.aspectRatioMode(), Qt::IgnoreAspectRatio);
+
+ // Test an aspect ratio set while not visible is respected.
+ widget.hide();
+ widget.setAspectRatioMode(Qt::KeepAspectRatio);
+ QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio);
+ widget.show();
+ QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio);
+}
+
+void tst_QVideoWidget::sizeHint_data()
+{
+ QTest::addColumn<QSize>("size");
+
+ QTest::newRow("720x576")
+ << QSize(720, 576);
+}
+
+void tst_QVideoWidget::sizeHintWindowControl()
+{
+ QFETCH(QSize, size);
+
+ QtTestVideoObject object(new QtTestWindowControl, 0, 0);
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ QVERIFY(widget.sizeHint().isEmpty());
+
+ object.testService->windowControl->setNativeSize(size);
+ QCOMPARE(widget.sizeHint(), size);
+}
+
+void tst_QVideoWidget::sizeHintWidgetControl()
+{
+ QFETCH(QSize, size);
+
+ QtTestVideoObject object(0, new QtTestWidgetControl, 0);
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ QVERIFY(widget.sizeHint().isEmpty());
+
+ object.testService->widgetControl->setSizeHint(size);
+ QCOMPARE(widget.sizeHint(), size);
+}
+
+void tst_QVideoWidget::sizeHintRendererControl_data()
+{
+ QTest::addColumn<QSize>("frameSize");
+ QTest::addColumn<QRect>("viewport");
+ QTest::addColumn<QSize>("pixelAspectRatio");
+ QTest::addColumn<QSize>("expectedSize");
+
+ QTest::newRow("640x480")
+ << QSize(640, 480)
+ << QRect(0, 0, 640, 480)
+ << QSize(1, 1)
+ << QSize(640, 480);
+
+ QTest::newRow("800x600, (80,60, 640x480) viewport")
+ << QSize(800, 600)
+ << QRect(80, 60, 640, 480)
+ << QSize(1, 1)
+ << QSize(640, 480);
+
+ QTest::newRow("800x600, (80,60, 640x480) viewport, 4:3")
+ << QSize(800, 600)
+ << QRect(80, 60, 640, 480)
+ << QSize(4, 3)
+ << QSize(853, 480);
+
+}
+
+void tst_QVideoWidget::sizeHintRendererControl()
+{
+ QFETCH(QSize, frameSize);
+ QFETCH(QRect, viewport);
+ QFETCH(QSize, pixelAspectRatio);
+ QFETCH(QSize, expectedSize);
+
+ QtTestVideoObject object(0, 0, new QtTestRendererControl);
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_ARGB32);
+ format.setViewport(viewport);
+ format.setPixelAspectRatio(pixelAspectRatio);
+
+ QVERIFY(object.testService->rendererControl->surface()->start(format));
+
+ QCOMPARE(widget.sizeHint(), expectedSize);
+}
+
+
+void tst_QVideoWidget::fullScreenWindowControl()
+{
+ QtTestVideoObject object(new QtTestWindowControl, 0, 0);
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ Qt::WindowFlags windowFlags = widget.windowFlags();
+
+ QSignalSpy spy(&widget, SIGNAL(fullScreenChanged(bool)));
+
+ // Test showing full screen with setFullScreen(true).
+ widget.setFullScreen(true);
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(object.testService->windowControl->isFullScreen(), true);
+ QCOMPARE(widget.isFullScreen(), true);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toBool(), true);
+
+ // Test returning to normal with setFullScreen(false).
+ widget.setFullScreen(false);
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(object.testService->windowControl->isFullScreen(), false);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toBool(), false);
+ QCOMPARE(widget.windowFlags(), windowFlags);
+
+ // Test showing full screen with showFullScreen().
+ widget.showFullScreen();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(object.testService->windowControl->isFullScreen(), true);
+ QCOMPARE(widget.isFullScreen(), true);
+ QCOMPARE(spy.count(), 3);
+ QCOMPARE(spy.value(2).value(0).toBool(), true);
+
+ // Test returning to normal with showNormal().
+ widget.showNormal();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(object.testService->windowControl->isFullScreen(), false);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 4);
+ QCOMPARE(spy.value(3).value(0).toBool(), false);
+ QCOMPARE(widget.windowFlags(), windowFlags);
+
+ // Test setFullScreen(false) and showNormal() do nothing when isFullScreen() == false.
+ widget.setFullScreen(false);
+ QCOMPARE(object.testService->windowControl->isFullScreen(), false);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 4);
+ widget.showNormal();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(object.testService->windowControl->isFullScreen(), false);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 4);
+
+ // Test setFullScreen(true) and showFullScreen() do nothing when isFullScreen() == true.
+ widget.showFullScreen();
+ QTest::qWaitForWindowShown(&widget);
+ widget.setFullScreen(true);
+ QCOMPARE(object.testService->windowControl->isFullScreen(), true);
+ QCOMPARE(widget.isFullScreen(), true);
+ QCOMPARE(spy.count(), 5);
+ widget.showFullScreen();
+ QCOMPARE(object.testService->windowControl->isFullScreen(), true);
+ QCOMPARE(widget.isFullScreen(), true);
+ QCOMPARE(spy.count(), 5);
+
+ // Test if the window control exits full screen mode, the widget follows suit.
+ object.testService->windowControl->setFullScreen(false);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 6);
+ QCOMPARE(spy.value(5).value(0).toBool(), false);
+
+ // Test if the window control enters full screen mode, the widget does nothing.
+ object.testService->windowControl->setFullScreen(false);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 6);
+}
+
+void tst_QVideoWidget::fullScreenWidgetControl()
+{
+ QtTestVideoObject object(0, new QtTestWidgetControl, 0);
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ Qt::WindowFlags windowFlags = widget.windowFlags();
+
+ QSignalSpy spy(&widget, SIGNAL(fullScreenChanged(bool)));
+
+ // Test showing full screen with setFullScreen(true).
+ widget.setFullScreen(true);
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(object.testService->widgetControl->isFullScreen(), true);
+ QCOMPARE(widget.isFullScreen(), true);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toBool(), true);
+
+ // Test returning to normal with setFullScreen(false).
+ widget.setFullScreen(false);
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(object.testService->widgetControl->isFullScreen(), false);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toBool(), false);
+ QCOMPARE(widget.windowFlags(), windowFlags);
+
+ // Test showing full screen with showFullScreen().
+ widget.showFullScreen();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(object.testService->widgetControl->isFullScreen(), true);
+ QCOMPARE(widget.isFullScreen(), true);
+ QCOMPARE(spy.count(), 3);
+ QCOMPARE(spy.value(2).value(0).toBool(), true);
+
+ // Test returning to normal with showNormal().
+ widget.showNormal();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(object.testService->widgetControl->isFullScreen(), false);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 4);
+ QCOMPARE(spy.value(3).value(0).toBool(), false);
+ QCOMPARE(widget.windowFlags(), windowFlags);
+
+ // Test setFullScreen(false) and showNormal() do nothing when isFullScreen() == false.
+ widget.setFullScreen(false);
+ QCOMPARE(object.testService->widgetControl->isFullScreen(), false);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 4);
+ widget.showNormal();
+ QCOMPARE(object.testService->widgetControl->isFullScreen(), false);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 4);
+
+ // Test setFullScreen(true) and showFullScreen() do nothing when isFullScreen() == true.
+ widget.showFullScreen();
+ QTest::qWaitForWindowShown(&widget);
+ widget.setFullScreen(true);
+ QCOMPARE(object.testService->widgetControl->isFullScreen(), true);
+ QCOMPARE(widget.isFullScreen(), true);
+ QCOMPARE(spy.count(), 5);
+ widget.showFullScreen();
+ QCOMPARE(object.testService->widgetControl->isFullScreen(), true);
+ QCOMPARE(widget.isFullScreen(), true);
+ QCOMPARE(spy.count(), 5);
+
+ // Test if the window control exits full screen mode, the widget follows suit.
+ object.testService->widgetControl->setFullScreen(false);
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 6);
+ QCOMPARE(spy.value(5).value(0).toBool(), false);
+
+ // Test if the window control enters full screen mode, the widget does nothing.
+ object.testService->widgetControl->setFullScreen(false);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 6);
+}
+
+
+void tst_QVideoWidget::fullScreenRendererControl()
+{
+ QtTestVideoObject object(0, 0, new QtTestRendererControl);
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ Qt::WindowFlags windowFlags = widget.windowFlags();
+
+ QSignalSpy spy(&widget, SIGNAL(fullScreenChanged(bool)));
+
+ // Test showing full screen with setFullScreen(true).
+ widget.setFullScreen(true);
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.isFullScreen(), true);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toBool(), true);
+
+ // Test returning to normal with setFullScreen(false).
+ widget.setFullScreen(false);
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toBool(), false);
+ QCOMPARE(widget.windowFlags(), windowFlags);
+
+ // Test showing full screen with showFullScreen().
+ widget.showFullScreen();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.isFullScreen(), true);
+ QCOMPARE(spy.count(), 3);
+ QCOMPARE(spy.value(2).value(0).toBool(), true);
+
+ // Test returning to normal with showNormal().
+ widget.showNormal();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 4);
+ QCOMPARE(spy.value(3).value(0).toBool(), false);
+ QCOMPARE(widget.windowFlags(), windowFlags);
+
+ // Test setFullScreen(false) and showNormal() do nothing when isFullScreen() == false.
+ widget.setFullScreen(false);
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 4);
+ widget.showNormal();
+ QCOMPARE(widget.isFullScreen(), false);
+ QCOMPARE(spy.count(), 4);
+
+ // Test setFullScreen(true) and showFullScreen() do nothing when isFullScreen() == true.
+ widget.showFullScreen();
+ QTest::qWaitForWindowShown(&widget);
+ widget.setFullScreen(true);
+ QCOMPARE(widget.isFullScreen(), true);
+ QCOMPARE(spy.count(), 5);
+ widget.showFullScreen();
+ QCOMPARE(widget.isFullScreen(), true);
+ QCOMPARE(spy.count(), 5);
+}
+
+
+void tst_QVideoWidget::color_data()
+{
+ QTest::addColumn<int>("controlValue");
+ QTest::addColumn<int>("value");
+ QTest::addColumn<int>("expectedValue");
+
+ QTest::newRow("12")
+ << 0
+ << 12
+ << 12;
+ QTest::newRow("-56")
+ << 87
+ << -56
+ << -56;
+ QTest::newRow("100")
+ << 32
+ << 100
+ << 100;
+ QTest::newRow("1294")
+ << 0
+ << 1294
+ << 100;
+ QTest::newRow("-102")
+ << 34
+ << -102
+ << -100;
+}
+
+void tst_QVideoWidget::brightnessWindowControl()
+{
+ QFETCH(int, controlValue);
+ QFETCH(int, value);
+ QFETCH(int, expectedValue);
+
+ QtTestVideoObject object(new QtTestWindowControl, 0, 0);
+ object.testService->windowControl->setBrightness(controlValue);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ // Test the video widget resets the controls starting brightness to the default.
+ QCOMPARE(widget.brightness(), 0);
+
+ QSignalSpy spy(&widget, SIGNAL(brightnessChanged(int)));
+
+ // Test the video widget sets the brightness value, bounded if necessary and emits a changed
+ // signal.
+ widget.setBrightness(value);
+ QCOMPARE(widget.brightness(), expectedValue);
+ QCOMPARE(object.testService->windowControl->brightness(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), expectedValue);
+
+ // Test the changed signal isn't emitted if the value is unchanged.
+ widget.setBrightness(value);
+ QCOMPARE(widget.brightness(), expectedValue);
+ QCOMPARE(object.testService->windowControl->brightness(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+
+ // Test the changed signal is emitted if the brightness is changed internally.
+ object.testService->windowControl->setBrightness(controlValue);
+ QCOMPARE(widget.brightness(), controlValue);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toInt(), controlValue);
+}
+
+void tst_QVideoWidget::brightnessWidgetControl()
+{
+ QFETCH(int, controlValue);
+ QFETCH(int, value);
+ QFETCH(int, expectedValue);
+
+ QtTestVideoObject object(0, new QtTestWidgetControl, 0);
+ object.testService->widgetControl->setBrightness(controlValue);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ QCOMPARE(widget.brightness(), 0);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ QSignalSpy spy(&widget, SIGNAL(brightnessChanged(int)));
+
+ widget.setBrightness(value);
+ QCOMPARE(widget.brightness(), expectedValue);
+ QCOMPARE(object.testService->widgetControl->brightness(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), expectedValue);
+
+ widget.setBrightness(value);
+ QCOMPARE(widget.brightness(), expectedValue);
+ QCOMPARE(object.testService->widgetControl->brightness(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+
+ object.testService->widgetControl->setBrightness(controlValue);
+ QCOMPARE(widget.brightness(), controlValue);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toInt(), controlValue);
+}
+
+void tst_QVideoWidget::brightnessRendererControl()
+{
+ QFETCH(int, value);
+ QFETCH(int, expectedValue);
+
+ QtTestVideoObject object(0, 0, new QtTestRendererControl);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ QSignalSpy spy(&widget, SIGNAL(brightnessChanged(int)));
+
+ widget.setBrightness(value);
+ QCOMPARE(widget.brightness(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), expectedValue);
+
+ widget.setBrightness(value);
+ QCOMPARE(widget.brightness(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QVideoWidget::contrastWindowControl()
+{
+ QFETCH(int, controlValue);
+ QFETCH(int, value);
+ QFETCH(int, expectedValue);
+
+ QtTestVideoObject object(new QtTestWindowControl, 0, 0);
+ object.testService->windowControl->setContrast(controlValue);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ QCOMPARE(widget.contrast(), 0);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.contrast(), 0);
+
+ QSignalSpy spy(&widget, SIGNAL(contrastChanged(int)));
+
+ widget.setContrast(value);
+ QCOMPARE(widget.contrast(), expectedValue);
+ QCOMPARE(object.testService->windowControl->contrast(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), expectedValue);
+
+ widget.setContrast(value);
+ QCOMPARE(widget.contrast(), expectedValue);
+ QCOMPARE(object.testService->windowControl->contrast(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+
+ object.testService->windowControl->setContrast(controlValue);
+ QCOMPARE(widget.contrast(), controlValue);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toInt(), controlValue);
+}
+
+void tst_QVideoWidget::contrastWidgetControl()
+{
+ QFETCH(int, controlValue);
+ QFETCH(int, value);
+ QFETCH(int, expectedValue);
+
+ QtTestVideoObject object(0, new QtTestWidgetControl, 0);
+ object.testService->widgetControl->setContrast(controlValue);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ QCOMPARE(widget.contrast(), 0);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.contrast(), 0);
+
+ QSignalSpy spy(&widget, SIGNAL(contrastChanged(int)));
+
+ widget.setContrast(value);
+ QCOMPARE(widget.contrast(), expectedValue);
+ QCOMPARE(object.testService->widgetControl->contrast(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), expectedValue);
+
+ widget.setContrast(value);
+ QCOMPARE(widget.contrast(), expectedValue);
+ QCOMPARE(object.testService->widgetControl->contrast(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+
+ object.testService->widgetControl->setContrast(controlValue);
+ QCOMPARE(widget.contrast(), controlValue);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toInt(), controlValue);
+}
+
+void tst_QVideoWidget::contrastRendererControl()
+{
+ QFETCH(int, value);
+ QFETCH(int, expectedValue);
+
+ QtTestVideoObject object(0, 0, new QtTestRendererControl);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ QSignalSpy spy(&widget, SIGNAL(contrastChanged(int)));
+
+ widget.setContrast(value);
+ QCOMPARE(widget.contrast(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), expectedValue);
+
+ widget.setContrast(value);
+ QCOMPARE(widget.contrast(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QVideoWidget::hueWindowControl()
+{
+ QFETCH(int, controlValue);
+ QFETCH(int, value);
+ QFETCH(int, expectedValue);
+
+ QtTestVideoObject object(new QtTestWindowControl, 0, 0);
+ object.testService->windowControl->setHue(controlValue);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ QCOMPARE(widget.hue(), 0);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.hue(), 0);
+
+ QSignalSpy spy(&widget, SIGNAL(hueChanged(int)));
+
+ widget.setHue(value);
+ QCOMPARE(widget.hue(), expectedValue);
+ QCOMPARE(object.testService->windowControl->hue(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), expectedValue);
+
+ widget.setHue(value);
+ QCOMPARE(widget.hue(), expectedValue);
+ QCOMPARE(object.testService->windowControl->hue(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+
+ object.testService->windowControl->setHue(controlValue);
+ QCOMPARE(widget.hue(), controlValue);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toInt(), controlValue);
+}
+
+void tst_QVideoWidget::hueWidgetControl()
+{
+ QFETCH(int, controlValue);
+ QFETCH(int, value);
+ QFETCH(int, expectedValue);
+
+ QtTestVideoObject object(0, new QtTestWidgetControl, 0);
+ object.testService->widgetControl->setHue(controlValue);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ QCOMPARE(widget.hue(), 0);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.hue(), 0);
+
+ QSignalSpy spy(&widget, SIGNAL(hueChanged(int)));
+
+ widget.setHue(value);
+ QCOMPARE(widget.hue(), expectedValue);
+ QCOMPARE(object.testService->widgetControl->hue(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), expectedValue);
+
+ widget.setHue(value);
+ QCOMPARE(widget.hue(), expectedValue);
+ QCOMPARE(object.testService->widgetControl->hue(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+
+ object.testService->widgetControl->setHue(controlValue);
+ QCOMPARE(widget.hue(), controlValue);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toInt(), controlValue);
+}
+
+void tst_QVideoWidget::hueRendererControl()
+{
+ QFETCH(int, value);
+ QFETCH(int, expectedValue);
+
+ QtTestVideoObject object(0, 0, new QtTestRendererControl);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ QSignalSpy spy(&widget, SIGNAL(hueChanged(int)));
+
+ widget.setHue(value);
+ QCOMPARE(widget.hue(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), expectedValue);
+
+ widget.setHue(value);
+ QCOMPARE(widget.hue(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QVideoWidget::saturationWindowControl()
+{
+ QFETCH(int, controlValue);
+ QFETCH(int, value);
+ QFETCH(int, expectedValue);
+
+ QtTestVideoObject object(new QtTestWindowControl, 0, 0);
+ object.testService->windowControl->setSaturation(controlValue);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ QCOMPARE(widget.saturation(), 0);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.saturation(), 0);
+
+ QSignalSpy spy(&widget, SIGNAL(saturationChanged(int)));
+
+ widget.setSaturation(value);
+ QCOMPARE(widget.saturation(), expectedValue);
+ QCOMPARE(object.testService->windowControl->saturation(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), expectedValue);
+
+ widget.setSaturation(value);
+ QCOMPARE(widget.saturation(), expectedValue);
+ QCOMPARE(object.testService->windowControl->saturation(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+
+ object.testService->windowControl->setSaturation(controlValue);
+ QCOMPARE(widget.saturation(), controlValue);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toInt(), controlValue);
+}
+
+void tst_QVideoWidget::saturationWidgetControl()
+{
+ QFETCH(int, controlValue);
+ QFETCH(int, value);
+ QFETCH(int, expectedValue);
+
+ QtTestVideoObject object(0, new QtTestWidgetControl, 0);
+ object.testService->widgetControl->setSaturation(controlValue);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+
+ QCOMPARE(widget.saturation(), 0);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QCOMPARE(widget.saturation(), 0);
+
+ QSignalSpy spy(&widget, SIGNAL(saturationChanged(int)));
+
+ widget.setSaturation(value);
+ QCOMPARE(widget.saturation(), expectedValue);
+ QCOMPARE(object.testService->widgetControl->saturation(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), expectedValue);
+
+ widget.setSaturation(value);
+ QCOMPARE(widget.saturation(), expectedValue);
+ QCOMPARE(object.testService->widgetControl->saturation(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+
+ object.testService->widgetControl->setSaturation(controlValue);
+ QCOMPARE(widget.saturation(), controlValue);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.value(1).value(0).toInt(), controlValue);
+
+}
+
+void tst_QVideoWidget::saturationRendererControl()
+{
+ QFETCH(int, value);
+ QFETCH(int, expectedValue);
+
+ QtTestVideoObject object(0, 0, new QtTestRendererControl);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QSignalSpy spy(&widget, SIGNAL(saturationChanged(int)));
+
+ widget.setSaturation(value);
+ QCOMPARE(widget.saturation(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.value(0).value(0).toInt(), expectedValue);
+
+ widget.setSaturation(value);
+ QCOMPARE(widget.saturation(), expectedValue);
+ QCOMPARE(spy.count(), 1);
+}
+
+static const uchar rgb32ImageData[] =
+{
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00
+};
+
+void tst_QVideoWidget::paintRendererControl()
+{
+ QtTestVideoObject object(0, 0, new QtTestRendererControl);
+
+ QVideoWidget widget;
+ object.bind(&widget);
+ widget.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ widget.resize(640,480);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ QPainterVideoSurface *surface = qobject_cast<QPainterVideoSurface *>(
+ object.testService->rendererControl->surface());
+
+ QVideoSurfaceFormat format(QSize(2, 2), QVideoFrame::Format_RGB32);
+
+ QVERIFY(surface->start(format));
+ QCOMPARE(surface->isActive(), true);
+ QCOMPARE(surface->isReady(), true);
+
+ QCoreApplication::processEvents(QEventLoop::AllEvents);
+
+ QCOMPARE(surface->isActive(), true);
+ QCOMPARE(surface->isReady(), true);
+
+ QVideoFrame frame(sizeof(rgb32ImageData), QSize(2, 2), 8, QVideoFrame::Format_RGB32);
+
+ frame.map(QAbstractVideoBuffer::WriteOnly);
+ memcpy(frame.bits(), rgb32ImageData, frame.mappedBytes());
+ frame.unmap();
+
+ QVERIFY(surface->present(frame));
+ QCOMPARE(surface->isActive(), true);
+ QCOMPARE(surface->isReady(), false);
+
+ //wait up to 2 seconds for the frame to be presented
+ for (int i=0; i<200 && !surface->isReady(); i++)
+ QTest::qWait(10);
+
+ QCOMPARE(surface->isActive(), true);
+ QCOMPARE(surface->isReady(), true);
+}
+
+QTEST_MAIN(tst_QVideoWidget)
+
+#include "tst_qvideowidget.moc"
diff --git a/tests/tests.pro b/tests/tests.pro
new file mode 100644
index 000000000..2bd49bd97
--- /dev/null
+++ b/tests/tests.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+SUBDIRS += auto
+
+# Disabled since we don't have any source.
+# SUBDIRS += benchmarks manual