summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
725 files changed, 157687 insertions, 0 deletions
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
+}
+